{"id":49471678,"url":"https://github.com/dingo-actual/openrouter-python-client","last_synced_at":"2026-04-30T16:36:19.475Z","repository":{"id":294753934,"uuid":"981345553","full_name":"dingo-actual/openrouter-python-client","owner":"dingo-actual","description":"An unofficial Python client for OpenRouter","archived":false,"fork":false,"pushed_at":"2025-08-20T19:49:14.000Z","size":1095,"stargazers_count":4,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-30T16:36:12.931Z","etag":null,"topics":["ai","api-client","api-wrapper","client","large-language-models","llm","openrouter","python","python-client","streaming","unofficial"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dingo-actual.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-10T22:27:34.000Z","updated_at":"2025-09-25T14:17:14.000Z","dependencies_parsed_at":"2025-08-02T23:21:11.335Z","dependency_job_id":"e3aae988-8ce2-449e-845e-df589cccb2a1","html_url":"https://github.com/dingo-actual/openrouter-python-client","commit_stats":null,"previous_names":["dingo-actual/openrouter-python-client"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/dingo-actual/openrouter-python-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dingo-actual%2Fopenrouter-python-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dingo-actual%2Fopenrouter-python-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dingo-actual%2Fopenrouter-python-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dingo-actual%2Fopenrouter-python-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dingo-actual","download_url":"https://codeload.github.com/dingo-actual/openrouter-python-client/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dingo-actual%2Fopenrouter-python-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32470879,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"ssl_error","status_checked_at":"2026-04-30T13:12:06.837Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","api-client","api-wrapper","client","large-language-models","llm","openrouter","python","python-client","streaming","unofficial"],"created_at":"2026-04-30T16:36:18.870Z","updated_at":"2026-04-30T16:36:19.465Z","avatar_url":"https://github.com/dingo-actual.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenRouter Python Client (Unofficial)\n\n\u003cimg src=\"images/openrouter_client_logo.png\" alt=\"OpenRouter Client (Unofficial) Logo\" width=\"830\" height=\"415\"\u003e\n\u003cbr\u003e\n\nAn unofficial Python client for [OpenRouter](https://openrouter.ai/), providing a comprehensive interface for interacting with large language models through the OpenRouter API.\n\n## Features\n\n- **Full API Support (Almost)**: Access all major OpenRouter endpoints including chat completions, text completions, model information, generations, credits, and API key management\n- **Streaming Support**: Stream responses from chat and completion endpoints\n- **Automatic Rate Limiting**: Automatically configures rate limits based on your API key's limits using SmartSurge\n- **Smart Retries**: Built-in retry logic with exponential backoff for reliable API communication\n- **Type Safety**: Fully typed interfaces with Pydantic models for all request and response data\n- **Tool Calling**: Built-in support for tool-calling with helper functions and decorators\n- **Safe Key Management**: Secure API key management with in-memory encryption and extensible secrets management\n- **Comprehensive Testing**: Extensive test suite with both local unit tests and remote integration tests\n\n## Disclaimer\n\nThis project is independently developed and is not affiliated with, endorsed, or sponsored by OpenRouter, Inc.\n\nYour use of the OpenRouter API through this interface is subject to OpenRouter's Terms of Service, Privacy Policy, and any other relevant agreements provided by OpenRouter, Inc. You are responsible for reviewing and complying with these terms.\n\nThis project is an open-source interface designed to interact with the OpenRouter API. It is provided \"as-is,\" without any warranty, express or implied, under the terms of the Apache 2.0 License.\n\n## Installation\n\n```bash\npip install openrouter-client-unofficial\n```\n\n## Quickstart\n\n```python\nfrom openrouter_client import OpenRouterClient\n\n# Initialize the client\nclient = OpenRouterClient(\n    api_key=\"your-api-key\",  # Or set OPENROUTER_API_KEY environment variable\n)\n\n# Chat completion example\nresponse = client.chat.create(\n    model=\"anthropic/claude-3-opus\",  # Or any other model on OpenRouter\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n        {\"role\": \"user\", \"content\": \"Tell me about OpenRouter.\"}\n    ]\n)\n\nprint(response.choices[0].message.content)\n```\n\n## Client Configuration\n\n```python\nfrom openrouter_client import OpenRouterClient\n\nclient = OpenRouterClient(\n    api_key=\"your-api-key\",  # API key for authentication\n    provisioning_api_key=\"your-prov-key\",  # Optional: for API key management\n    base_url=\"https://openrouter.ai/api/v1\",  # Base URL for API\n    organization_id=\"your-org-id\",  # Optional organization ID\n    reference_id=\"your-ref-id\",  # Optional reference ID\n    log_level=\"INFO\",  # Logging level\n    timeout=60.0,  # Request timeout in seconds\n    retries=3,  # Number of retries for failed requests\n    backoff_factor=0.5,  # Exponential backoff factor\n    rate_limit=None,  # Optional custom rate limit (auto-configured by default)\n)\n```\n\n### Automatic Rate Limiting\n\nThe client automatically configures rate limits based on your API key's limits during initialization. It fetches your current key information and sets appropriate rate limits to prevent hitting API limits. This happens transparently when you create a new client instance.\n\nIf you need custom rate limiting, you can still provide your own configuration via the `rate_limit` parameter.\n\nYou can also calculate rate limits based on your remaining credits:\n\n```python\n# Calculate rate limits based on available credits\nrate_limits = client.calculate_rate_limits()\nprint(f\"Recommended: {rate_limits['requests']} requests per {rate_limits['period']} seconds\")\n```\n\n## Examples\n\n### Streaming Responses\n\n```python\nfrom openrouter_client import OpenRouterClient\n\nclient = OpenRouterClient(api_key=\"your-api-key\")\n\n# Stream the response\nfor chunk in client.chat.create(\n    model=\"openai/gpt-4\",\n    messages=[\n        {\"role\": \"user\", \"content\": \"Write a short poem about AI.\"}\n    ],\n    stream=True,\n):\n    if chunk.choices and chunk.choices[0].delta.content:\n        print(chunk.choices[0].delta.content, end=\"\")\n```\n\n### Function Calling\n\n```python\nfrom openrouter_client import OpenRouterClient, tool\nfrom openrouter_client.models import ChatCompletionTool, FunctionDefinition, StringParameter, FunctionParameters\n\nclient = OpenRouterClient(api_key=\"your-api-key\")\n\n# Method 1: Using the @tool decorator (recommended)\n@tool\ndef get_weather(location: str) -\u003e str:\n    \"\"\"Get the weather for a location.\n    \n    Args:\n        location: The city and state\n        \n    Returns:\n        Weather information for the location\n    \"\"\"\n    # Your weather API logic here\n    return f\"The weather in {location} is sunny.\"\n\n# Method 2: Manual tool definition\nweather_tool = ChatCompletionTool(\n    type=\"function\",\n    function=FunctionDefinition(\n        name=\"get_weather\",\n        description=\"Get the weather for a location\",\n        parameters=FunctionParameters(\n            type=\"object\",\n            properties={\n                \"location\": StringParameter(\n                    type=\"string\",\n                    description=\"The city and state\"\n                )\n            },\n            required=[\"location\"]\n        )\n    )\n)\n\n# Make a request with tool\nresponse = client.chat.create(\n    model=\"anthropic/claude-3-opus\",\n    messages=[\n        {\"role\": \"user\", \"content\": \"What's the weather like in San Francisco?\"}\n    ],\n    tools=[get_weather],  # Using the decorated function\n)\n\n# Process tool calls\nif response.choices[0].message.tool_calls:\n    tool_call = response.choices[0].message.tool_calls[0]\n    print(f\"Tool called: {tool_call.function.name}\")\n    print(f\"Arguments: {tool_call.function.arguments}\")\n```\n\n### Prompt Caching\n\n```python\nfrom openrouter_client import OpenRouterClient\n\nclient = OpenRouterClient(api_key=\"your-api-key\")\n\n# OpenAI models: automatic caching for prompts \u003e 1024 tokens\nresponse = client.chat.create(\n    model=\"openai/gpt-3.5-turbo\",\n    messages=[\n        {\"role\": \"user\", \"content\": f\"Here is a long document: {long_text}\\n\\nSummarize this document.\"}\n    ]\n)\n\n# Anthropic models: explicit cache_control markers\nresponse = client.chat.create(\n    model=\"anthropic/claude-3-opus\",\n    messages=[\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\"type\": \"text\", \"text\": \"Here is a long document:\"},\n                # Mark this part for caching\n                {\"type\": \"text\", \"text\": long_text, \"cache_control\": {\"type\": \"ephemeral\"}},\n                {\"type\": \"text\", \"text\": \"Summarize this document.\"}\n            ]\n        }\n    ]\n)\n```\n\n### Context Length Management\n\nThe client provides built-in context length management:\n\n```python\n# Refresh model context lengths from the API\ncontext_lengths = client.refresh_context_lengths()\n\n# Get context length for a specific model\nmax_tokens = client.get_context_length(\"anthropic/claude-3-opus\")\nprint(f\"Claude 3 Opus supports up to {max_tokens} tokens\")\n```\n\n### API Key Management\n\nManage API keys programmatically (requires provisioning API key):\n\n```python\nclient = OpenRouterClient(\n    api_key=\"your-api-key\",\n    provisioning_api_key=\"your-provisioning-key\"\n)\n\n# Get current key information\nkey_info = client.keys.get_current()\nprint(f\"Current usage: {key_info['data']['usage']} credits\")\nprint(f\"Rate limit: {key_info['data']['rate_limit']['requests']} requests per {key_info['data']['rate_limit']['interval']}\")\n\n# List all keys\nkeys = client.keys.list()\n\n# Create a new key\nnew_key = client.keys.create(\n    name=\"My New Key\",\n    label=\"Production API Key\",\n    limit=1000.0  # Credit limit\n)\n```\n\n## Available Endpoints\n\n- `client.chat`: Chat completions API\n- `client.completions`: Text completions API\n- `client.models`: Model information and selection\n- `client.generations`: Generation metadata and details\n- `client.credits`: Credit management and usage tracking\n- `client.keys`: API key management and provisioning\n\n## License\n\nThis project is licensed under the Apache 2.0 License - see the LICENSE file for details.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdingo-actual%2Fopenrouter-python-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdingo-actual%2Fopenrouter-python-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdingo-actual%2Fopenrouter-python-client/lists"}