ZapAPI Docs
Get StartedConceptsAI GatewayGuidesPayment GatewaySDKAPI ReferenceResources
AI Gateway

Chat Completions

The OpenAI-compatible endpoint — streaming, vision, tools, web search, thinking levels, and routing preferences.

POST /ai/chat/completions is a drop-in replacement for OpenAI's chat completions endpoint. Everything your OpenAI SDK sends works here — plus ZapAPI additions (sats billing, routing suffixes, web search, PII-safe options).

Basic request

Simple completion
curl https://api.zapapi.com/api/v1/ai/chat/completions \
  -H "Authorization: Bearer zap_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-6.1-sol",
    "messages": [
      {"role": "system", "content": "You are concise."},
      {"role": "user", "content": "Summarize the Lightning Network in two sentences."}
    ]
  }'

The response shape is identical to OpenAI's (choices[0].message.content, usage with native token counts). Token counts are what you're billed on.

Streaming

SSE streaming
curl -N https://api.zapapi.com/api/v1/ai/chat/completions \
  -H "Authorization: Bearer zap_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-6.1-sol",
    "stream": true,
    "messages": [{"role": "user", "content": "Write a short poem about sats."}]
  }'

SSE keep-alive comments (: OPENROUTER PROCESSING) may appear — skip lines starting with : before parsing. The final data: frame before [DONE] carries the usage object used for billing.

Vision (image input)

On vision-capable models, send content parts with images as HTTPS URLs or base64 data URLs:

Message with an image
{
  "model": "openai/gpt-6.1-sol",
  "messages": [
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "What does this diagram show?" },
        { "type": "image_url", "image_url": { "url": "data:image/png;base64,iVBOR…" } }
      ]
    }
  ]
}

Two ways to ground answers with real-time web results. A flat fee per search-enabled request applies (shown in your price breakdown).

Always search (plugin)
{
  "model": "anthropic/claude-sonnet-5.5",
  "plugins": [{ "id": "web", "max_results": 5 }],
  "messages": [{ "role": "user", "content": "What are today's top Lightning Network updates?" }]
}
Model-decided (server tool)
{
  "model": "anthropic/claude-sonnet-5.5",
  "tools": [{ "type": "web_search" }],
  "messages": [{ "role": "user", "content": "Who won the latest Boltz update?" }]
}

Or simply append :online to the model id.

Thinking levels

Reasoning models accept an effort hint. Higher effort = more reasoning tokens (billed as output):

Reasoning effort
{
  "model": "anthropic/claude-opus-5.5",
  "reasoning": { "effort": "medium" },
  "messages": [{ "role": "user", "content": "Prove there are infinitely many primes." }]
}

Supported efforts are listed per model in the catalog (reasoning.supported_efforts), e.g. low / medium / high / xhigh / max. Some models make reasoning mandatory.

Routing preferences

Pass provider routing through unchanged:

Provider routing
{
  "model": "deepseek/deepseek-v4.1-flash",
  "provider": {
    "sort": "throughput",
    "zdr": true,
    "data_collection": "deny"
  },
  "messages": [{ "role": "user", "content": "Hello" }]
}

Or use the model-id suffixes: :nitro, :floor, :exacto, :online, :thinking, :extended.

Tools & structured output

tools, tool_choice, response_format (JSON schema / json_object), and parallel_tool_calls are forwarded to the provider. Add provider.require_parameters: true to only route to providers that support every parameter you send.

Errors

HTTPCodeMeaning
400invalid_requestMissing/invalid model or messages
401unauthorizedBad or missing API key
402insufficient_balanceNot enough AI credit — includes required_sats and balance_sats
404model_not_foundUnknown id / stale catalog
404model_retiredModel was retired upstream
429upstream_rate_limitedProvider rate limit (common on free tiers) — retry or switch models
502upstream_errorProvider returned an error (never billed)
503ai_upstream_unavailableGateway upstream temporarily down — retry shortly

Errors use the OpenAI error envelope: { "error": { "message", "code" } }.

Failed calls are never billed

If the upstream errors before producing a completion, the charge is $0 and the query is logged with an errorCode for your audit trail. See Billing & Sats Pricing.

On this page