provod.ai / docs
API

Use Chat Completions

OpenAI-compatible chat completion requests and streaming.

Last updated on

Send the smallest successful request

Choose an available chat model from GET /v1/models, then send a non-streaming request first:

Terminal
export PROVOD_API_KEY="sk_..."

curl --fail-with-body --silent --show-error https://api.provod.ai/v1/chat/completions \
  -H "Authorization: Bearer $PROVOD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.4",
    "messages": [
      { "role": "user", "content": "Reply with ok" }
    ]
  }'

A representative successful response is:

Response
{
  "id": "chatcmpl_example",
  "object": "chat.completion",
  "created": 1786651200,
  "model": "openai/gpt-5.4",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "ok" },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 8,
    "completion_tokens": 1,
    "total_tokens": 9
  }
}

Read the assistant text from choices[0].message.content. Check finish_reason before assuming the answer is complete, and use the returned usage when the selected model reports it.

A chat message is submitted and streamed back as incremental output.

OpenAI-compatible chat at /v1/chat/completions.

Set an output limit only when needed

The shipped request contract accepts either max_completion_tokens or the legacy spelling max_tokens as a positive integer. Send only one. The selected model's capabilities determine whether and how the limit can be used, so check its supported_parameters instead of treating either spelling as a universal workaround.

If you omit both fields, the service uses its current default when preparing and reserving the request. That default is not a promise about every model's maximum output. For a deliberate cap, send one field supported by the chosen model and inspect finish_reason in the result.

Add streaming after the first request works

Streaming delivers an answer incrementally instead of waiting for the complete JSON response. Chat Completions uses Server-Sent Events (SSE), a text format in which each event is carried in a data: record.

Terminal
export PROVOD_API_KEY="sk_..."

curl --no-buffer --fail-with-body --silent --show-error https://api.provod.ai/v1/chat/completions \
  -H "Authorization: Bearer $PROVOD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.4",
    "messages": [
      { "role": "user", "content": "Reply with ok" }
    ],
    "stream": true
  }'

Each JSON event contributes a choices[0].delta; a successful stream ends with the literal marker [DONE]:

SSE
data: {"id":"chatcmpl_example","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}

data: {"id":"chatcmpl_example","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"ok"},"finish_reason":null}]}

data: {"id":"chatcmpl_example","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]

Handle three terminal cases: a non-2xx JSON error before SSE starts, an SSE payload containing an error, and a connection that closes before [DONE]. A public error code is the client-facing error.code value in an error payload; use it for diagnostics and retry decisions.

Do not blindly retry delivered output

Retry with bounded backoff only when no output has been delivered. After any text arrives, keep the partial result and ask the user or application to decide whether to continue: an automatic retry can duplicate work and cost, and confirmed usage from an interrupted stream may be billed.

Troubleshooting

On this page