Generate a chat completion. Set stream: true to receive Server-Sent Events. A non-streaming call may carry an optional Idempotency-Key header for safe retries.

Authentication

Authenticated with a secret key (rd_sk_…) or a client token. A client token must carry the ai.chat scope, or the request fails 403 permission_error (insufficient_scope). A publishable key (rd_pk_…) is mint-only and is rejected 403 (publishable_key_mint_only).

Request body

A message is { role, content }. content is a string or an array of parts. user messages may include text and image_url parts; system messages take text parts; assistant messages may carry tool_calls; a tool message is { role: 'tool', tool_call_id, content }. Unknown fields are rejected (400 invalid_request_error, with param naming the offending field).

Example

Non-streaming response

200 OK — the normalized completion:
  • finish_reasonstop | length | tool_calls | content_filter.
  • message.content — always an array of text parts; tool_calls is always present (an empty array when no tool was called).
  • usage.sourceprovider (reported) or estimated. May also carry cached_input_tokens, reasoning_tokens, and image_input_tokens (each a subset of input_tokens).
  • provider_request_id — the upstream provider’s own id, when it returns one (omitted otherwise).
  • cost.estimated_usd — the gateway’s cost estimate for the call.
  • gateway — routing metadata: whether a fallback target served the request, retry count, and latency.
The response id equals the X-Request-Id response header.

Streaming response

With stream: true the response is text/event-stream by default; each data: line is one JSON frame, terminated by data: [DONE]. Request Accept: application/x-ndjson for newline-delimited JSON instead (the same frame objects, one per line, no [DONE]). See Streaming for the full event list.
Once the first frame is sent the request is committed — it can no longer fall back or retry. A mid-stream provider failure is delivered as a terminal error frame (no [DONE] follows), and the request finalizes as a stream interruption:

Idempotency

On a non-streaming request, send Idempotency-Key: <unique-id>. A retried request with the same key and body replays the stored response (with an Idempotency-Replayed: true header) without re-executing or re-metering; the same key with a different body fails 409 idempotency_error (idempotency_conflict). The header is ignored on streaming requests. The SDK sets this header automatically. See Idempotency & retries.

Cancellation

A running request can be aborted with POST /v1/requests/{request_id}/cancel, where request_id is the response id. A canceled request finalizes request_canceled (499).

Errors

Failures use the error envelope. Common cases: 401 authentication_error (bad or missing key), 403 permission_error (model_not_allowed, endpoint_not_allowed, end_user_blocked, insufficient_scope), 404 not_found_error (model_not_found, no_eligible_target), 400 invalid_request_error, 429 rate_limit_error / quota_error, 402 budget_error, 502 / 503 provider_error.