---
title: "Chat completion"
method: POST
path: "/chat/completions"
tags: ["Chat"]
---

# Chat completion

`POST /chat/completions`

## Request

- Base URL: `https://studio.fintechstudios.com/api/v1`
- URL: `https://studio.fintechstudios.com/api/v1/chat/completions`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Generate a chat completion using an LLM via OpenRouter. Supports multiple model providers (Anthropic, OpenAI, Perplexity). Credits charged dynamically based on token usage.

## Request body

- object
  - `model` string, required: Model ID from /models endpoint
  - `messages` object[], required: Conversation messages
    - `role` 'system' | 'user' | 'assistant', required
    - `content` string, required
  - `max_tokens` integer
  - `temperature` number
  - `response_format` object
    - `type` 'text' | 'json_object'
  - `provider_params` object: Provider-specific request parameters forwarded to the upstream LLM via OpenRouter. Known Perplexity params: return_images (boolean), return_related_questions (boolean), search_recency_filter (string: 'month'|'week'|'day'|'hour'), search_domain_filter (string[]).
  - `enrich_citations` boolean: When true, post-process provider metadata to extract a structured `citations` array as a sibling to `provider_metadata`. Currently resolves Perplexity citation URLs into objects with url, title, source_name, and date. Raw provider_metadata is never modified. Response content `[n]` references are preserved as-is for apps to render as they choose.
  - `normalize_images` boolean: When true, normalize provider-specific image metadata into a consistent schema. Maps variant field names (image_url/url/src, origin_url/source_url/page_url) to stable fields: url, source_url, width, height, alt, source_domain. Deduplicates by URL. Raw provider_metadata.images is never modified.

## Response `200`

Chat completion response

- object
  - `data` object
    - `id` string
    - `object` string
    - `model` string
    - `choices` object[]
      - `index` integer
      - `message` object
        - `role` string
        - `content` string
      - `finish_reason` string
    - `usage` object
      - `prompt_tokens` integer
      - `completion_tokens` integer
      - `total_tokens` integer
    - `provider_metadata` object, nullable: Raw provider-specific response metadata, passed through unmodified. Contents vary by provider. Perplexity models may return: citations (string[] of URLs), images (object[]), related_questions (string[]), search_results (object[]).
    - `citations` object[], nullable: Structured citation objects resolved from provider metadata. Only present when `enrich_citations: true` was set in the request AND the provider returned citation data. Content `[n]` references are NOT rewritten — apps decide how to render them using this array.
      - `index` integer, required: 1-based index matching [n] references in content
      - `url` string, required: Source URL
      - `title` string: Article/page title from search results, if available
      - `source_name` string: Short source name derived from title or URL hostname
      - `date` string: Publication date from search results, if available
    - `images` object[], nullable: Normalized image objects from provider metadata. Only present when `normalize_images: true` was set in the request AND the provider returned image data. All provider-specific field name variants are mapped to a consistent schema. Deduplicated by URL.
      - `url` string, required: Direct URL to the image
      - `source_url` string: URL of the page where the image was found
      - `width` integer: Image width in pixels
      - `height` integer: Image height in pixels
      - `alt` string: Alt text or description
      - `source_domain` string: Domain name of the source page (e.g. 'reuters.com')
  - `meta` Meta
    - `request_id` string
    - `credits_used` integer
    - `credits_remaining` integer
    - `rate_limit` object
      - `limit` integer
      - `remaining` integer
      - `reset` integer

## Other responses

- `400`: Validation error
- `401`: Invalid API key
- `402`: Insufficient credits (`insufficient_credits`), or the account's AI model usage limit is used up (`ai_usage_limit_reached`, with `details.resets_at`) — not retryable
- `429`: Rate limit exceeded — honor the Retry-After header
- `503`: AI model provider temporarily unavailable or busy (`upstream_unavailable`) — retryable; honor the Retry-After header when present

---

[API](https://skmtc.dev/fintechstudios/apis/fts-studio-api.md) · [All operations](https://skmtc.dev/fintechstudios/apis/fts-studio-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fintechstudios/apis/fts-studio-api/revisions/4886597d1d96?raw)
