Skip to content

Chat Completions

Request and response schema.

POST https://api.aimodelsrouter.ai/v1/chat/completions creates a model response for a conversation. The body is the OpenAI Chat Completions request. model and a non-empty messages array are required; if the model rejects a parameter, you get 400 invalid_request with the reason.

Request body

FieldTypeDescription
modelstring, requiredModel slug, e.g. deepseek/deepseek-v4-flash.
messagesarray, requiredConversation so far: objects with role (system, user, assistant, tool) and content (string or content parts).
streambooleanStream the response as server-sent events. Default false.
stream_optionsobject{ include_usage: true } is accepted; the final usage chunk is always sent when streaming.
max_tokens / max_completion_tokensintegerUpper bound on generated tokens. Also lowers the hold placed on your balance.
temperature, top_pnumberSampling parameters, passed through to the model.
stopstring | string[]Stop sequences.
tools, tool_choicearray, string | objectFunction calling, for models with the tools capability.
response_formatobjectJSON mode / JSON schema, for models with the structured_outputs capability.
seed, presence_penalty, frequency_penaltynumberPassed through when the model supports them.
userstringAccepted for compatibility. Not stored and not passed to the model provider.
curl https://api.aimodelsrouter.ai/v1/chat/completions \
  -H "Authorization: Bearer $AMR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek/deepseek-v4-flash",
    "max_tokens": 512,
    "messages": [
      {"role": "system", "content": "You are concise."},
      {"role": "user", "content": "Explain idempotency keys in one paragraph."}
    ]
  }'

Response

FieldDescription
idOur generation id, gen-…. Also returned in the X-Generation-Id header. Use it with GET /generation?id= and to find the request in your activity log.
modelThe slug that served the request: the one you sent, or the replacement of a retired slug (then the X-AMR-Model-Alias header repeats the slug you sent).
choices[]OpenAI-shaped choices: message (content, tool_calls) and finish_reason. A reasoning model's trace is in both reasoning_content and reasoning (the same text), on every route; read either.
usageprompt_tokens, completion_tokens, total_tokens, details where reported, plus cost: the amount charged in USD (a number).
The upstream provider that served a request is never exposed in responses. Only OpenAI-schema fields are passed on, at every level, so responses look the same whichever route served them: no system_fingerprint, service_tier or serving-engine fields.

Routing controls

FieldEffect
max_price (or provider.max_price){"prompt": 1, "completion": 4} in USD per 1M tokens. If the model costs more, the request is refused with 400 max_price_exceeded and nothing is charged.
zdr (or provider.zdr)true: use only routes whose supplier's terms promise prompts and outputs are not stored. A model without one answers 400 zdr_unavailable. See data_retention in GET /models.

Neither is sent to the model. service_tier is not sent either: every request is served at the listed price.

Look up a generation

GET /generation?id=gen-… (authenticated) returns metadata for one of your requests: model, status, tokens, cost, latency, time to first token and creation time. GET /generations lists your recent ones and GET /usage totals them by day or model; see Usage API.

curl "https://api.aimodelsrouter.ai/v1/generation?id=gen-3f1c9b8e0a2d4c55b6e7f8a9b0c1d2e3" \
  -H "Authorization: Bearer $AMR_API_KEY"