Inference API
Overview
One OpenAI-compatible endpoint: what requests look like, what comes back, and how to handle the failure modes.
Inference runs through the OpenAI-compatible chat completions endpoint on the data plane. Authenticate every request with an org API key in the Authorization header:
POST https://inference.pearlresearch.ai/v1/chat/completions
Authorization: Bearer $PEARL_API_KEY
Content-Type: application/jsonThe request body follows the OpenAI chat completions schema: a model ID from the catalog, a messages array, and optional parameters. Any OpenAI SDK works unchanged, see the quickstart for client setup in Python and TypeScript. Two companion endpoints ride alongside: GET /models (the live catalog) and the legacy POST /completions (raw-prompt completions, streaming included).
The response envelope
A non-streamed response is a single JSON object:
{
"id": "chatcmpl-2de22e60-5d2a-48e7-acfa-28c53fd9da40",
"object": "chat.completion",
"created": 1785229039,
"model": "deepseek/deepseek-v4-flash-0731",
"choices": [
{
"index": 0,
"finish_reason": "stop",
"logprobs": null,
"message": {
"role": "assistant",
"content": "The sky appears blue because of Rayleigh scattering. ...",
"reasoning": "The question is about atmospheric optics. The key mechanism is ..."
}
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 145,
"total_tokens": 157,
"prompt_tokens_details": {"cached_tokens": 0}
}
}choices[0].message, the assistant reply. Reasoning models add areasoningfield alongsidecontent; tool use addstool_calls.finish_reason,stop(natural end or stop sequence),length(hitmax_tokens, the reply is truncated), ortool_calls(the model wants your code to run a tool).usage, the token counts your organization is billed on. Depending on the serving worker, it may also carryprompt_tokens_details.cached_tokens(see prompt caching) andcompletion_tokens_details.reasoning_tokens.
Parameters
Alongside the standard OpenAI parameters (temperature, top_p, frequency_penalty, presence_penalty, max_tokens, seed, up to 4 stop sequences), models accept top_k and min_p extensions, pass those via extra_body in the OpenAI SDKs. Per-model support is listed in supported_sampling_parameters on GET /models.
Errors
Error responses are JSON and carry a request_id, log it, and include it when you contact support; it is how a specific request gets found on the network.
| Status | Meaning | What to do |
|---|---|---|
| 400 | Malformed request, invalid JSON, missing fields, or an unsupported parameter | Fix the request; retrying unchanged will fail again |
| 401 | Missing, invalid, or revoked API key | Check the Authorization header; mint a new key if yours was revoked |
| 402 | Your organization is out of credits | Top up on the Billing page (or enable auto-recharge), then retry |
| 404 | Unknown model ID or path | Check the id against GET /models |
| 429 | Rate limited | Back off exponentially with jitter, then retry |
| 5xx | Transient network or worker failure | Safe to retry with backoff, the network routes around unhealthy workers |
A 402 is an account state, not a transient fault: requests keep failing until the balance is topped up. If you run production traffic on a prepaid balance, enable auto-recharge so a busy night doesn't become an outage.
Retry guidance
- Retry
429and5xxwith exponential backoff and jitter; cap the attempts and surface therequest_idwhen giving up. - Do not blind-retry
400/401/402/404, they fail the same way until the request, key, or balance changes. - Once a response starts streaming, a failure ends the stream instead of returning an error object, see Streaming for how to detect an incomplete stream.