Skip to main content

Completions Response Format

Here’s the response schema as a TypeScript type:
TypeScript
// Definitions of subtypes are below
type Response = {
  id: string;
  // Depending on whether you set "stream" to "true" and
  // whether you passed in "messages" or a "prompt", you
  // will get a different output shape
  choices: (NonStreamingChoice | StreamingChoice | NonChatChoice)[];
  created: number; // Unix timestamp
  model: string;
  object: 'chat.completion' | 'chat.completion.chunk';

  system_fingerprint?: string; // Only present if the provider supports it

  // Usage data is always returned for non-streaming.
  // When streaming, you will get one usage object at
  // the end accompanied by an empty choices array.
  usage?: ResponseUsage;
};
// If the provider returns usage, we pass it down
// as-is. Otherwise, we count using the GPT-4 tokenizer.

type ResponseUsage = {
  /** Including images and tools if any */
  prompt_tokens: number;
  /** The tokens generated */
  completion_tokens: number;
  /** Sum of the above two fields */
  total_tokens: number;
};
// Subtypes:
type NonChatChoice = {
  finish_reason: string | null;
  text: string;
  error?: ErrorResponse;
};

type NonStreamingChoice = {
  finish_reason: string | null;
  native_finish_reason: string | null;
  message: {
    content: string | null;
    role: string;
    tool_calls?: ToolCall[];
  };
  error?: ErrorResponse;
};

type StreamingChoice = {
  finish_reason: string | null;
  native_finish_reason: string | null;
  delta: {
    content: string | null;
    role?: string;
    tool_calls?: ToolCall[];
  };
  error?: ErrorResponse;
};

type ErrorResponse = {
  code: number; // See "Error Handling" section
  message: string;
  metadata?: Record<string, unknown>; // Contains additional error information such as provider details, the raw error message, etc.
};

type ToolCall = {
  id: string;
  type: 'function';
  function: FunctionCall;
};
Here’s an example:
{
  "id":"gen-xxxxxxxxxxxxxx",
  "created":1757140020,
  "model":"openai/gpt-4",
  "object":"chat.completion",
  "system_fingerprint":"None",
  "choices":[
    {
      "finish_reason":"stop", // Normalized finish_reason
      "index":0,
      "message":{
        // will be "delta" if streaming
        "content":"The capital of France is Paris.",
        "role":"assistant",
        "tool_calls":"None",
        "function_call":"None"
      },
      "provider_specific_fields":{
        "native_finish_reason":"stop" // The raw finish_reason from the provider
      }
    }
  ],
  "usage":{
    "completion_tokens":7,
    "prompt_tokens":14,
    "total_tokens":21,
    "completion_tokens_details":{
      "accepted_prediction_tokens":"None",
      "audio_tokens":"None",
      "reasoning_tokens":0,
      "rejected_prediction_tokens":"None"
    },
    "prompt_tokens_details":{
      "audio_tokens":0,
      "cached_tokens":0
    }
  },
  "provider":"OpenAI"
}

Finish Reason

Some models and providers may have additional finish reasons. The raw finish_reason string returned by the model is available via the native_finish_reason property.