@lap v0.3
# Machine-readable API spec. Each @endpoint block is one API call.
@api OpenRouter API
@base https://openrouter.ai/api/v1
@version 1.0.0
@auth Bearer bearer | Bearer bearer
@endpoints 88
@hint download_for_search
@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(11)

@group activity
@endpoint GET /activity
@optional {date: str, api_key_hash: str, user_id: str}
@returns(200) {data: [map]}
@errors {400, 401, 403, 404, 500}

@endgroup

@group analytics
@endpoint GET /analytics/meta
@returns(200) {data: map{dimensions: [map], granularities: [map], metrics: [map], operators: [map]}}
@errors {401, 403, 500}

@endpoint POST /analytics/query
@required {metrics: [str]}
@optional {dimensions: [str], filters: [map{field!: str, operator!: str, value!: any}], granularity: str, group_limit: int, limit: int, order_by: map{direction!: str, field!: str}, time_range: map{end!: str(date-time), start!: str(date-time)}}
@returns(200) {data: map{cachedAt: num(double), data: [map], metadata: map{query_time_ms: num(double), row_count: int, truncated: bool}, warnings: [str]}}
@errors {400, 401, 403, 408, 500}

@endgroup

@group audio
@endpoint POST /audio/speech
@required {input: str, model: str, voice: str}
@optional {provider: map{options: map}, response_format: str(mp3/pcm)=pcm, speed: num(double)}
@returns(200)
@errors {400, 401, 402, 404, 429, 500, 502, 503, 524, 529}

@endpoint POST /audio/transcriptions
@required {input_audio: map{data!: str, format!: str}, model: str}
@optional {language: str, provider: map{options: map}, temperature: num(double)}
@returns(200) {text: str, usage: map{cost: num(double), input_tokens: int, output_tokens: int, seconds: num(double), total_tokens: int}}
@errors {400, 401, 402, 404, 429, 500, 502, 503, 524, 529}

@endgroup

@group auth
@endpoint POST /auth/keys
@required {code: str}
@optional {code_challenge_method: str(S256/plain), code_verifier: str}
@returns(200) {key: str, user_id: str?}
@errors {400, 403, 500}

@endpoint POST /auth/keys/code
@required {callback_url: str(uri)}
@optional {code_challenge: str, code_challenge_method: str(S256/plain), expires_at: str(date-time), key_label: str, limit: num(double), spawn_agent: str, spawn_cloud: str, usage_limit_type: str(daily/weekly/monthly), workspace_id: str(uuid)}
@returns(200) {data: map{app_id: int, created_at: str, id: str}}
@errors {400, 401, 403, 409, 500}

@endgroup

@group benchmarks
@endpoint GET /benchmarks
@optional {source: str(artificial-analysis/design-arena), task_type: str(coding/intelligence/agentic), arena: str(models/builders/agents), category: str, max_results: int}
@returns(200) {data: [any], meta: map{as_of: str, citation: str?, model_count: int, source: str?, source_url: str?, task_type: str?, version: str}}
@errors {400, 401, 429, 500}

@endgroup

@group byok
@endpoint GET /byok
@optional {offset: int, limit: int, workspace_id: str(uuid), 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)}
@returns(200) {data: [map], total_count: int}
@errors {401, 500}

@endpoint POST /byok
@required {key: str, 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 {allowed_models: [str], allowed_user_ids: [str], disabled: bool, is_fallback: bool, name: str, workspace_id: str(uuid)}
@returns(201) {data: any}
@errors {400, 401, 403, 500}

@endpoint DELETE /byok/{id}
@required {id: str(uuid)}
@returns(200) {deleted: bool}
@errors {401, 404, 500}

@endpoint GET /byok/{id}
@required {id: str(uuid)}
@returns(200) {data: any}
@errors {401, 404, 500}

@endpoint PATCH /byok/{id}
@required {id: str(uuid)}
@optional {allowed_models: [str], allowed_user_ids: [str], disabled: bool, is_fallback: bool, key: str, name: str}
@returns(200) {data: any}
@errors {400, 401, 404, 500}

@endgroup

@group chat
@endpoint POST /chat/completions
@required {messages: [any]}
@optional {X-OpenRouter-Metadata: str, cache_control: map{ttl: str, type!: str}, debug: map{echo_upstream_body: bool}, frequency_penalty: num(double), image_config: map, logit_bias: map, logprobs: bool, max_completion_tokens: int, max_tokens: int, metadata: map, min_p: num(double), modalities: [str], model: str, models: [any], parallel_tool_calls: bool, plugins: [any], presence_penalty: num(double), 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}, reasoning: map{effort: str, summary: str}, reasoning_effort: str(max/xhigh/high/medium/low/minimal/none), repetition_penalty: num(double), response_format: any, route: str(fallback/sort), seed: int, service_tier: str(auto/default/flex/priority/scale), session_id: str, stop: any, stop_server_tools_when: [any], stream: bool=false, stream_options: map{include_usage: bool}, temperature: num(double), tool_choice: any, tools: [any], top_a: num(double), 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}, user: str}
@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}}
@errors {400, 401, 402, 403, 404, 408, 413, 422, 429, 500, 502, 503, 524, 529}

@endgroup

@group classifications
@endpoint GET /classifications/task
@optional {window: str=7d}
@returns(200) {data: map{as_of: str, classifications: [map], macro_categories: [map], window_days: int}}
@errors {400, 401, 429, 500}

@endgroup

@group credits
@endpoint GET /credits
@returns(200) {data: map{total_credits: num(double), total_usage: num(double)}}
@errors {401, 403, 500}

@endpoint POST /credits/coinbase
@returns(200)
@errors {410}

@endgroup

@group datasets
@endpoint GET /datasets/app-rankings
@optional {category: str(coding/creative/productivity/entertainment), 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), sort: str(popular/trending)=popular, start_date: str, end_date: str, limit: int=50, offset: int=0}
@returns(200) {data: [map], meta: map{as_of: str, end_date: str, start_date: str, version: str}}
@errors {400, 401, 429, 500}

@endpoint GET /datasets/rankings-daily
@optional {start_date: str, end_date: str}
@returns(200) {data: [map], meta: map{as_of: str, end_date: str, start_date: str, version: str}}
@errors {400, 401, 429, 500}

@endgroup

@group embeddings
@endpoint POST /embeddings
@required {input: any, model: str}
@optional {dimensions: int, encoding_format: str(float/base64), input_type: str, provider: any, user: str}
@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}}
@errors {400, 401, 402, 404, 429, 500, 502, 503, 524, 529}

@endpoint GET /embeddings/models
@returns(200) {data: [map]}
@errors {400, 500}

@endgroup

@group endpoints
@endpoint GET /endpoints/zdr
@returns(200) {data: [map]}
@errors {500}

@endgroup

@group files
@endpoint GET /files
@optional {limit: int, cursor: str, workspace_id: str(uuid)}
@returns(200) {cursor: str?, data: [map], first_id: str?, has_more: bool, last_id: str?}
@errors {400, 401, 429, 500}

@endpoint POST /files
@optional {workspace_id: str(uuid)}
@returns(200) {created_at: str, downloadable: bool, filename: str, id: str, mime_type: str, size_bytes: int, type: str}
@errors {400, 401, 403, 413, 429, 500}

@endpoint DELETE /files/{file_id}
@required {file_id: str}
@optional {workspace_id: str(uuid)}
@returns(200) {id: str, type: str}
@errors {401, 404, 429, 500}

@endpoint GET /files/{file_id}
@required {file_id: str}
@optional {workspace_id: str(uuid)}
@returns(200) {created_at: str, downloadable: bool, filename: str, id: str, mime_type: str, size_bytes: int, type: str}
@errors {401, 404, 429, 500}

@endpoint GET /files/{file_id}/content
@required {file_id: str}
@optional {workspace_id: str(uuid)}
@returns(200)
@errors {400, 401, 404, 429, 500}

@endgroup

@group generation
@endpoint GET /generation
@required {id: str}
@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?}}
@errors {401, 402, 404, 429, 500, 502, 524, 529}

@endpoint GET /generation/content
@required {id: str}
@returns(200) {data: map{input: any, output: map{completion: str?, reasoning: str?}}}
@errors {401, 403, 404, 429, 500, 502, 524, 529}

@endgroup

@group guardrails
@endpoint GET /guardrails
@optional {offset: int, limit: int, workspace_id: str(uuid)}
@returns(200) {data: [map], total_count: int}
@errors {401, 500}

@endpoint POST /guardrails
@required {name: str}
@optional {allowed_models: [str], allowed_providers: [str], content_filter_builtins: [map{action!: str, label: str, scan_scope: str, slug!: str}], content_filters: [map{action!: str, label: str, pattern!: str}], description: str, enforce_zdr: bool, enforce_zdr_anthropic: bool, enforce_zdr_google: bool, enforce_zdr_openai: bool, enforce_zdr_other: bool, ignored_models: [str], ignored_providers: [str], limit_usd: num(double), reset_interval: str(daily/weekly/monthly), workspace_id: str(uuid)}
@returns(201) {data: any}
@errors {400, 401, 403, 500}

@endpoint DELETE /guardrails/{id}
@required {id: str(uuid)}
@returns(200) {deleted: bool}
@errors {401, 404, 500}

@endpoint GET /guardrails/{id}
@required {id: str(uuid)}
@returns(200) {data: any}
@errors {401, 404, 500}

@endpoint PATCH /guardrails/{id}
@required {id: str(uuid)}
@optional {allowed_models: [str], allowed_providers: [str], content_filter_builtins: [map{action!: str, label: str, scan_scope: str, slug!: str}], content_filters: [map{action!: str, label: str, pattern!: str}], description: str, enforce_zdr: bool, enforce_zdr_anthropic: bool, enforce_zdr_google: bool, enforce_zdr_openai: bool, enforce_zdr_other: bool, ignored_models: [str], ignored_providers: [str], limit_usd: num(double), name: str, reset_interval: str(daily/weekly/monthly)}
@returns(200) {data: any}
@errors {400, 401, 404, 500}

@endpoint GET /guardrails/{id}/assignments/keys
@required {id: str(uuid)}
@optional {offset: int, limit: int}
@returns(200) {data: [map], total_count: int}
@errors {401, 404, 500}

@endpoint POST /guardrails/{id}/assignments/keys
@required {id: str(uuid), key_hashes: [str]}
@returns(200) {assigned_count: int}
@errors {400, 401, 404, 500}

@endpoint POST /guardrails/{id}/assignments/keys/remove
@required {id: str(uuid), key_hashes: [str]}
@returns(200) {unassigned_count: int}
@errors {400, 401, 404, 500}

@endpoint GET /guardrails/{id}/assignments/members
@required {id: str(uuid)}
@optional {offset: int, limit: int}
@returns(200) {data: [map], total_count: int}
@errors {401, 404, 500}

@endpoint POST /guardrails/{id}/assignments/members
@required {id: str(uuid), member_user_ids: [str]}
@returns(200) {assigned_count: int}
@errors {400, 401, 404, 500}

@endpoint POST /guardrails/{id}/assignments/members/remove
@required {id: str(uuid), member_user_ids: [str]}
@returns(200) {unassigned_count: int}
@errors {400, 401, 404, 500}

@endpoint GET /guardrails/assignments/keys
@optional {offset: int, limit: int}
@returns(200) {data: [map], total_count: int}
@errors {401, 500}

@endpoint GET /guardrails/assignments/members
@optional {offset: int, limit: int}
@returns(200) {data: [map], total_count: int}
@errors {401, 500}

@endgroup

@group images
@endpoint POST /images
@required {model: str, prompt: str}
@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), background: str(auto/transparent/opaque), input_references: [map{image_url!: map, type!: str}], n: int, output_compression: int, output_format: str(png/jpeg/webp/svg), provider: map{options: any}, quality: str(auto/low/medium/high), resolution: str(512/1K/2K/4K), seed: int, size: str, stream: bool}
@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}}
@errors {400, 401, 402, 403, 404, 429, 500, 502, 524, 529}

@endpoint GET /images/models
@returns(200) {data: [map]}
@errors {500}

@endpoint GET /images/models/{author}/{slug}/endpoints
@required {author: str, slug: str}
@returns(200) {endpoints: [map], id: str}
@errors {404, 500}

@endgroup

@group key
@endpoint GET /key
@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)}}
@errors {401, 500}

@endgroup

@group keys
@endpoint GET /keys
@optional {include_disabled: bool, offset: int, workspace_id: str(uuid)}
@returns(200) {data: [map]}
@errors {401, 429, 500}

@endpoint POST /keys
@required {name: str}
@optional {creator_user_id: str, expires_at: str(date-time), include_byok_in_limit: bool, limit: num(double), limit_reset: str(daily/weekly/monthly), workspace_id: str(uuid)}
@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}
@errors {400, 401, 403, 429, 500}

@endpoint DELETE /keys/{hash}
@required {hash: str}
@returns(200) {deleted: bool}
@errors {401, 404, 429, 500}

@endpoint GET /keys/{hash}
@required {hash: str}
@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}}
@errors {401, 404, 429, 500}

@endpoint PATCH /keys/{hash}
@required {hash: str}
@optional {disabled: bool, include_byok_in_limit: bool, limit: num(double), limit_reset: str(daily/weekly/monthly), name: str}
@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}}
@errors {400, 401, 404, 429, 500}

@endgroup

@group messages
@endpoint POST /messages
@required {messages: [map{content!: any, role!: str}], model: str}
@optional {X-OpenRouter-Metadata: str, cache_control: map{ttl: str, type!: str}, context_management: map{edits: [any]}, fallbacks: [map{model!: str}], max_tokens: int, metadata: map{user_id: str}, models: [str], output_config: map{effort: str, format: map, task_budget: map}, plugins: [any], 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}, route: str(fallback/sort), service_tier: str, session_id: str, speed: any, stop_sequences: [str], stop_server_tools_when: [any], 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}, user: str}
@returns(200)
@errors {400, 401, 403, 404, 429, 500, 503, 529}

@endgroup

@group model
@endpoint GET /model/{author}/{slug}
@required {author: str, slug: str}
@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?}}}
@errors {404, 500}

@endgroup

@group models
@endpoint GET /models
@optional {category: str(programming/roleplay/marketing/marketing/seo/technology/science/translation/legal/finance/health/trivia/academia), supported_parameters: str, output_modalities: str, 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), q: str, input_modalities: str, context: int, min_price: num, max_price: num, arch: str, model_authors: str, providers: str, distillable: str(true/false), zdr: str, region: str}
@returns(200) {data: [map]}
@errors {400, 500}

@endpoint GET /models/{author}/{slug}/endpoints
@required {author: str, slug: str}
@returns(200) {data: map{architecture: any, created: int, description: str, endpoints: [map], id: str, name: str}}
@errors {404, 500}

@endpoint GET /models/count
@optional {output_modalities: str}
@returns(200) {data: map{count: int}}
@errors {400, 500}

@endpoint GET /models/user
@returns(200) {data: [map]}
@errors {401, 404, 500}

@endgroup

@group observability
@endpoint GET /observability/destinations
@optional {offset: int, limit: int, workspace_id: str(uuid)}
@returns(200) {data: [any], total_count: int}
@errors {401, 500}

@endpoint POST /observability/destinations
@required {config: map, name: str, type: str(arize/braintrust/clickhouse/datadog/grafana/langfuse/langsmith/newrelic/opik/otel-collector/posthog/ramp/s3/sentry/snowflake/weave/webhook)}
@optional {api_key_hashes: [str], enabled: bool=true, filter_rules: map{enabled: bool, groups!: [map]}, privacy_mode: bool=false, sampling_rate: num(double), workspace_id: str(uuid)}
@returns(201) {data: any}
@errors {400, 401, 403, 409, 500}

@endpoint DELETE /observability/destinations/{id}
@required {id: str(uuid)}
@returns(200) {deleted: bool}
@errors {401, 404, 500}

@endpoint GET /observability/destinations/{id}
@required {id: str(uuid)}
@returns(200) {data: any}
@errors {401, 404, 500}

@endpoint PATCH /observability/destinations/{id}
@required {id: str(uuid)}
@optional {api_key_hashes: [str], config: map, enabled: bool, filter_rules: any, name: str, privacy_mode: bool, sampling_rate: num(double)}
@returns(200) {data: any}
@errors {400, 401, 404, 409, 500}

@endgroup

@group organization
@endpoint GET /organization/members
@optional {offset: int, limit: int}
@returns(200) {data: [map], total_count: int}
@errors {401, 404, 500}

@endgroup

@group presets
@endpoint GET /presets
@optional {offset: int, limit: int}
@returns(200) {data: [map], total_count: int}
@errors {400, 401, 500}

@endpoint GET /presets/{slug}
@required {slug: str}
@returns(200) {data: any}
@errors {400, 401, 404, 500}

@endpoint POST /presets/{slug}/chat/completions
@required {slug: str, messages: [any]}
@optional {cache_control: map{ttl: str, type!: str}, debug: map{echo_upstream_body: bool}, frequency_penalty: num(double), image_config: map, logit_bias: map, logprobs: bool, max_completion_tokens: int, max_tokens: int, metadata: map, min_p: num(double), modalities: [str], model: str, models: [any], parallel_tool_calls: bool, plugins: [any], presence_penalty: num(double), 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}, reasoning: map{effort: str, summary: str}, reasoning_effort: str(max/xhigh/high/medium/low/minimal/none), repetition_penalty: num(double), response_format: any, route: str(fallback/sort), seed: int, service_tier: str(auto/default/flex/priority/scale), session_id: str, stop: any, stop_server_tools_when: [any], stream: bool=false, stream_options: map{include_usage: bool}, temperature: num(double), tool_choice: any, tools: [any], top_a: num(double), 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}, user: str}
@returns(200) {data: any}
@errors {400, 401, 403, 404, 409, 500}

@endpoint POST /presets/{slug}/messages
@required {slug: str, messages: [map{content!: any, role!: str}], model: str}
@optional {cache_control: map{ttl: str, type!: str}, context_management: map{edits: [any]}, fallbacks: [map{model!: str}], max_tokens: int, metadata: map{user_id: str}, models: [str], output_config: map{effort: str, format: map, task_budget: map}, plugins: [any], 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}, route: str(fallback/sort), service_tier: str, session_id: str, speed: any, stop_sequences: [str], stop_server_tools_when: [any], 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}, user: str}
@returns(200) {data: any}
@errors {400, 401, 403, 404, 409, 500}

@endpoint POST /presets/{slug}/responses
@required {slug: str}
@optional {background: bool, cache_control: map{ttl: str, type!: str}, debug: map{echo_upstream_body: bool}, frequency_penalty: num(double), image_config: map, include: [str], input: any, instructions: str, max_output_tokens: int, max_tool_calls: int, metadata: map, modalities: [str], model: str, models: [str], parallel_tool_calls: bool, plugins: [any], 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}, reasoning: any, route: str(fallback/sort), safety_identifier: str, service_tier: str(auto/default/flex/priority/scale)=auto, session_id: str, stop_server_tools_when: [any], store: bool=false, stream: bool=false, temperature: num(double), text: any, 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}, truncation: str(auto/disabled), user: str}
@returns(200) {data: any}
@errors {400, 401, 403, 404, 409, 500}

@endpoint GET /presets/{slug}/versions
@required {slug: str}
@optional {offset: int, limit: int}
@returns(200) {data: [map], total_count: int}
@errors {400, 401, 404, 500}

@endpoint GET /presets/{slug}/versions/{version}
@required {slug: str, version: str}
@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}}
@errors {400, 401, 404, 500}

@endgroup

@group providers
@endpoint GET /providers
@returns(200) {data: [map]}
@errors {500}

@endgroup

@group rerank
@endpoint POST /rerank
@required {documents: [any], model: str, query: str}
@optional {provider: any, top_n: int}
@returns(200) {id: str, model: str, provider: str, results: [map], usage: map{cost: num(double), search_units: int, total_tokens: int}}
@errors {400, 401, 402, 404, 429, 500, 502, 503, 524, 529}

@endgroup

@group responses
@endpoint POST /responses
@optional {X-OpenRouter-Metadata: str, background: bool, cache_control: map{ttl: str, type!: str}, debug: map{echo_upstream_body: bool}, frequency_penalty: num(double), image_config: map, include: [str], input: any, instructions: str, max_output_tokens: int, max_tool_calls: int, metadata: map, modalities: [str], model: str, models: [str], parallel_tool_calls: bool, plugins: [any], 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}, reasoning: any, route: str(fallback/sort), safety_identifier: str, service_tier: str(auto/default/flex/priority/scale)=auto, session_id: str, stop_server_tools_when: [any], store: bool=false, stream: bool=false, temperature: num(double), text: any, 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}, truncation: str(auto/disabled), user: str}
@returns(200)
@errors {400, 401, 402, 403, 404, 408, 413, 422, 429, 500, 502, 503, 524, 529}

@endgroup

@group videos
@endpoint POST /videos
@required {model: str, prompt: str}
@optional {aspect_ratio: str(16:9/9:16/1:1/4:3/3:4/3:2/2:3/21:9/9:21), callback_url: str(uri), duration: int, frame_images: [any], generate_audio: bool, input_references: [any], provider: map{options: any}, resolution: str(480p/720p/1080p/1K/2K/4K), seed: int, size: str}
@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}}
@errors {400, 401, 402, 404, 429, 500}

@endpoint GET /videos/{jobId}
@required {jobId: str}
@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}}
@errors {401, 404, 500}

@endpoint GET /videos/{jobId}/content
@required {jobId: str}
@optional {index: int=0}
@returns(200)
@errors {400, 401, 404, 500, 502}

@endpoint GET /videos/models
@returns(200) {data: [map]}
@errors {400, 500}

@endgroup

@group workspaces
@endpoint GET /workspaces
@optional {offset: int, limit: int}
@returns(200) {data: [map], total_count: int}
@errors {401, 500}

@endpoint POST /workspaces
@required {name: str, slug: str}
@optional {default_image_model: str, default_provider_sort: str, default_text_model: str, description: str, io_logging_api_key_ids: [int], io_logging_sampling_rate: num(double), is_data_discount_logging_enabled: bool, is_observability_broadcast_enabled: bool, is_observability_io_logging_enabled: bool}
@returns(201) {data: any}
@errors {400, 401, 403, 500}

@endpoint DELETE /workspaces/{id}
@required {id: str}
@returns(200) {deleted: bool}
@errors {400, 401, 403, 404, 500}

@endpoint GET /workspaces/{id}
@required {id: str}
@returns(200) {data: any}
@errors {401, 404, 500}

@endpoint PATCH /workspaces/{id}
@required {id: str}
@optional {default_image_model: str, default_provider_sort: str, default_text_model: str, description: str, io_logging_api_key_ids: [int], io_logging_sampling_rate: num(double), is_data_discount_logging_enabled: bool, is_observability_broadcast_enabled: bool, is_observability_io_logging_enabled: bool, name: str, slug: str}
@returns(200) {data: any}
@errors {400, 401, 403, 404, 500}

@endpoint GET /workspaces/{id}/budgets
@required {id: str}
@returns(200) {data: [map]}
@errors {401, 404, 500}

@endpoint DELETE /workspaces/{id}/budgets/{interval}
@required {id: str, interval: str}
@returns(200) {deleted: bool}
@errors {401, 404, 500}

@endpoint PUT /workspaces/{id}/budgets/{interval}
@required {id: str, interval: str, limit_usd: num(double)}
@returns(200) {data: any}
@errors {400, 401, 404, 500}

@endpoint GET /workspaces/{id}/members
@required {id: str}
@optional {offset: int, limit: int}
@returns(200) {data: [map], total_count: int}
@errors {401, 403, 404, 500}

@endpoint POST /workspaces/{id}/members/add
@required {id: str, user_ids: [str]}
@returns(200) {added_count: int, data: [map]}
@errors {400, 401, 403, 404, 500}

@endpoint POST /workspaces/{id}/members/remove
@required {id: str, user_ids: [str]}
@returns(200) {removed_count: int}
@errors {400, 401, 403, 404, 500}

@endgroup

@end
