{"files":{"SKILL.md":"---\nname: openrouter-api\ndescription: \"OpenRouter API skill. Use when working with OpenRouter for activity, analytics, audio. Covers 87 endpoints.\"\nversion: 1.0.0\ngenerator: lapsh\n---\n\n# OpenRouter API\nAPI version: 1.0.0\n\n## Auth\nBearer bearer | Bearer bearer\n\n## Base URL\nhttps://openrouter.ai/api/v1\n\n## Setup\n1. Set Authorization header with your Bearer token\n2. GET /activity -- verify access\n3. POST /analytics/query -- create first query\n\n## Endpoints\n\n87 endpoints across 29 groups. See references/api-spec.lap for full details.\n\n### activity\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /activity | Get user activity grouped by endpoint |\n\n### analytics\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /analytics/meta | Get available analytics metrics and dimensions |\n| POST | /analytics/query | Query analytics data |\n\n### audio\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /audio/speech | Create speech |\n| POST | /audio/transcriptions | Create transcription |\n\n### auth\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /auth/keys | Exchange authorization code for API key |\n| POST | /auth/keys/code | Create authorization code |\n\n### benchmarks\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /benchmarks | List Benchmarks |\n\n### byok\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /byok | List BYOK provider credentials |\n| POST | /byok | Create a BYOK provider credential |\n| DELETE | /byok/{id} | Delete a BYOK provider credential |\n| GET | /byok/{id} | Get a BYOK provider credential |\n| PATCH | /byok/{id} | Update a BYOK provider credential |\n\n### chat\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /chat/completions | Create a chat completion |\n\n### classifications\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /classifications/task | Task classification market share |\n\n### credits\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /credits | Get remaining credits |\n| POST | /credits/coinbase | Deprecated Coinbase Commerce charge endpoint |\n\n### datasets\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /datasets/app-rankings | Top apps by token usage |\n| GET | /datasets/rankings-daily | Daily token totals for top 50 models |\n\n### embeddings\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /embeddings | Submit an embedding request |\n| GET | /embeddings/models | List all embeddings models |\n\n### endpoints\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /endpoints/zdr | Preview the impact of ZDR on the available endpoints |\n\n### files\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /files | List files |\n| POST | /files | Upload a file |\n| DELETE | /files/{file_id} | Delete a file |\n| GET | /files/{file_id} | Get file metadata |\n| GET | /files/{file_id}/content | Download file content |\n\n### generation\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /generation | Get request & usage metadata for a generation |\n| GET | /generation/content | Get stored prompt and completion content for a generation |\n\n### guardrails\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /guardrails | List guardrails |\n| POST | /guardrails | Create a guardrail |\n| DELETE | /guardrails/{id} | Delete a guardrail |\n| GET | /guardrails/{id} | Get a guardrail |\n| PATCH | /guardrails/{id} | Update a guardrail |\n| GET | /guardrails/{id}/assignments/keys | List key assignments for a guardrail |\n| POST | /guardrails/{id}/assignments/keys | Bulk assign keys to a guardrail |\n| POST | /guardrails/{id}/assignments/keys/remove | Bulk unassign keys from a guardrail |\n| GET | /guardrails/{id}/assignments/members | List member assignments for a guardrail |\n| POST | /guardrails/{id}/assignments/members | Bulk assign members to a guardrail |\n| POST | /guardrails/{id}/assignments/members/remove | Bulk unassign members from a guardrail |\n| GET | /guardrails/assignments/keys | List all key assignments |\n| GET | /guardrails/assignments/members | List all member assignments |\n\n### images\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /images | Generate an image |\n| GET | /images/models | List image generation models |\n| GET | /images/models/{author}/{slug}/endpoints | List endpoints for an image model |\n\n### key\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /key | Get current API key |\n\n### keys\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /keys | List API keys |\n| POST | /keys | Create a new API key |\n| DELETE | /keys/{hash} | Delete an API key |\n| GET | /keys/{hash} | Get a single API key |\n| PATCH | /keys/{hash} | Update an API key |\n\n### messages\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /messages | Create a message |\n\n### model\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /model/{author}/{slug} | Get a model by its slug |\n\n### models\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /models | List all models and their properties |\n| GET | /models/{author}/{slug}/endpoints | List all endpoints for a model |\n| GET | /models/count | Get total count of available models |\n| GET | /models/user | List models filtered by user provider preferences, privacy settings, and guardrails |\n\n### observability\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /observability/destinations | List observability destinations |\n| POST | /observability/destinations | Create an observability destination |\n| DELETE | /observability/destinations/{id} | Delete an observability destination |\n| GET | /observability/destinations/{id} | Get an observability destination |\n| PATCH | /observability/destinations/{id} | Update an observability destination |\n\n### organization\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /organization/members | List organization members |\n\n### presets\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /presets | List presets |\n| GET | /presets/{slug} | Get a preset |\n| POST | /presets/{slug}/chat/completions | Create a preset from a chat-completions request body |\n| POST | /presets/{slug}/messages | Create a preset from a messages request body |\n| POST | /presets/{slug}/responses | Create a preset from a responses request body |\n| GET | /presets/{slug}/versions | List versions of a preset |\n| GET | /presets/{slug}/versions/{version} | Get a specific version of a preset |\n\n### providers\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /providers | List all providers |\n\n### rerank\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /rerank | Submit a rerank request |\n\n### responses\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /responses | Create a response |\n\n### videos\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | /videos | Submit a video generation request |\n| GET | /videos/{jobId} | Poll video generation status |\n| GET | /videos/{jobId}/content | Download generated video content |\n| GET | /videos/models | List all video generation models |\n\n### workspaces\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /workspaces | List workspaces |\n| POST | /workspaces | Create a workspace |\n| DELETE | /workspaces/{id} | Delete a workspace |\n| GET | /workspaces/{id} | Get a workspace |\n| PATCH | /workspaces/{id} | Update a workspace |\n| GET | /workspaces/{id}/budgets | List workspace budgets |\n| DELETE | /workspaces/{id}/budgets/{interval} | Delete a workspace budget |\n| PUT | /workspaces/{id}/budgets/{interval} | Create or update a workspace budget |\n| POST | /workspaces/{id}/members/add | Bulk add members to a workspace |\n| POST | /workspaces/{id}/members/remove | Bulk remove members from a workspace |\n\n## Common Questions\n\nMatch user requests to endpoints in references/api-spec.lap. Key patterns:\n- \"List all activity?\" -> GET /activity\n- \"List all meta?\" -> GET /analytics/meta\n- \"Create a query?\" -> POST /analytics/query\n- \"Create a speech?\" -> POST /audio/speech\n- \"Create a transcription?\" -> POST /audio/transcriptions\n- \"Create a key?\" -> POST /auth/keys\n- \"Create a code?\" -> POST /auth/keys/code\n- \"List all benchmarks?\" -> GET /benchmarks\n- \"List all byok?\" -> GET /byok\n- \"Create a byok?\" -> POST /byok\n- \"Delete a byok?\" -> DELETE /byok/{id}\n- \"Get byok details?\" -> GET /byok/{id}\n- \"Partially update a byok?\" -> PATCH /byok/{id}\n- \"Create a completion?\" -> POST /chat/completions\n- \"List all task?\" -> GET /classifications/task\n- \"List all credits?\" -> GET /credits\n- \"Create a coinbase?\" -> POST /credits/coinbase\n- \"List all app-rankings?\" -> GET /datasets/app-rankings\n- \"List all rankings-daily?\" -> GET /datasets/rankings-daily\n- \"Create a embedding?\" -> POST /embeddings\n- \"List all models?\" -> GET /embeddings/models\n- \"List all zdr?\" -> GET /endpoints/zdr\n- \"List all files?\" -> GET /files\n- \"Create a file?\" -> POST /files\n- \"Delete a file?\" -> DELETE /files/{file_id}\n- \"Get file details?\" -> GET /files/{file_id}\n- \"List all content?\" -> GET /files/{file_id}/content\n- \"List all generation?\" -> GET /generation\n- \"List all content?\" -> GET /generation/content\n- \"List all guardrails?\" -> GET /guardrails\n- \"Create a guardrail?\" -> POST /guardrails\n- \"Delete a guardrail?\" -> DELETE /guardrails/{id}\n- \"Get guardrail details?\" -> GET /guardrails/{id}\n- \"Partially update a guardrail?\" -> PATCH /guardrails/{id}\n- \"List all keys?\" -> GET /guardrails/{id}/assignments/keys\n- \"Create a key?\" -> POST /guardrails/{id}/assignments/keys\n- \"Create a remove?\" -> POST /guardrails/{id}/assignments/keys/remove\n- \"List all members?\" -> GET /guardrails/{id}/assignments/members\n- \"Create a member?\" -> POST /guardrails/{id}/assignments/members\n- \"Create a remove?\" -> POST /guardrails/{id}/assignments/members/remove\n- \"List all keys?\" -> GET /guardrails/assignments/keys\n- \"List all members?\" -> GET /guardrails/assignments/members\n- \"Create a image?\" -> POST /images\n- \"List all models?\" -> GET /images/models\n- \"List all endpoints?\" -> GET /images/models/{author}/{slug}/endpoints\n- \"List all key?\" -> GET /key\n- \"List all keys?\" -> GET /keys\n- \"Create a key?\" -> POST /keys\n- \"Delete a key?\" -> DELETE /keys/{hash}\n- \"Get key details?\" -> GET /keys/{hash}\n- \"Partially update a key?\" -> PATCH /keys/{hash}\n- \"Create a message?\" -> POST /messages\n- \"Get model details?\" -> GET /model/{author}/{slug}\n- \"Search models?\" -> GET /models\n- \"List all endpoints?\" -> GET /models/{author}/{slug}/endpoints\n- \"List all count?\" -> GET /models/count\n- \"List all user?\" -> GET /models/user\n- \"List all destinations?\" -> GET /observability/destinations\n- \"Create a destination?\" -> POST /observability/destinations\n- \"Delete a destination?\" -> DELETE /observability/destinations/{id}\n- \"Get destination details?\" -> GET /observability/destinations/{id}\n- \"Partially update a destination?\" -> PATCH /observability/destinations/{id}\n- \"List all members?\" -> GET /organization/members\n- \"List all presets?\" -> GET /presets\n- \"Get preset details?\" -> GET /presets/{slug}\n- \"Create a completion?\" -> POST /presets/{slug}/chat/completions\n- \"Create a message?\" -> POST /presets/{slug}/messages\n- \"Create a response?\" -> POST /presets/{slug}/responses\n- \"List all versions?\" -> GET /presets/{slug}/versions\n- \"Get version details?\" -> GET /presets/{slug}/versions/{version}\n- \"List all providers?\" -> GET /providers\n- \"Create a rerank?\" -> POST /rerank\n- \"Create a response?\" -> POST /responses\n- \"Create a video?\" -> POST /videos\n- \"Get video details?\" -> GET /videos/{jobId}\n- \"List all content?\" -> GET /videos/{jobId}/content\n- \"List all models?\" -> GET /videos/models\n- \"List all workspaces?\" -> GET /workspaces\n- \"Create a workspace?\" -> POST /workspaces\n- \"Delete a workspace?\" -> DELETE /workspaces/{id}\n- \"Get workspace details?\" -> GET /workspaces/{id}\n- \"Partially update a workspace?\" -> PATCH /workspaces/{id}\n- \"List all budgets?\" -> GET /workspaces/{id}/budgets\n- \"Delete a budget?\" -> DELETE /workspaces/{id}/budgets/{interval}\n- \"Update a budget?\" -> PUT /workspaces/{id}/budgets/{interval}\n- \"Create a add?\" -> POST /workspaces/{id}/members/add\n- \"Create a remove?\" -> POST /workspaces/{id}/members/remove\n- \"How to authenticate?\" -> See Auth section\n\n## Response Tips\n- Check response schemas in references/api-spec.lap for field details\n- List endpoints may support pagination; check for limit, offset, or cursor params\n- Create/update endpoints typically return the created/updated object\n\n## CLI\n\n```bash\n# Update this spec to the latest version\nnpx @lap-platform/lapsh get openrouter-api -o references/api-spec.lap\n\n# Search for related APIs\nnpx @lap-platform/lapsh search openrouter-api\n```\n\n## References\n- Full spec: See references/api-spec.lap for complete endpoint details, parameter tables, and response schemas\n\n> Generated from the official API spec by [LAP](https://lap.sh)\n","references/api-spec.lap":"@lap v0.3\n# Machine-readable API spec. Each @endpoint block is one API call.\n@api OpenRouter API\n@base https://openrouter.ai/api/v1\n@version 1.0.0\n@auth Bearer bearer | Bearer bearer\n@endpoints 87\n@hint download_for_search\n@toc activity(1), analytics(2), audio(2), auth(2), benchmarks(1), byok(5), chat(1), classifications(1), credits(2), datasets(2), embeddings(2), endpoints(1), files(5), generation(2), guardrails(13), images(3), key(1), keys(5), messages(1), model(1), models(4), observability(5), organization(1), presets(7), providers(1), rerank(1), responses(1), videos(4), workspaces(10)\n\n@group activity\n@endpoint GET /activity\n@desc Get user activity grouped by endpoint\n@optional {date: str # Filter by a single UTC date in the last 30 days (YYYY-MM-DD format)., api_key_hash: str # Filter by API key hash (SHA-256 hex string, as returned by the keys API)., user_id: str # Filter by org member user ID. Only applicable for organization accounts.}\n@returns(200) {data: [map]} # Returns user activity data grouped by endpoint\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group analytics\n@endpoint GET /analytics/meta\n@desc Get available analytics metrics and dimensions\n@returns(200) {data: map{dimensions: [map], granularities: [map], metrics: [map], operators: [map]}} # Returns analytics query metadata\n@errors {401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /analytics/query\n@desc Query analytics data\n@required {metrics: [str]}\n@optional {dimensions: [str], filters: [map{field!: str, operator!: str, value!: any}], granularity: str # Time granularity, group_limit: int # Maximum rows per distinct combination of dimensions. When omitted on time-series queries (granularity + dimensions), auto-computed to avoid truncating time windows. Explicit values override the default and may truncate time buckets if set lower than the number of buckets in the range. Ignored when no dimensions are specified., limit: int # Maximum total rows returned. Defaults to 1000. On time-series queries with dimensions and no explicit group_limit, the server may raise this to accommodate the expected number of unique time-bucket/dimension combinations., order_by: map{direction!: str, field!: str}, time_range: map{end!: str(date-time), start!: str(date-time)}}\n@returns(200) {data: map{cachedAt: num(double), data: [map], metadata: map{query_time_ms: num(double), row_count: int, truncated: bool}, warnings: [str]}} # Analytics query results\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 408: Request Timeout - Operation exceeded time limit, 500: Internal Server Error - Unexpected server error}\n@example_request {\"dimensions\":[\"model\"],\"granularity\":\"day\",\"limit\":100,\"metrics\":[\"request_count\"],\"time_range\":{\"end\":\"2025-01-08T00:00:00Z\",\"start\":\"2025-01-01T00:00:00Z\"}}\n\n@endgroup\n\n@group audio\n@endpoint POST /audio/speech\n@desc Create speech\n@required {input: str # Text to synthesize, model: str # TTS model identifier, voice: str # Voice identifier (provider-specific).}\n@optional {provider: map{options: map} # Provider-specific passthrough configuration, response_format: str(mp3/pcm)=pcm # Audio output format, speed: num(double) # Playback speed multiplier. Only used by models that support it (e.g. OpenAI TTS). Ignored by other providers.}\n@returns(200) Audio bytes stream\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 402: Payment Required - Insufficient credits or quota to complete request, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure, 503: Service Unavailable - Service temporarily unavailable, 524: Infrastructure Timeout - Provider request timed out at edge network, 529: Provider Overloaded - Provider is temporarily overloaded}\n@example_request {\"input\":\"Hello world\",\"model\":\"elevenlabs/eleven-turbo-v2\",\"response_format\":\"pcm\",\"speed\":1,\"voice\":\"alloy\"}\n\n@endpoint POST /audio/transcriptions\n@desc Create transcription\n@required {input_audio: map{data!: str, format!: str} # Base64-encoded audio to transcribe, model: str # STT model identifier}\n@optional {language: str # ISO-639-1 language code (e.g., \"en\", \"ja\"). Auto-detected if omitted., provider: map{options: map} # Provider-specific passthrough configuration, temperature: num(double) # Sampling temperature for transcription}\n@returns(200) {text: str, usage: map{cost: num(double), input_tokens: int, output_tokens: int, seconds: num(double), total_tokens: int}} # Transcription result\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 402: Payment Required - Insufficient credits or quota to complete request, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure, 503: Service Unavailable - Service temporarily unavailable, 524: Infrastructure Timeout - Provider request timed out at edge network, 529: Provider Overloaded - Provider is temporarily overloaded}\n@example_request {\"input_audio\":{\"data\":\"UklGRiQA...\",\"format\":\"wav\"},\"language\":\"en\",\"model\":\"openai/whisper-large-v3\"}\n\n@endgroup\n\n@group auth\n@endpoint POST /auth/keys\n@desc Exchange authorization code for API key\n@required {code: str # The authorization code received from the OAuth redirect}\n@optional {code_challenge_method: str(S256/plain) # The method used to generate the code challenge, code_verifier: str # The code verifier if code_challenge was used in the authorization request}\n@returns(200) {key: str, user_id: str?} # Successfully exchanged code for an API key\n@errors {400: Bad Request - Invalid request parameters or malformed input, 403: Forbidden - Authentication successful but insufficient permissions, 500: Internal Server Error - Unexpected server error}\n@example_request {\"code\":\"auth_code_abc123def456\",\"code_challenge_method\":\"S256\",\"code_verifier\":\"dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk\"}\n\n@endpoint POST /auth/keys/code\n@desc Create authorization code\n@required {callback_url: str(uri) # The callback URL to redirect to after authorization. Supports https URLs and localhost/127.0.0.1 URLs on any port for local CLI tools.}\n@optional {code_challenge: str # PKCE code challenge for enhanced security, code_challenge_method: str(S256/plain) # The method used to generate the code challenge, expires_at: str(date-time) # Optional expiration time for the API key to be created, key_label: str # Optional custom label for the API key. Defaults to the app name if not provided., limit: num(double) # Credit limit for the API key to be created, spawn_agent: str # Agent identifier for spawn telemetry, spawn_cloud: str # Cloud identifier for spawn telemetry, usage_limit_type: str(daily/weekly/monthly) # Optional credit limit reset interval. When set, the credit limit resets on this interval., workspace_id: str(uuid) # Optional workspace ID to associate the API key with}\n@returns(200) {data: map{app_id: int, created_at: str, id: str}} # Successfully created authorization code\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 409: Conflict - Resource conflict or concurrent modification, 500: Internal Server Error - Unexpected server error}\n@example_request {\"callback_url\":\"https://myapp.com/auth/callback\",\"code_challenge\":\"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\",\"code_challenge_method\":\"S256\",\"limit\":100}\n\n@endgroup\n\n@group benchmarks\n@endpoint GET /benchmarks\n@desc List Benchmarks\n@optional {source: str(artificial-analysis/design-arena) # Benchmark source to query. Determines the shape of the returned items. When omitted, returns results from all sources., task_type: str(coding/intelligence/agentic) # Filter results by task type. For Artificial Analysis, maps to the corresponding index. For Design Arena, maps to the matching category., arena: str(models/builders/agents) # Design Arena only: arena to query. Defaults to `models` when source is `design-arena`., category: str # Design Arena only: category within the arena (e.g. `codecategories`, `uicomponent`, `gamedev`, `3d`, `dataviz`, `image`, `video`, `svg`). When omitted, returns all categories., max_results: int # Maximum number of items to return. When omitted, all matching results are returned.}\n@returns(200) {data: [any], meta: map{as_of: str, citation: str?, model_count: int, source: str?, source_url: str?, task_type: str?, version: str}} # Benchmark results filtered by the specified source and optional task type.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group byok\n@endpoint GET /byok\n@desc List BYOK provider credentials\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100), workspace_id: str(uuid) # Optional workspace ID to filter by. Defaults to the authenticated entity's default workspace., provider: str(ai21/aion-labs/akashml/alibaba/amazon-bedrock/amazon-nova/ambient/anthropic/arcee-ai/atlas-cloud/avian/azure/baidu/baseten/black-forest-labs/byteplus/cerebras/chutes/cirrascale/clarifai/cloudflare/cohere/crusoe/darkbloom/decart/deepinfra/deepseek/dekallm/digitalocean/featherless/fireworks/friendli/gmicloud/google-ai-studio/google-vertex/groq/heygen/inception/inceptron/inferact-vllm/inference-net/infermatic/inflection/io-net/ionstream/liquid/mancer/mara/minimax/mistral/modelrun/modular/moonshotai/morph/ncompass/nebius/nex-agi/nextbit/novita/nvidia/open-inference/openai/parasail/perceptron/perplexity/phala/poolside/quiver/recraft/reka/relace/sakana-ai/sambanova/seed/siliconflow/sourceful/stepfun/streamlake/switchpoint/tenstorrent/together/upstage/venice/wafer/wandb/xai/xiaomi/z-ai) # Optional provider slug to filter by (e.g. `openai`, `anthropic`, `amazon-bedrock`).}\n@returns(200) {data: [map], total_count: int} # List of BYOK credentials\n@errors {401: Unauthorized - Authentication required or invalid credentials, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /byok\n@desc Create a BYOK provider credential\n@required {key: str # The raw provider API key or credential. This value is encrypted at rest and never returned in API responses., provider: str(ai21/aion-labs/akashml/alibaba/amazon-bedrock/amazon-nova/ambient/anthropic/arcee-ai/atlas-cloud/avian/azure/baidu/baseten/black-forest-labs/byteplus/cerebras/chutes/cirrascale/clarifai/cloudflare/cohere/crusoe/darkbloom/decart/deepinfra/deepseek/dekallm/digitalocean/featherless/fireworks/friendli/gmicloud/google-ai-studio/google-vertex/groq/heygen/inception/inceptron/inferact-vllm/inference-net/infermatic/inflection/io-net/ionstream/liquid/mancer/mara/minimax/mistral/modelrun/modular/moonshotai/morph/ncompass/nebius/nex-agi/nextbit/novita/nvidia/open-inference/openai/parasail/perceptron/perplexity/phala/poolside/quiver/recraft/reka/relace/sakana-ai/sambanova/seed/siliconflow/sourceful/stepfun/streamlake/switchpoint/tenstorrent/together/upstage/venice/wafer/wandb/xai/xiaomi/z-ai) # The upstream provider this credential authenticates against, as a lowercase slug (e.g. `openai`, `anthropic`, `amazon-bedrock`).}\n@optional {allowed_models: [str] # Optional allowlist of model slugs this credential may be used for. `null` means no restriction., allowed_user_ids: [str] # Optional allowlist of user IDs that may use this credential. `null` means no restriction., disabled: bool # Whether this credential should be created in a disabled state., is_fallback: bool # Whether this credential is treated as a fallback — used only after non-fallback keys for the same provider have been tried., name: str # Optional human-readable name for the credential., workspace_id: str(uuid) # Optional workspace ID. Defaults to the authenticated entity's default workspace.}\n@returns(201) {data: any} # BYOK credential created successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 500: Internal Server Error - Unexpected server error}\n@example_request {\"key\":\"sk-proj-abc123...\",\"name\":\"Production OpenAI Key\",\"provider\":\"openai\"}\n\n@endpoint DELETE /byok/{id}\n@desc Delete a BYOK provider credential\n@required {id: str(uuid) # The BYOK credential ID (UUID).}\n@returns(200) {deleted: bool} # BYOK credential deleted successfully\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /byok/{id}\n@desc Get a BYOK provider credential\n@required {id: str(uuid) # The BYOK credential ID (UUID).}\n@returns(200) {data: any} # BYOK credential details\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint PATCH /byok/{id}\n@desc Update a BYOK provider credential\n@required {id: str(uuid) # The BYOK credential ID (UUID).}\n@optional {allowed_models: [str] # Optional allowlist of model slugs this credential may be used for. `null` means no restriction., allowed_user_ids: [str] # Optional allowlist of user IDs that may use this credential. `null` means no restriction., disabled: bool # Whether this credential is disabled., is_fallback: bool # Whether this credential is treated as a fallback — used only after non-fallback keys for the same provider have been tried., key: str # A new raw provider API key to rotate the credential in-place. The previous key material is overwritten and the masked label is regenerated. Encrypted at rest and never returned in API responses., name: str # Optional human-readable name for the credential.}\n@returns(200) {data: any} # BYOK credential updated successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"disabled\":false,\"name\":\"Updated OpenAI Key\"}\n\n@endgroup\n\n@group chat\n@endpoint POST /chat/completions\n@desc Create a chat completion\n@required {messages: [any] # List of messages for the conversation}\n@optional {X-OpenRouter-Metadata: str # Opt-in to surface routing metadata on the response under `openrouter_metadata`. Defaults to `disabled`. The legacy header `X-OpenRouter-Experimental-Metadata` is also accepted for backward compatibility., cache_control: map{ttl: str, type!: str} # Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models., debug: map{echo_upstream_body: bool} # Debug options for inspecting request transformations (streaming only), frequency_penalty: num(double) # Frequency penalty (-2.0 to 2.0), image_config: map # Provider-specific image configuration options. Keys and values vary by model/provider. See https://openrouter.ai/docs/guides/overview/multimodal/image-generation for more details., logit_bias: map # Token logit bias adjustments, logprobs: bool # Return log probabilities, max_completion_tokens: int # Maximum tokens in completion, max_tokens: int # Maximum tokens (deprecated, use max_completion_tokens). Note: some providers enforce a minimum of 16., metadata: map # Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values), min_p: num(double) # Minimum probability threshold relative to the most likely token. Tokens with probability below min_p * (probability of top token) are filtered out. Not all providers support this parameter., modalities: [str] # Output modalities for the response. Supported values are \"text\", \"image\", and \"audio\"., model: str # Model to use for completion, models: [any] # Models to use for completion, parallel_tool_calls: bool # Whether to enable parallel function calling during tool use. When true, the model may generate multiple tool calls in a single response., plugins: [any] # Plugins you want to enable for this request, including their settings., presence_penalty: num(double) # Presence penalty (-2.0 to 2.0), provider: map{allow_fallbacks: bool, data_collection: str, enforce_distillable_text: bool, ignore: [any], max_price: map, only: [any], order: [any], preferred_max_latency: any, preferred_min_throughput: any, quantizations: [str], require_parameters: bool, sort: any, zdr: bool} # When multiple model providers are available, optionally indicate your routing preference., reasoning: map{effort: str, summary: str} # Configuration options for reasoning models, reasoning_effort: str(max/xhigh/high/medium/low/minimal/none) # Shorthand for setting reasoning effort. Equivalent to setting reasoning.effort. Cannot be used simultaneously with reasoning.effort if they differ., repetition_penalty: num(double) # Penalizes tokens based on how much they have already appeared in the text. A value of 1.0 means no penalty. Values above 1.0 penalize repeated tokens more strongly. Not all providers support this parameter., response_format: any # Response format configuration, route: str(fallback/sort) # **DEPRECATED** Use providers.sort.partition instead. Backwards-compatible alias for providers.sort.partition. Accepts legacy values: \"fallback\" (maps to \"model\"), \"sort\" (maps to \"none\")., seed: int # Random seed for deterministic outputs, service_tier: str(auto/default/flex/priority/scale) # The service tier to use for processing this request., session_id: str # A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters., stop: any # Stop sequences (up to 4), stop_server_tools_when: [any] # Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`., stream: bool=false # Enable streaming response, stream_options: map{include_usage: bool} # Streaming configuration options, temperature: num(double) # Sampling temperature (0-2), tool_choice: any # Tool choice configuration, tools: [any] # Available tools for function calling, top_a: num(double) # Consider only tokens with \"sufficiently high\" probabilities based on the probability of the most likely token. Not all providers support this parameter., top_k: int # Limits the model to choose from the top K most likely tokens at each step. A value of 1 means the model will always pick the most likely next token. Not all providers support this parameter., top_logprobs: int # Number of top log probabilities to return (0-20), top_p: num(double) # Nucleus sampling parameter (0-1), trace: map{generation_name: str, parent_span_id: str, span_name: str, trace_id: str, trace_name: str} # Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations., user: str # Unique user identifier}\n@returns(200) {choices: [map], created: int, id: str, model: str, object: str, openrouter_metadata: map{attempt: int, attempts: [map], endpoints: map{available: [map], total: int}, is_byok: bool, params: map{quality_floor: num(double), throughput_floor: num(double), version_group: str}, pipeline: [map], region: str?, requested: str, strategy: str, summary: str}, service_tier: str?, system_fingerprint: str?, usage: map{completion_tokens: int, completion_tokens_details: map?{accepted_prediction_tokens: int?, audio_tokens: int?, reasoning_tokens: int?, rejected_prediction_tokens: int?}, cost: num(double)?, cost_details: map?{upstream_inference_completions_cost: num(double), upstream_inference_cost: num(double)?, upstream_inference_prompt_cost: num(double)}, is_byok: bool, prompt_tokens: int, prompt_tokens_details: map?{audio_tokens: int, cache_write_tokens: int, cached_tokens: int, video_tokens: int}, server_tool_use_details: map?{tool_calls_executed: int?, tool_calls_requested: int?, web_search_requests: int?}, total_tokens: int}} # Successful chat completion response\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 402: Payment Required - Insufficient credits or quota to complete request, 403: Forbidden - Authentication successful but insufficient permissions, or a guardrail blocked the request. When guardrails block and the `X-OpenRouter-Metadata: enabled` header is present, the response includes `openrouter_metadata` with full routing context and a `pipeline` array containing guardrail stage details., 404: Not Found - Resource does not exist, 408: Request Timeout - Operation exceeded time limit, 413: Payload Too Large - Request payload exceeds size limits, 422: Unprocessable Entity - Semantic validation failure, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure, 503: Service Unavailable - Service temporarily unavailable, 524: Infrastructure Timeout - Provider request timed out at edge network, 529: Provider Overloaded - Provider is temporarily overloaded}\n@example_request {\"max_tokens\":150,\"messages\":[{\"content\":\"You are a helpful assistant.\",\"role\":\"system\"},{\"content\":\"What is the capital of France?\",\"role\":\"user\"}],\"model\":\"openai/gpt-4\",\"temperature\":0.7}\n\n@endgroup\n\n@group classifications\n@endpoint GET /classifications/task\n@desc Task classification market share\n@optional {window: str=7d # Trailing time window for the classification data. Currently only `7d` (trailing 7 days) is supported.}\n@returns(200) {data: map{as_of: str, classifications: [map], macro_categories: [map], window_days: int}} # Task classification market-share data for the requested trailing window.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group credits\n@endpoint GET /credits\n@desc Get remaining credits\n@returns(200) {data: map{total_credits: num(double), total_usage: num(double)}} # Returns the total credits purchased and used\n@errors {401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /credits/coinbase\n@desc Deprecated Coinbase Commerce charge endpoint\n@returns(200) This endpoint is deprecated and will never return a 200 response.\n@errors {410: Gone - Endpoint has been permanently removed or deprecated}\n\n@endgroup\n\n@group datasets\n@endpoint GET /datasets/app-rankings\n@desc Top apps by token usage\n@optional {category: str(coding/creative/productivity/entertainment) # Marketplace category group to filter by (e.g. `coding`). Only apps tagged with a subcategory inside this group are returned. Mutually combinable with `subcategory` — when both are supplied the `subcategory` must belong to the `category` group., subcategory: str(cli-agent/ide-extension/cloud-agent/programming-app/native-app-builder/creative-writing/video-gen/image-gen/audio-gen/roleplay/game/writing-assistant/general-chat/personal-agent/legal) # Marketplace subcategory to filter by (e.g. `cli-agent`). Takes precedence over `category` for the actual filter; when `category` is also supplied the pair must be consistent., sort: str(popular/trending)=popular # `popular` ranks apps by total token volume inside the date window. `trending` ranks apps by absolute excess token growth: window volume minus the average volume of the three equal-length periods immediately preceding the window. Apps with no excess growth are omitted from `trending` results., start_date: str # Start of the date window in YYYY-MM-DD (UTC), inclusive. Defaults to 30 days before `end_date`. The dataset begins at 2025-01-01; earlier values are clamped forward to that floor and the resolved value is echoed in `meta.start_date`., end_date: str # End of the date window in YYYY-MM-DD (UTC), inclusive. Defaults to the most recent completed UTC day. Must be on or after 2025-01-01; earlier values are rejected with a 400., limit: int=50 # Maximum number of apps to return (1-100). Defaults to 50., offset: int=0 # Number of ranked apps to skip before the first returned row (0-100). Defaults to 0. `rank` stays absolute, so the first row of `offset=50` is `rank: 51`.}\n@returns(200) {data: [map], meta: map{as_of: str, end_date: str, start_date: str, version: str}} # Apps ranked per the requested `sort`, re-numbered 1..N. `popular` sorts by `total_tokens` descending; `trending` sorts by absolute excess token growth descending and may return fewer than `limit` rows.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /datasets/rankings-daily\n@desc Daily token totals for top 50 models\n@optional {start_date: str # Start of the date window in YYYY-MM-DD (UTC), inclusive. Defaults to 30 days before `end_date`. The dataset begins at 2025-01-01; earlier values are clamped forward to that floor and the resolved value is echoed in `meta.start_date`., end_date: str # End of the date window in YYYY-MM-DD (UTC), inclusive. Defaults to the most recent completed UTC day. Must be on or after 2025-01-01; earlier values are rejected with a 400.}\n@returns(200) {data: [map], meta: map{as_of: str, end_date: str, start_date: str, version: str}} # Up to 51 rows per day — the top 50 public models by `total_tokens` plus a single aggregated `other` row covering every model outside that top 50. Sorted by `date` ascending, then by `total_tokens` descending, with `other` pinned last within its date.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group embeddings\n@endpoint POST /embeddings\n@desc Submit an embedding request\n@required {input: any # Text, token, or multimodal input(s) to embed, model: str # The model to use for embeddings}\n@optional {dimensions: int # The number of dimensions for the output embeddings, encoding_format: str(float/base64) # The format of the output embeddings, input_type: str # The type of input (e.g. search_query, search_document), provider: any, user: str # A unique identifier for the end-user}\n@returns(200) {data: [map], id: str, model: str, object: str, usage: map{cost: num(double), cost_details: map?{upstream_inference_completions_cost: num(double), upstream_inference_cost: num(double)?, upstream_inference_prompt_cost: num(double)}, is_byok: bool, prompt_tokens: int, prompt_tokens_details: map{audio_tokens: int, file_tokens: int, image_tokens: int, text_tokens: int, video_tokens: int}, total_tokens: int}} # Embedding response\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 402: Payment Required - Insufficient credits or quota to complete request, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure, 503: Service Unavailable - Service temporarily unavailable, 524: Infrastructure Timeout - Provider request timed out at edge network, 529: Provider Overloaded - Provider is temporarily overloaded}\n\n@endpoint GET /embeddings/models\n@desc List all embeddings models\n@returns(200) {data: [map]} # Returns a list of embeddings models\n@errors {400: Bad Request - Invalid request parameters or malformed input, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group endpoints\n@endpoint GET /endpoints/zdr\n@desc Preview the impact of ZDR on the available endpoints\n@returns(200) {data: [map]} # Returns a list of endpoints\n@errors {500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group files\n@endpoint GET /files\n@desc List files\n@optional {limit: int # Maximum number of files to return (1–1000)., cursor: str # Opaque pagination cursor from a previous response., workspace_id: str(uuid) # Workspace to scope the request to. Defaults to the caller’s default workspace.}\n@returns(200) {cursor: str?, data: [map], first_id: str?, has_more: bool, last_id: str?} # A page of files.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /files\n@desc Upload a file\n@optional {workspace_id: str(uuid) # Workspace to scope the request to. Defaults to the caller’s default workspace.}\n@returns(200) {created_at: str, downloadable: bool, filename: str, id: str, mime_type: str, size_bytes: int, type: str} # The uploaded file metadata.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 413: Payload Too Large - Request payload exceeds size limits, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endpoint DELETE /files/{file_id}\n@desc Delete a file\n@required {file_id: str}\n@optional {workspace_id: str(uuid) # Workspace to scope the request to. Defaults to the caller’s default workspace.}\n@returns(200) {id: str, type: str} # The file was deleted.\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /files/{file_id}\n@desc Get file metadata\n@required {file_id: str}\n@optional {workspace_id: str(uuid) # Workspace to scope the request to. Defaults to the caller’s default workspace.}\n@returns(200) {created_at: str, downloadable: bool, filename: str, id: str, mime_type: str, size_bytes: int, type: str} # The file metadata.\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /files/{file_id}/content\n@desc Download file content\n@required {file_id: str}\n@optional {workspace_id: str(uuid) # Workspace to scope the request to. Defaults to the caller’s default workspace.}\n@returns(200) The raw file content.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group generation\n@endpoint GET /generation\n@desc Get request & usage metadata for a generation\n@required {id: str # The generation ID}\n@returns(200) {data: map{api_type: str?, app_id: int?, cache_discount: num(double)?, cancelled: bool?, created_at: str, data_region: str, external_user: str?, finish_reason: str?, generation_time: num(double)?, http_referer: str?, id: str, is_byok: bool, latency: num(double)?, model: str, moderation_latency: num(double)?, native_finish_reason: str?, native_tokens_cached: int?, native_tokens_completion: int?, native_tokens_completion_images: int?, native_tokens_prompt: int?, native_tokens_reasoning: int?, num_fetches: int?, num_input_audio_prompt: int?, num_media_completion: int?, num_media_prompt: int?, num_search_results: int?, origin: str, preset_id: str?, provider_name: str?, provider_responses: [map]?, request_id: str?, response_cache_source_id: str?, router: str?, service_tier: str?, session_id: str?, streamed: bool?, tokens_completion: int?, tokens_prompt: int?, total_cost: num(double), upstream_id: str?, upstream_inference_cost: num(double)?, usage: num(double), user_agent: str?, web_search_engine: str?}} # Returns the request metadata for this generation\n@errors {401: Unauthorized - Authentication required or invalid credentials, 402: Payment Required - Insufficient credits or quota to complete request, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure, 524: Infrastructure Timeout - Provider request timed out at edge network, 529: Provider Overloaded - Provider is temporarily overloaded}\n\n@endpoint GET /generation/content\n@desc Get stored prompt and completion content for a generation\n@required {id: str # The generation ID}\n@returns(200) {data: map{input: any, output: map{completion: str?, reasoning: str?}}} # Returns the stored prompt and completion content\n@errors {401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure, 524: Infrastructure Timeout - Provider request timed out at edge network, 529: Provider Overloaded - Provider is temporarily overloaded}\n\n@endgroup\n\n@group guardrails\n@endpoint GET /guardrails\n@desc List guardrails\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100), workspace_id: str(uuid) # Filter guardrails by workspace ID. By default, guardrails in the default workspace are returned.}\n@returns(200) {data: [map], total_count: int} # List of guardrails\n@errors {401: Unauthorized - Authentication required or invalid credentials, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /guardrails\n@desc Create a guardrail\n@required {name: str # Name for the new guardrail}\n@optional {allowed_models: [str] # Array of model identifiers (slug or canonical_slug accepted), allowed_providers: [str] # List of allowed provider IDs, content_filter_builtins: [map{action!: str, label: str, scan_scope: str, slug!: str}] # Builtin content filters to apply. The \"flag\" action is only supported for \"regex-prompt-injection\"; PII slugs (email, phone, ssn, credit-card, ip-address, person-name, address) accept \"block\" or \"redact\" only., content_filters: [map{action!: str, label: str, pattern!: str}] # Custom regex content filters to apply to request messages, description: str # Description of the guardrail, enforce_zdr: bool # Deprecated. Use enforce_zdr_anthropic, enforce_zdr_openai, enforce_zdr_google, and enforce_zdr_other instead. When provided, its value is copied into any of those per-provider fields that are not explicitly specified on the request., enforce_zdr_anthropic: bool # Whether to enforce zero data retention for Anthropic models. Falls back to enforce_zdr when not provided., enforce_zdr_google: bool # Whether to enforce zero data retention for Google models. Falls back to enforce_zdr when not provided., enforce_zdr_openai: bool # Whether to enforce zero data retention for OpenAI models. Falls back to enforce_zdr when not provided., enforce_zdr_other: bool # Whether to enforce zero data retention for models that are not from Anthropic, OpenAI, or Google. Falls back to enforce_zdr when not provided., ignored_models: [str] # Array of model identifiers to exclude from routing (slug or canonical_slug accepted), ignored_providers: [str] # List of provider IDs to exclude from routing, limit_usd: num(double) # Spending limit in USD, reset_interval: str(daily/weekly/monthly) # Interval at which the limit resets (daily, weekly, monthly), workspace_id: str(uuid) # The workspace to create the guardrail in. Defaults to the default workspace if not provided.}\n@returns(201) {data: any} # Guardrail created successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 500: Internal Server Error - Unexpected server error}\n@example_request {\"allowed_models\":null,\"allowed_providers\":[\"openai\",\"anthropic\",\"deepseek\"],\"description\":\"A guardrail for limiting API usage\",\"enforce_zdr_anthropic\":true,\"enforce_zdr_google\":false,\"enforce_zdr_openai\":true,\"enforce_zdr_other\":false,\"ignored_models\":null,\"ignored_providers\":null,\"limit_usd\":50,\"name\":\"My New Guardrail\",\"reset_interval\":\"monthly\"}\n\n@endpoint DELETE /guardrails/{id}\n@desc Delete a guardrail\n@required {id: str(uuid) # The unique identifier of the guardrail to delete}\n@returns(200) {deleted: bool} # Guardrail deleted successfully\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /guardrails/{id}\n@desc Get a guardrail\n@required {id: str(uuid) # The unique identifier of the guardrail to retrieve}\n@returns(200) {data: any} # Guardrail details\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint PATCH /guardrails/{id}\n@desc Update a guardrail\n@required {id: str(uuid) # The unique identifier of the guardrail to update}\n@optional {allowed_models: [str] # Array of model identifiers (slug or canonical_slug accepted), allowed_providers: [str] # New list of allowed provider IDs, content_filter_builtins: [map{action!: str, label: str, scan_scope: str, slug!: str}] # Builtin content filters to apply. Set to null to remove. The \"flag\" action is only supported for \"regex-prompt-injection\"; PII slugs (email, phone, ssn, credit-card, ip-address, person-name, address) accept \"block\" or \"redact\" only., content_filters: [map{action!: str, label: str, pattern!: str}] # Custom regex content filters to apply. Set to null to remove., description: str # New description for the guardrail, enforce_zdr: bool # Deprecated. Use enforce_zdr_anthropic, enforce_zdr_openai, enforce_zdr_google, and enforce_zdr_other instead. When provided, its value is copied into any of those per-provider fields that are not explicitly specified on the request., enforce_zdr_anthropic: bool # Whether to enforce zero data retention for Anthropic models. Falls back to enforce_zdr when not provided., enforce_zdr_google: bool # Whether to enforce zero data retention for Google models. Falls back to enforce_zdr when not provided., enforce_zdr_openai: bool # Whether to enforce zero data retention for OpenAI models. Falls back to enforce_zdr when not provided., enforce_zdr_other: bool # Whether to enforce zero data retention for models that are not from Anthropic, OpenAI, or Google. Falls back to enforce_zdr when not provided., ignored_models: [str] # Array of model identifiers to exclude from routing (slug or canonical_slug accepted), ignored_providers: [str] # List of provider IDs to exclude from routing, limit_usd: num(double) # New spending limit in USD, name: str # New name for the guardrail, reset_interval: str(daily/weekly/monthly) # Interval at which the limit resets (daily, weekly, monthly)}\n@returns(200) {data: any} # Guardrail updated successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"description\":\"Updated description\",\"limit_usd\":75,\"name\":\"Updated Guardrail Name\",\"reset_interval\":\"weekly\"}\n\n@endpoint GET /guardrails/{id}/assignments/keys\n@desc List key assignments for a guardrail\n@required {id: str(uuid) # The unique identifier of the guardrail}\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100)}\n@returns(200) {data: [map], total_count: int} # List of key assignments\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /guardrails/{id}/assignments/keys\n@desc Bulk assign keys to a guardrail\n@required {id: str(uuid) # The unique identifier of the guardrail, key_hashes: [str] # Array of API key hashes to assign to the guardrail}\n@returns(200) {assigned_count: int} # Assignment result\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"key_hashes\":[\"c56454edb818d6b14bc0d61c46025f1450b0f4012d12304ab40aacb519fcbc93\"]}\n\n@endpoint POST /guardrails/{id}/assignments/keys/remove\n@desc Bulk unassign keys from a guardrail\n@required {id: str(uuid) # The unique identifier of the guardrail, key_hashes: [str] # Array of API key hashes to unassign from the guardrail}\n@returns(200) {unassigned_count: int} # Unassignment result\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"key_hashes\":[\"c56454edb818d6b14bc0d61c46025f1450b0f4012d12304ab40aacb519fcbc93\"]}\n\n@endpoint GET /guardrails/{id}/assignments/members\n@desc List member assignments for a guardrail\n@required {id: str(uuid) # The unique identifier of the guardrail}\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100)}\n@returns(200) {data: [map], total_count: int} # List of member assignments\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /guardrails/{id}/assignments/members\n@desc Bulk assign members to a guardrail\n@required {id: str(uuid) # The unique identifier of the guardrail, member_user_ids: [str] # Array of member user IDs to assign to the guardrail}\n@returns(200) {assigned_count: int} # Assignment result\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"member_user_ids\":[\"user_abc123\",\"user_def456\"]}\n\n@endpoint POST /guardrails/{id}/assignments/members/remove\n@desc Bulk unassign members from a guardrail\n@required {id: str(uuid) # The unique identifier of the guardrail, member_user_ids: [str] # Array of member user IDs to unassign from the guardrail}\n@returns(200) {unassigned_count: int} # Unassignment result\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"member_user_ids\":[\"user_abc123\",\"user_def456\"]}\n\n@endpoint GET /guardrails/assignments/keys\n@desc List all key assignments\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100)}\n@returns(200) {data: [map], total_count: int} # List of key assignments\n@errors {401: Unauthorized - Authentication required or invalid credentials, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /guardrails/assignments/members\n@desc List all member assignments\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100)}\n@returns(200) {data: [map], total_count: int} # List of member assignments\n@errors {401: Unauthorized - Authentication required or invalid credentials, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group images\n@endpoint POST /images\n@desc Generate an image\n@required {model: str # The image generation model to use, prompt: str # Text description of the desired image}\n@optional {aspect_ratio: str(1:1/1:2/1:4/1:8/2:1/2:3/3:2/3:4/4:1/4:3/4:5/5:4/8:1/9:16/16:9/9:19.5/19.5:9/9:20/20:9/9:21/21:9/auto) # Normalized aspect ratio of the generated image. Providers clamp to their supported subset., background: str(auto/transparent/opaque) # Background treatment. `transparent` requires an output_format that supports alpha (png or webp)., input_references: [map{image_url!: map, type!: str}] # Reference images to guide image-to-image generation, as base64 data URLs or HTTP(S) URLs., n: int # Number of images to generate (1-10). Providers that only support single-image generation reject n > 1., output_compression: int # Compression level (0-100) for webp/jpeg output. Ignored for png and by providers without a compression knob., output_format: str(png/jpeg/webp/svg) # Encoding of the returned image bytes. Most models produce raster formats (png, jpeg, webp). SVG is supported by vectorization models (e.g. Quiver) — the SVG markup is UTF-8 base64-encoded in `b64_json`., provider: map{options: any} # Provider-specific passthrough configuration, quality: str(auto/low/medium/high) # Rendering quality. Providers without a quality knob ignore this., resolution: str(512/1K/2K/4K) # Normalized resolution tier of the generated image. Concrete pixel dimensions are derived per-provider., seed: int # If specified, the generation will sample deterministically, such that repeated requests with the same seed and parameters should return the same result. Determinism is not guaranteed for all providers., size: str # Optional. A convenience shorthand for output dimensions — pass a tier (\"2K\", \"4K\") or explicit pixels (\"2048x2048\") and we normalize it to the right dimensions for the chosen provider. Interchangeable with resolution + aspect_ratio; use those directly for enumerated, per-model discoverable values. Conflicting size + resolution/aspect_ratio is rejected., stream: bool # If true, partial images are streamed as SSE events as they become available. Only supported by providers with native streaming (currently OpenAI). Non-streaming providers ignore this flag and return a buffered response.}\n@returns(200) {created: int, data: [map], usage: map{completion_tokens: int, completion_tokens_details: map?{audio_tokens: int?, image_tokens: int?, reasoning_tokens: int?}, cost: num(double)?, cost_details: map?{upstream_inference_completions_cost: num(double), upstream_inference_cost: num(double)?, upstream_inference_prompt_cost: num(double)}, is_byok: bool, iterations: [any]?, prompt_tokens: int, prompt_tokens_details: map?{audio_tokens: int?, cache_write_tokens: int?, cached_tokens: int?, file_tokens: int?, video_tokens: int?}, server_tool_use: map?{tool_calls_executed: int?, tool_calls_requested: int?, web_search_requests: int?}, service_tier: str?, speed: str?, total_tokens: int}} # Image generation response\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 402: Payment Required - Insufficient credits or quota to complete request, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure, 524: Infrastructure Timeout - Provider request timed out at edge network, 529: Provider Overloaded - Provider is temporarily overloaded}\n@example_request {\"model\":\"bytedance-seed/seedream-4.5\",\"prompt\":\"a red panda astronaut floating in space, studio lighting\"}\n\n@endpoint GET /images/models\n@desc List image generation models\n@returns(200) {data: [map]} # List of image generation models\n@errors {500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /images/models/{author}/{slug}/endpoints\n@desc List endpoints for an image model\n@required {author: str # Model author/organization, slug: str # Model slug}\n@returns(200) {endpoints: [map], id: str} # The full per-endpoint records for an image model\n@errors {404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group key\n@endpoint GET /key\n@desc Get current API key\n@returns(200) {data: map{byok_usage: num(double), byok_usage_daily: num(double), byok_usage_monthly: num(double), byok_usage_weekly: num(double), creator_user_id: str?, expires_at: str(date-time)?, include_byok_in_limit: bool, is_free_tier: bool, is_management_key: bool, is_provisioning_key: bool, label: str, limit: num(double)?, limit_remaining: num(double)?, limit_reset: str?, rate_limit: map{interval: str, note: str, requests: int}, usage: num(double), usage_daily: num(double), usage_monthly: num(double), usage_weekly: num(double)}} # API key details\n@errors {401: Unauthorized - Authentication required or invalid credentials, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group keys\n@endpoint GET /keys\n@desc List API keys\n@optional {include_disabled: bool # Whether to include disabled API keys in the response, offset: int # Number of API keys to skip for pagination, workspace_id: str(uuid) # Filter API keys by workspace ID. By default, keys in the default workspace are returned.}\n@returns(200) {data: [map]} # List of API keys\n@errors {401: Unauthorized - Authentication required or invalid credentials, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /keys\n@desc Create a new API key\n@required {name: str # Name for the new API key}\n@optional {creator_user_id: str # Optional user ID of the key creator. Only meaningful for organization-owned keys where a specific member is creating the key., expires_at: str(date-time) # Optional ISO 8601 UTC timestamp when the API key should expire. Must be UTC, other timezones will be rejected, include_byok_in_limit: bool # Whether to include BYOK usage in the limit, limit: num(double) # Optional spending limit for the API key in USD, limit_reset: str(daily/weekly/monthly) # Type of limit reset for the API key (daily, weekly, monthly, or null for no reset). Resets happen automatically at midnight UTC, and weeks are Monday through Sunday., workspace_id: str(uuid) # The workspace to create the API key in. Defaults to the default workspace if not provided.}\n@returns(201) {data: map{byok_usage: num(double), byok_usage_daily: num(double), byok_usage_monthly: num(double), byok_usage_weekly: num(double), created_at: str, creator_user_id: str?, disabled: bool, expires_at: str(date-time)?, hash: str, include_byok_in_limit: bool, label: str, limit: num(double)?, limit_remaining: num(double)?, limit_reset: str?, name: str, updated_at: str?, usage: num(double), usage_daily: num(double), usage_monthly: num(double), usage_weekly: num(double), workspace_id: str}, key: str} # API key created successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n@example_request {\"expires_at\":\"2027-12-31T23:59:59Z\",\"include_byok_in_limit\":true,\"limit\":50,\"limit_reset\":\"monthly\",\"name\":\"My New API Key\"}\n\n@endpoint DELETE /keys/{hash}\n@desc Delete an API key\n@required {hash: str # The hash identifier of the API key to delete}\n@returns(200) {deleted: bool} # API key deleted successfully\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /keys/{hash}\n@desc Get a single API key\n@required {hash: str # The hash identifier of the API key to retrieve}\n@returns(200) {data: map{byok_usage: num(double), byok_usage_daily: num(double), byok_usage_monthly: num(double), byok_usage_weekly: num(double), created_at: str, creator_user_id: str?, disabled: bool, expires_at: str(date-time)?, hash: str, include_byok_in_limit: bool, label: str, limit: num(double)?, limit_remaining: num(double)?, limit_reset: str?, name: str, updated_at: str?, usage: num(double), usage_daily: num(double), usage_monthly: num(double), usage_weekly: num(double), workspace_id: str}} # API key details\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n\n@endpoint PATCH /keys/{hash}\n@desc Update an API key\n@required {hash: str # The hash identifier of the API key to update}\n@optional {disabled: bool # Whether to disable the API key, include_byok_in_limit: bool # Whether to include BYOK usage in the limit, limit: num(double) # New spending limit for the API key in USD, limit_reset: str(daily/weekly/monthly) # New limit reset type for the API key (daily, weekly, monthly, or null for no reset). Resets happen automatically at midnight UTC, and weeks are Monday through Sunday., name: str # New name for the API key}\n@returns(200) {data: map{byok_usage: num(double), byok_usage_daily: num(double), byok_usage_monthly: num(double), byok_usage_weekly: num(double), created_at: str, creator_user_id: str?, disabled: bool, expires_at: str(date-time)?, hash: str, include_byok_in_limit: bool, label: str, limit: num(double)?, limit_remaining: num(double)?, limit_reset: str?, name: str, updated_at: str?, usage: num(double), usage_daily: num(double), usage_monthly: num(double), usage_weekly: num(double), workspace_id: str}} # API key updated successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n@example_request {\"disabled\":false,\"include_byok_in_limit\":true,\"limit\":75,\"limit_reset\":\"daily\",\"name\":\"Updated API Key Name\"}\n\n@endgroup\n\n@group messages\n@endpoint POST /messages\n@desc Create a message\n@required {messages: [map{content!: any, role!: str}], model: str}\n@optional {X-OpenRouter-Metadata: str # Opt-in to surface routing metadata on the response under `openrouter_metadata`. Defaults to `disabled`. The legacy header `X-OpenRouter-Experimental-Metadata` is also accepted for backward compatibility., cache_control: map{ttl: str, type!: str} # Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models., context_management: map{edits: [any]}, fallbacks: [map{model!: str}] # Fallback models to try if the primary model fails or refuses, in order. Handled by OpenRouter multi-model routing rather than Anthropic server-side fallbacks; cannot be combined with `models`. Each entry accepts only `model`. Maximum of 3 entries., max_tokens: int, metadata: map{user_id: str}, models: [str], output_config: map{effort: str, format: map, task_budget: map} # Configuration for controlling output behavior. Supports the effort parameter and structured output format., plugins: [any] # Plugins you want to enable for this request, including their settings., provider: map{allow_fallbacks: bool, data_collection: str, enforce_distillable_text: bool, ignore: [any], max_price: map, only: [any], order: [any], preferred_max_latency: any, preferred_min_throughput: any, quantizations: [str], require_parameters: bool, sort: any, zdr: bool} # When multiple model providers are available, optionally indicate your routing preference., route: str(fallback/sort) # **DEPRECATED** Use providers.sort.partition instead. Backwards-compatible alias for providers.sort.partition. Accepts legacy values: \"fallback\" (maps to \"model\"), \"sort\" (maps to \"none\")., service_tier: str, session_id: str # A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters., speed: any, stop_sequences: [str], stop_server_tools_when: [any] # Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`., stream: bool, system: any, temperature: num(double), thinking: any, tool_choice: any, tools: [any], top_k: int, top_p: num(double), trace: map{generation_name: str, parent_span_id: str, span_name: str, trace_id: str, trace_name: str} # Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations., user: str # A unique identifier representing your end-user, which helps distinguish between different users of your app. This allows your app to identify specific users in case of abuse reports, preventing your entire app from being affected by the actions of individual users. Maximum of 256 characters.}\n@returns(200) Successful response\n@errors {400: Invalid request error, 401: Authentication error, 403: Forbidden - Authentication successful but insufficient permissions, or a guardrail blocked the request. When guardrails block and the `X-OpenRouter-Metadata: enabled` header is present, the response includes `openrouter_metadata` with full routing context and a `pipeline` array containing guardrail stage details., 404: Not found error, 429: Rate limit error, 500: API error, 503: Overloaded error, 529: Overloaded error}\n@example_request {\"max_tokens\":1024,\"messages\":[{\"content\":\"Hello, how are you?\",\"role\":\"user\"}],\"model\":\"anthropic/claude-sonnet-4\"}\n\n@endgroup\n\n@group model\n@endpoint GET /model/{author}/{slug}\n@desc Get a model by its slug\n@required {author: str # The author/organization of the model, slug: str # The model slug, optionally including a variant suffix (e.g. gpt-4 or gpt-4:free)}\n@returns(200) {data: map{architecture: map{input_modalities: [str], instruct_type: str?, modality: str?, output_modalities: [str], tokenizer: str}, benchmarks: map{artificial_analysis: map{agentic_index: num(double)?, coding_index: num(double)?, intelligence_index: num(double)?}, design_arena: [map]}, canonical_slug: str, context_length: int?, created: int, default_parameters: map?{frequency_penalty: num(double)?, presence_penalty: num(double)?, repetition_penalty: num(double)?, temperature: num(double)?, top_k: int?, top_p: num(double)?}, description: str, expiration_date: str?, hugging_face_id: str?, id: str, knowledge_cutoff: str?, links: map{details: str}, name: str, per_request_limits: map?{completion_tokens: num, prompt_tokens: num}, pricing: map{audio: str, audio_output: str, completion: str, discount: num(double), image: str, image_output: str, image_token: str, input_audio_cache: str, input_cache_read: str, input_cache_write: str, input_cache_write_1h: str, internal_reasoning: str, prompt: str, request: str, web_search: str}, reasoning: map{default_effort: any, default_enabled: bool, mandatory: bool, supported_efforts: [str]?, supports_max_tokens: bool}, supported_parameters: [str], supported_voices: [str]?, top_provider: map{context_length: int?, is_moderated: bool, max_completion_tokens: int?}}} # Returns the model details\n@errors {404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group models\n@endpoint GET /models\n@desc List all models and their properties\n@optional {category: str(programming/roleplay/marketing/marketing/seo/technology/science/translation/legal/finance/health/trivia/academia) # Filter models by use case category, supported_parameters: str # Filter models by supported parameter (comma-separated), output_modalities: str # Filter models by output modality. Accepts a comma-separated list of modalities (text, image, audio, embeddings) or \"all\" to include all models. Defaults to \"text\"., sort: str(most-popular/newest/top-weekly/pricing-low-to-high/pricing-high-to-low/context-high-to-low/throughput-high-to-low/latency-low-to-high/intelligence-high-to-low/design-arena-elo-high-to-low) # Sort the returned models server-side. Prefer this over fetching the full list and sorting client-side. Options: pricing-low-to-high, pricing-high-to-low (average prompt/completion price), context-high-to-low (context length), throughput-high-to-low, latency-low-to-high (recent median performance), most-popular, top-weekly (tokens processed in the last week), newest (creation date), intelligence-high-to-low (Artificial Analysis intelligence index), design-arena-elo-high-to-low (best Design Arena ELO across arenas). Models without a score for the chosen benchmark are placed last. When omitted, the existing default ordering is preserved., q: str # Free-text search by model name or slug., input_modalities: str # Filter models by input modality. Comma-separated list of: text, image, audio, file., context: int # Minimum context length (tokens). Models with smaller context are excluded., min_price: num # Minimum prompt price in $/M tokens., max_price: num # Maximum prompt price in $/M tokens., arch: str # Filter models by architecture/model family (e.g. GPT, Claude, Gemini, Llama)., model_authors: str # Filter models by the organization that created the model. Comma-separated list of author slugs., providers: str # Filter models by hosting provider. Comma-separated list of provider names., distillable: str(true/false) # Filter by distillation capability. \"true\" returns only distillable models, \"false\" excludes them., zdr: str # When set to \"true\", return only models with zero data retention endpoints., region: str # Filter to models with endpoints in the given data region. Currently only \"eu\" is supported.}\n@returns(200) {data: [map]} # Returns a list of models or RSS feed\n@errors {400: Bad Request - Invalid request parameters or malformed input, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /models/{author}/{slug}/endpoints\n@desc List all endpoints for a model\n@required {author: str # The author/organization of the model, slug: str # The model slug}\n@returns(200) {data: map{architecture: any, created: int, description: str, endpoints: [map], id: str, name: str}} # Returns a list of endpoints\n@errors {404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /models/count\n@desc Get total count of available models\n@optional {output_modalities: str # Filter models by output modality. Accepts a comma-separated list of modalities (text, image, audio, embeddings) or \"all\" to include all models. Defaults to \"text\".}\n@returns(200) {data: map{count: int}} # Returns the total count of available models\n@errors {400: Bad Request - Invalid request parameters or malformed input, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /models/user\n@desc List models filtered by user provider preferences, privacy settings, and guardrails\n@returns(200) {data: [map]} # Returns a list of models filtered by user provider preferences\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group observability\n@endpoint GET /observability/destinations\n@desc List observability destinations\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100), workspace_id: str(uuid) # Optional workspace ID to filter by. Defaults to the authenticated entity's default workspace.}\n@returns(200) {data: [any], total_count: int} # List of observability destinations\n@errors {401: Unauthorized - Authentication required or invalid credentials, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /observability/destinations\n@desc Create an observability destination\n@required {config: map # Provider-specific configuration. The shape depends on `type` and is validated server-side., name: str # Human-readable name for the destination., type: str(arize/braintrust/clickhouse/datadog/grafana/langfuse/langsmith/newrelic/opik/otel-collector/posthog/ramp/s3/sentry/snowflake/weave/webhook) # The destination type. Only stable destination types are accepted.}\n@optional {api_key_hashes: [str] # Optional allowlist of OpenRouter API key hashes whose traffic is forwarded. `null` or omitted means all keys. Must contain at least one hash if provided., enabled: bool=true # Whether this destination should be enabled immediately., filter_rules: map{enabled: bool, groups!: [map]} # Optional structured filter rules controlling which events are forwarded., privacy_mode: bool=false # When true, request/response bodies are not forwarded — only metadata., sampling_rate: num(double) # Sampling rate between 0.0001 and 1 (1 = 100%)., workspace_id: str(uuid) # Optional workspace ID. Defaults to the authenticated entity's default workspace.}\n@returns(201) {data: any} # Destination created successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 409: Conflict - Resource conflict or concurrent modification, 500: Internal Server Error - Unexpected server error}\n@example_request {\"config\":{\"baseUrl\":\"https://us.cloud.langfuse.com\",\"publicKey\":\"pk-l...EfGh\",\"secretKey\":\"sk-l...AbCd\"},\"name\":\"Production Langfuse\",\"type\":\"langfuse\"}\n\n@endpoint DELETE /observability/destinations/{id}\n@desc Delete an observability destination\n@required {id: str(uuid) # The destination ID (UUID).}\n@returns(200) {deleted: bool} # Destination deleted successfully\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /observability/destinations/{id}\n@desc Get an observability destination\n@required {id: str(uuid) # The destination ID (UUID).}\n@returns(200) {data: any} # The observability destination\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint PATCH /observability/destinations/{id}\n@desc Update an observability destination\n@required {id: str(uuid) # The destination ID (UUID).}\n@optional {api_key_hashes: [str] # Optional allowlist of OpenRouter API key hashes. `null` clears the filter (all keys). Omitting leaves the current value. Must contain at least one hash if provided., config: map # Provider-specific configuration fields to update. Masked values are ignored; unset fields keep their current value., enabled: bool # Whether the destination is enabled., filter_rules: any, name: str # Human-readable name for the destination., privacy_mode: bool # When true, request/response bodies are not forwarded — only metadata., sampling_rate: num(double) # Sampling rate between 0.0001 and 1 (1 = 100%).}\n@returns(200) {data: any} # Destination updated successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 409: Conflict - Resource conflict or concurrent modification, 500: Internal Server Error - Unexpected server error}\n@example_request {\"enabled\":false,\"name\":\"Updated Langfuse\"}\n\n@endgroup\n\n@group organization\n@endpoint GET /organization/members\n@desc List organization members\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100)}\n@returns(200) {data: [map], total_count: int} # List of organization members\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group presets\n@endpoint GET /presets\n@desc List presets\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100)}\n@returns(200) {data: [map], total_count: int} # Paginated list of presets.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /presets/{slug}\n@desc Get a preset\n@required {slug: str # URL-safe slug identifying the preset.}\n@returns(200) {data: any} # Preset with its designated version.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /presets/{slug}/chat/completions\n@desc Create a preset from a chat-completions request body\n@required {slug: str # URL-safe slug identifying the preset. Created if it does not exist., messages: [any] # List of messages for the conversation}\n@optional {cache_control: map{ttl: str, type!: str} # Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models., debug: map{echo_upstream_body: bool} # Debug options for inspecting request transformations (streaming only), frequency_penalty: num(double) # Frequency penalty (-2.0 to 2.0), image_config: map # Provider-specific image configuration options. Keys and values vary by model/provider. See https://openrouter.ai/docs/guides/overview/multimodal/image-generation for more details., logit_bias: map # Token logit bias adjustments, logprobs: bool # Return log probabilities, max_completion_tokens: int # Maximum tokens in completion, max_tokens: int # Maximum tokens (deprecated, use max_completion_tokens). Note: some providers enforce a minimum of 16., metadata: map # Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values), min_p: num(double) # Minimum probability threshold relative to the most likely token. Tokens with probability below min_p * (probability of top token) are filtered out. Not all providers support this parameter., modalities: [str] # Output modalities for the response. Supported values are \"text\", \"image\", and \"audio\"., model: str # Model to use for completion, models: [any] # Models to use for completion, parallel_tool_calls: bool # Whether to enable parallel function calling during tool use. When true, the model may generate multiple tool calls in a single response., plugins: [any] # Plugins you want to enable for this request, including their settings., presence_penalty: num(double) # Presence penalty (-2.0 to 2.0), provider: map{allow_fallbacks: bool, data_collection: str, enforce_distillable_text: bool, ignore: [any], max_price: map, only: [any], order: [any], preferred_max_latency: any, preferred_min_throughput: any, quantizations: [str], require_parameters: bool, sort: any, zdr: bool} # When multiple model providers are available, optionally indicate your routing preference., reasoning: map{effort: str, summary: str} # Configuration options for reasoning models, reasoning_effort: str(max/xhigh/high/medium/low/minimal/none) # Shorthand for setting reasoning effort. Equivalent to setting reasoning.effort. Cannot be used simultaneously with reasoning.effort if they differ., repetition_penalty: num(double) # Penalizes tokens based on how much they have already appeared in the text. A value of 1.0 means no penalty. Values above 1.0 penalize repeated tokens more strongly. Not all providers support this parameter., response_format: any # Response format configuration, route: str(fallback/sort) # **DEPRECATED** Use providers.sort.partition instead. Backwards-compatible alias for providers.sort.partition. Accepts legacy values: \"fallback\" (maps to \"model\"), \"sort\" (maps to \"none\")., seed: int # Random seed for deterministic outputs, service_tier: str(auto/default/flex/priority/scale) # The service tier to use for processing this request., session_id: str # A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters., stop: any # Stop sequences (up to 4), stop_server_tools_when: [any] # Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`., stream: bool=false # Enable streaming response, stream_options: map{include_usage: bool} # Streaming configuration options, temperature: num(double) # Sampling temperature (0-2), tool_choice: any # Tool choice configuration, tools: [any] # Available tools for function calling, top_a: num(double) # Consider only tokens with \"sufficiently high\" probabilities based on the probability of the most likely token. Not all providers support this parameter., top_k: int # Limits the model to choose from the top K most likely tokens at each step. A value of 1 means the model will always pick the most likely next token. Not all providers support this parameter., top_logprobs: int # Number of top log probabilities to return (0-20), top_p: num(double) # Nucleus sampling parameter (0-1), trace: map{generation_name: str, parent_span_id: str, span_name: str, trace_id: str, trace_name: str} # Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations., user: str # Unique user identifier}\n@returns(200) {data: any} # Preset created or updated successfully.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 409: Conflict - Resource conflict or concurrent modification, 500: Internal Server Error - Unexpected server error}\n@example_request {\"messages\":[{\"content\":\"You are a helpful assistant.\",\"role\":\"system\"},{\"content\":\"Hello!\",\"role\":\"user\"}],\"model\":\"openai/gpt-5.4\",\"temperature\":0.7}\n\n@endpoint POST /presets/{slug}/messages\n@desc Create a preset from a messages request body\n@required {slug: str # URL-safe slug identifying the preset. Created if it does not exist., messages: [map{content!: any, role!: str}], model: str}\n@optional {cache_control: map{ttl: str, type!: str} # Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models., context_management: map{edits: [any]}, fallbacks: [map{model!: str}] # Fallback models to try if the primary model fails or refuses, in order. Handled by OpenRouter multi-model routing rather than Anthropic server-side fallbacks; cannot be combined with `models`. Each entry accepts only `model`. Maximum of 3 entries., max_tokens: int, metadata: map{user_id: str}, models: [str], output_config: map{effort: str, format: map, task_budget: map} # Configuration for controlling output behavior. Supports the effort parameter and structured output format., plugins: [any] # Plugins you want to enable for this request, including their settings., provider: map{allow_fallbacks: bool, data_collection: str, enforce_distillable_text: bool, ignore: [any], max_price: map, only: [any], order: [any], preferred_max_latency: any, preferred_min_throughput: any, quantizations: [str], require_parameters: bool, sort: any, zdr: bool} # When multiple model providers are available, optionally indicate your routing preference., route: str(fallback/sort) # **DEPRECATED** Use providers.sort.partition instead. Backwards-compatible alias for providers.sort.partition. Accepts legacy values: \"fallback\" (maps to \"model\"), \"sort\" (maps to \"none\")., service_tier: str, session_id: str # A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters., speed: any, stop_sequences: [str], stop_server_tools_when: [any] # Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`., stream: bool, system: any, temperature: num(double), thinking: any, tool_choice: any, tools: [any], top_k: int, top_p: num(double), trace: map{generation_name: str, parent_span_id: str, span_name: str, trace_id: str, trace_name: str} # Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations., user: str # A unique identifier representing your end-user, which helps distinguish between different users of your app. This allows your app to identify specific users in case of abuse reports, preventing your entire app from being affected by the actions of individual users. Maximum of 256 characters.}\n@returns(200) {data: any} # Preset created or updated successfully.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 409: Conflict - Resource conflict or concurrent modification, 500: Internal Server Error - Unexpected server error}\n@example_request {\"max_tokens\":1024,\"messages\":[{\"content\":\"Hello!\",\"role\":\"user\"}],\"model\":\"anthropic/claude-4.6-sonnet\",\"system\":\"You are a helpful assistant.\"}\n\n@endpoint POST /presets/{slug}/responses\n@desc Create a preset from a responses request body\n@required {slug: str # URL-safe slug identifying the preset. Created if it does not exist.}\n@optional {background: bool, cache_control: map{ttl: str, type!: str} # Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models., debug: map{echo_upstream_body: bool} # Debug options for inspecting request transformations (streaming only), frequency_penalty: num(double), image_config: map # Provider-specific image configuration options. Keys and values vary by model/provider. See https://openrouter.ai/docs/guides/overview/multimodal/image-generation for more details., include: [str], input: any # Input for a response request - can be a string or array of items, instructions: str, max_output_tokens: int, max_tool_calls: int, metadata: map # Metadata key-value pairs for the request. Keys must be ≤64 characters and cannot contain brackets. Values must be ≤512 characters. Maximum 16 pairs allowed., modalities: [str] # Output modalities for the response. Supported values are \"text\" and \"image\"., model: str, models: [str], parallel_tool_calls: bool, plugins: [any] # Plugins you want to enable for this request, including their settings., presence_penalty: num(double), previous_response_id: str, prompt: map{id!: str, variables: map}, prompt_cache_key: str, provider: map{allow_fallbacks: bool, data_collection: str, enforce_distillable_text: bool, ignore: [any], max_price: map, only: [any], order: [any], preferred_max_latency: any, preferred_min_throughput: any, quantizations: [str], require_parameters: bool, sort: any, zdr: bool} # When multiple model providers are available, optionally indicate your routing preference., reasoning: any # Configuration for reasoning mode in the response, route: str(fallback/sort) # **DEPRECATED** Use providers.sort.partition instead. Backwards-compatible alias for providers.sort.partition. Accepts legacy values: \"fallback\" (maps to \"model\"), \"sort\" (maps to \"none\")., safety_identifier: str, service_tier: str(auto/default/flex/priority/scale)=auto, session_id: str # A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters., stop_server_tools_when: [any] # Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`., store: bool=false, stream: bool=false, temperature: num(double), text: any # Text output configuration including format and verbosity, tool_choice: any, tools: [any], top_k: int, top_logprobs: int, top_p: num(double), trace: map{generation_name: str, parent_span_id: str, span_name: str, trace_id: str, trace_name: str} # Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations., truncation: str(auto/disabled), user: str # A unique identifier representing your end-user, which helps distinguish between different users of your app. This allows your app to identify specific users in case of abuse reports, preventing your entire app from being affected by the actions of individual users. Maximum of 256 characters.}\n@returns(200) {data: any} # Preset created or updated successfully.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 409: Conflict - Resource conflict or concurrent modification, 500: Internal Server Error - Unexpected server error}\n@example_request {\"input\":\"Hello!\",\"instructions\":\"You are a helpful assistant.\",\"model\":\"openai/gpt-5.4\"}\n\n@endpoint GET /presets/{slug}/versions\n@desc List versions of a preset\n@required {slug: str # URL-safe slug identifying the preset.}\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100)}\n@returns(200) {data: [map], total_count: int} # Paginated list of preset versions.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /presets/{slug}/versions/{version}\n@desc Get a specific version of a preset\n@required {slug: str # URL-safe slug identifying the preset., version: str # Version number of the preset.}\n@returns(200) {data: map?{config: map, created_at: str, creator_id: str, id: str, preset_id: str, system_prompt: str?, updated_at: str, version: int}} # The requested preset version.\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group providers\n@endpoint GET /providers\n@desc List all providers\n@returns(200) {data: [map]} # Returns a list of providers\n@errors {500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group rerank\n@endpoint POST /rerank\n@desc Submit a rerank request\n@required {documents: [any] # The list of documents to rerank. Documents may be plain strings, or structured objects with `text` and/or `image` for multimodal models., model: str # The rerank model to use, query: str # The search query to rerank documents against}\n@optional {provider: any, top_n: int # Number of most relevant documents to return}\n@returns(200) {id: str, model: str, provider: str, results: [map], usage: map{cost: num(double), search_units: int, total_tokens: int}} # Rerank response\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 402: Payment Required - Insufficient credits or quota to complete request, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure, 503: Service Unavailable - Service temporarily unavailable, 524: Infrastructure Timeout - Provider request timed out at edge network, 529: Provider Overloaded - Provider is temporarily overloaded}\n\n@endgroup\n\n@group responses\n@endpoint POST /responses\n@desc Create a response\n@optional {X-OpenRouter-Metadata: str # Opt-in to surface routing metadata on the response under `openrouter_metadata`. Defaults to `disabled`. The legacy header `X-OpenRouter-Experimental-Metadata` is also accepted for backward compatibility., background: bool, cache_control: map{ttl: str, type!: str} # Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models., debug: map{echo_upstream_body: bool} # Debug options for inspecting request transformations (streaming only), frequency_penalty: num(double), image_config: map # Provider-specific image configuration options. Keys and values vary by model/provider. See https://openrouter.ai/docs/guides/overview/multimodal/image-generation for more details., include: [str], input: any # Input for a response request - can be a string or array of items, instructions: str, max_output_tokens: int, max_tool_calls: int, metadata: map # Metadata key-value pairs for the request. Keys must be ≤64 characters and cannot contain brackets. Values must be ≤512 characters. Maximum 16 pairs allowed., modalities: [str] # Output modalities for the response. Supported values are \"text\" and \"image\"., model: str, models: [str], parallel_tool_calls: bool, plugins: [any] # Plugins you want to enable for this request, including their settings., presence_penalty: num(double), previous_response_id: str, prompt: map{id!: str, variables: map}, prompt_cache_key: str, provider: map{allow_fallbacks: bool, data_collection: str, enforce_distillable_text: bool, ignore: [any], max_price: map, only: [any], order: [any], preferred_max_latency: any, preferred_min_throughput: any, quantizations: [str], require_parameters: bool, sort: any, zdr: bool} # When multiple model providers are available, optionally indicate your routing preference., reasoning: any # Configuration for reasoning mode in the response, route: str(fallback/sort) # **DEPRECATED** Use providers.sort.partition instead. Backwards-compatible alias for providers.sort.partition. Accepts legacy values: \"fallback\" (maps to \"model\"), \"sort\" (maps to \"none\")., safety_identifier: str, service_tier: str(auto/default/flex/priority/scale)=auto, session_id: str # A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters., stop_server_tools_when: [any] # Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`., store: bool=false, stream: bool=false, temperature: num(double), text: any # Text output configuration including format and verbosity, tool_choice: any, tools: [any], top_k: int, top_logprobs: int, top_p: num(double), trace: map{generation_name: str, parent_span_id: str, span_name: str, trace_id: str, trace_name: str} # Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations., truncation: str(auto/disabled), user: str # A unique identifier representing your end-user, which helps distinguish between different users of your app. This allows your app to identify specific users in case of abuse reports, preventing your entire app from being affected by the actions of individual users. Maximum of 256 characters.}\n@returns(200) Successful response\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 402: Payment Required - Insufficient credits or quota to complete request, 403: Forbidden - Authentication successful but insufficient permissions, or a guardrail blocked the request. When guardrails block and the `X-OpenRouter-Metadata: enabled` header is present, the response includes `openrouter_metadata` with full routing context and a `pipeline` array containing guardrail stage details., 404: Not Found - Resource does not exist, 408: Request Timeout - Operation exceeded time limit, 413: Payload Too Large - Request payload exceeds size limits, 422: Unprocessable Entity - Semantic validation failure, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure, 503: Service Unavailable - Service temporarily unavailable, 524: Infrastructure Timeout - Provider request timed out at edge network, 529: Provider Overloaded - Provider is temporarily overloaded}\n@example_request {\"input\":\"Tell me a joke\",\"model\":\"openai/gpt-4o\"}\n\n@endgroup\n\n@group videos\n@endpoint POST /videos\n@desc Submit a video generation request\n@required {model: str, prompt: str}\n@optional {aspect_ratio: str(16:9/9:16/1:1/4:3/3:4/3:2/2:3/21:9/9:21) # Aspect ratio of the generated video, callback_url: str(uri) # URL to receive a webhook notification when the video generation job completes. Overrides the workspace-level default callback URL if set. Must be HTTPS., duration: int # Duration of the generated video in seconds, frame_images: [any] # Images to use as the first and/or last frame of the generated video. Each image must specify a frame_type of first_frame or last_frame., generate_audio: bool # Whether to generate audio alongside the video. Defaults to the endpoint's generate_audio capability flag, false if not set., input_references: [any] # Reference assets to guide video generation. Accepts image, audio, and video references. Audio and video references are only honored by providers that support them (currently BytePlus Seedance 2.0); other providers use image references and ignore the rest., provider: map{options: any} # Provider-specific passthrough configuration, resolution: str(480p/720p/1080p/1K/2K/4K) # Resolution of the generated video, seed: int # If specified, the generation will sample deterministically, such that repeated requests with the same seed and parameters should return the same result. Determinism is not guaranteed for all providers., size: str # Exact pixel dimensions of the generated video in \"WIDTHxHEIGHT\" format (e.g. \"1280x720\"). Interchangeable with resolution + aspect_ratio.}\n@returns(202) {error: str, generation_id: str, id: str, polling_url: str, status: str, unsigned_urls: [str], usage: map{cost: num(double)?, is_byok: bool}} # Video generation request accepted\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 402: Payment Required - Insufficient credits or quota to complete request, 404: Not Found - Resource does not exist, 429: Too Many Requests - Rate limit exceeded, 500: Internal Server Error - Unexpected server error}\n@example_request {\"aspect_ratio\":\"16:9\",\"duration\":8,\"model\":\"google/veo-3.1\",\"prompt\":\"A serene mountain landscape at sunset\",\"resolution\":\"720p\"}\n\n@endpoint GET /videos/{jobId}\n@desc Poll video generation status\n@required {jobId: str}\n@returns(200) {error: str, generation_id: str, id: str, polling_url: str, status: str, unsigned_urls: [str], usage: map{cost: num(double)?, is_byok: bool}} # Video generation status\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /videos/{jobId}/content\n@desc Download generated video content\n@required {jobId: str}\n@optional {index: int=0}\n@returns(200) Video content stream. The body is the raw video bytes proxied from the upstream provider, and the Content-Type reflects the provider media type (video/mp4).\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error, 502: Bad Gateway - Provider/upstream API failure}\n\n@endpoint GET /videos/models\n@desc List all video generation models\n@returns(200) {data: [map]} # Returns a list of video generation models\n@errors {400: Bad Request - Invalid request parameters or malformed input, 500: Internal Server Error - Unexpected server error}\n\n@endgroup\n\n@group workspaces\n@endpoint GET /workspaces\n@desc List workspaces\n@optional {offset: int # Number of records to skip for pagination, limit: int # Maximum number of records to return (max 100)}\n@returns(200) {data: [map], total_count: int} # List of workspaces\n@errors {401: Unauthorized - Authentication required or invalid credentials, 500: Internal Server Error - Unexpected server error}\n\n@endpoint POST /workspaces\n@desc Create a workspace\n@required {name: str # Name for the new workspace, slug: str # URL-friendly slug (lowercase alphanumeric segments separated by single hyphens, no leading/trailing hyphens)}\n@optional {default_image_model: str # Default image model for this workspace, default_provider_sort: str # Default provider sort preference (price, throughput, latency, exacto), default_text_model: str # Default text model for this workspace, description: str # Description of the workspace, io_logging_api_key_ids: [int] # Optional array of API key IDs to filter I/O logging, io_logging_sampling_rate: num(double) # Sampling rate for I/O logging (0.0001-1), is_data_discount_logging_enabled: bool # Whether data discount logging is enabled, is_observability_broadcast_enabled: bool # Whether broadcast is enabled, is_observability_io_logging_enabled: bool # Whether private logging is enabled}\n@returns(201) {data: any} # Workspace created successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 500: Internal Server Error - Unexpected server error}\n@example_request {\"default_image_model\":\"openai/dall-e-3\",\"default_provider_sort\":\"price\",\"default_text_model\":\"openai/gpt-4o\",\"description\":\"Production environment workspace\",\"name\":\"Production\",\"slug\":\"production\"}\n\n@endpoint DELETE /workspaces/{id}\n@desc Delete a workspace\n@required {id: str # The workspace ID (UUID) or slug}\n@returns(200) {deleted: bool} # Workspace deleted successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint GET /workspaces/{id}\n@desc Get a workspace\n@required {id: str # The workspace ID (UUID) or slug}\n@returns(200) {data: any} # Workspace details\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint PATCH /workspaces/{id}\n@desc Update a workspace\n@required {id: str # The workspace ID (UUID) or slug}\n@optional {default_image_model: str # Default image model for this workspace, default_provider_sort: str # Default provider sort preference (price, throughput, latency, exacto), default_text_model: str # Default text model for this workspace, description: str # New description for the workspace, io_logging_api_key_ids: [int] # Optional array of API key IDs to filter I/O logging, io_logging_sampling_rate: num(double) # Sampling rate for I/O logging (0.0001-1), is_data_discount_logging_enabled: bool # Whether data discount logging is enabled, is_observability_broadcast_enabled: bool # Whether broadcast is enabled, is_observability_io_logging_enabled: bool # Whether private logging is enabled, name: str # New name for the workspace, slug: str # New URL-friendly slug (lowercase alphanumeric segments separated by single hyphens, no leading/trailing hyphens)}\n@returns(200) {data: any} # Workspace updated successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"name\":\"Updated Workspace\",\"slug\":\"updated-workspace\"}\n\n@endpoint GET /workspaces/{id}/budgets\n@desc List workspace budgets\n@required {id: str # The workspace ID (UUID) or slug}\n@returns(200) {data: [map]} # Budgets retrieved successfully\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint DELETE /workspaces/{id}/budgets/{interval}\n@desc Delete a workspace budget\n@required {id: str # The workspace ID (UUID) or slug, interval: str # Budget reset interval. Use \"lifetime\" for a one-time budget that never resets.}\n@returns(200) {deleted: bool} # Budget deleted successfully\n@errors {401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n\n@endpoint PUT /workspaces/{id}/budgets/{interval}\n@desc Create or update a workspace budget\n@required {id: str # The workspace ID (UUID) or slug, interval: str # Budget reset interval. Use \"lifetime\" for a one-time budget that never resets., limit_usd: num(double) # Spending limit in USD. Must be greater than 0.}\n@returns(200) {data: any} # Budget created or updated successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"limit_usd\":100}\n\n@endpoint POST /workspaces/{id}/members/add\n@desc Bulk add members to a workspace\n@required {id: str # The workspace ID (UUID) or slug, user_ids: [str] # List of user IDs to add to the workspace. Members are assigned the same role they hold in the organization.}\n@returns(200) {added_count: int, data: [map]} # Members added successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"user_ids\":[\"user_abc123\",\"user_def456\"]}\n\n@endpoint POST /workspaces/{id}/members/remove\n@desc Bulk remove members from a workspace\n@required {id: str # The workspace ID (UUID) or slug, user_ids: [str] # List of user IDs to remove from the workspace}\n@returns(200) {removed_count: int} # Members removed successfully\n@errors {400: Bad Request - Invalid request parameters or malformed input, 401: Unauthorized - Authentication required or invalid credentials, 403: Forbidden - Authentication successful but insufficient permissions, 404: Not Found - Resource does not exist, 500: Internal Server Error - Unexpected server error}\n@example_request {\"user_ids\":[\"user_abc123\",\"user_def456\"]}\n\n@endgroup\n\n@end\n"}}