---
title: "Create Completion"
method: POST
path: "/api/v1/completions"
tags: ["Completions"]
---

# Create Completion

`POST /api/v1/completions`

Generate a text completion. Set `stream: true` for SSE streaming.

All SSE frames use `event: stream_event` with a JSON-serialized lithos
`StreamEvent` payload, discriminated by `type`: started,
content_block_start, text_delta, reasoning_delta, tool_call_delta,
content_block_end, usage, rate_limits, ended, and error.

## Request body

- CreateCompletionRequest — A lithos `Request` plus `stream`. Field names match the lithos wire form so a serialized lithos request can be posted as-is.
  - `messages` CompletionMessage[], required — The conversation messages.
    - `role` 'system' | 'developer' | 'user' | 'assistant' | 'tool', required — The role of the message author.
    - `content` CompletionContentPart[], required — Content parts of the message.
      - `type` string, required — Content part type.
    - `name` string — Optional name for the message author.
    - `tool_call_id` string — Tool call ID for tool result messages.
  - `model` string — Model selector: `provider/model`, a model id or alias, or a provider id. The server picks a ready-provider default when omitted.
  - `provider` string — Optional provider pin for a bare model selector.
  - `system` string — System prompt (convenience; prepended as a system message).
  - `stream` boolean — Stream response via SSE.
  - `tools` CompletionToolDefinition[] — Tool definitions available to the model.
    - `name` string, required — Tool name.
    - `description` string, required — Human-readable tool description.
    - `kind` CompletionToolDefinitionKind, required — lithos `ToolDefinitionKind`: `{type: function, input_schema}` for JSON-argument tools or `{type: custom, format}` for free-form input.
      - `type` 'function' | 'custom', required
  - `tool_choice` CompletionToolChoice — A lithos `ToolChoice`, discriminated by `type`.
    - `type` 'auto' | 'none' | 'required' | 'tool', required — Tool selection mode.
    - `name` string — Required when type is `tool`.
  - `response_format` CompletionResponseFormat — lithos `ResponseFormat`, discriminated by `type`: `text`, `json_object`, or `json_schema` ({name, schema}).
    - `type` 'text' | 'json_object' | 'json_schema', required
  - `schema` unknown
  - `max_output_tokens` integer
  - `temperature` number, double
  - `top_p` number, double
  - `stop_sequences` string[] — Stop sequences.
  - `reasoning_effort` 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' — Native reasoning-effort level requested for an LLM call.
  - `speed` 'fast' | 'balanced' | 'economical' — lithos `Speed`: the requested latency or cost tier.
  - `metadata` object — Request tags forwarded to providers that accept them.
  - `provider_options` object — Raw provider options keyed by provider id.

## Response `200`

Completion result (JSON when stream=false, SSE when stream=true)

- CompletionResponse — A lithos `Response`, returned verbatim. The server prices the response: `cost` is the catalog estimate or the provider's own figure. When the request carried `schema`, `output` holds the parsed object.
  - `output` unknown
  - `id` string, nullable
  - `model` ModelHandle, required — A resolved provider and model identity.
    - `provider` string, required — LLM provider identifier.
    - `model` string, required — Canonical model id within the provider.
  - `content` CompletionContentPart[], required
    - `type` string, required — Content part type.
  - `suppressed_tool_calls` object[] — Tool calls withheld because the turn ended early.
  - `finish_reason` string, required — Why generation stopped: stop, length, tool_call, content_filter, error, incomplete, or a provider-specific reason.
  - `usage` TokenCounts, required — lithos `TokenCounts`: five disjoint token buckets. Every token is counted in exactly one, so their plain sum is the total. `input` excludes cache reads and writes, while `output` excludes reasoning tokens when the provider reports them separately. A bucket that is absent reads as zero.
    - `input` integer — Prompt tokens that were neither read from nor written to a cache.
    - `output` integer — Completion tokens that are not reasoning tokens.
    - `reasoning` integer — Completion tokens spent on reasoning, priced at the output rate.
    - `cache_read` integer — Prompt tokens served from a provider cache.
    - `cache_write` integer — Prompt tokens written into a provider cache.
  - `cost` Cost — lithos `Cost`: a USD amount in micros and where it came from.
    - `usd_micros` integer, required
    - `source` 'catalog' | 'provider' | 'application', required — Where a cost came from: `catalog` (estimated from catalog prices), `provider` (the provider's own reported cost), or `application` (a sum the caller assembled from differently sourced parts).
  - `rate_limits` object
  - `warnings` object[]
    - `code` string, required
    - `message` string, required
  - `raw` unknown

## Other responses

- `400` — Invalid request

## Changes

- **2026-09-14** `57ca921cdd38` — 6 breaking
  - the `cost/usd_micros` response's property format changed from `int64` to `uint64` for status `200`
  - the `usage/cache_read` response's property format changed from `int64` to `uint64` for status `200`
  - the `usage/cache_write` response's property format changed from `int64` to `uint64` for status `200`
  - the `usage/input` response's property format changed from `int64` to `uint64` for status `200`
  - …2 more
- **2026-09-08** `9aaa5d3a64cc` — 15 breaking, 8 warning, 20 info
  - added the new required request property `messages/items/content/items/type`
  - added the new required request property `tool_choice/type`
  - added the new required request property `tools/items/kind`
  - the `provider_options` request property type changed from no type to `object`
  - …39 more
- **2026-07-24** `d3b22cbaeec0` — 1 breaking, 8 info
  - request property `reasoning_effort` was restricted to a list of enum values
  - added the new `high` enum value to the request property `reasoning_effort`
  - added the new `low` enum value to the request property `reasoning_effort`
  - added the new `max` enum value to the request property `reasoning_effort`
  - …5 more
- …earlier changes not shown

[Full history](https://skmtc.dev/fabro-sh/apis/fabro-run-api/changes/api/v1/completions/post.md)

---

[API](https://skmtc.dev/fabro-sh/apis/fabro-run-api.md) · [All operations](https://skmtc.dev/fabro-sh/apis/fabro-run-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fabro-sh/apis/fabro-run-api/revisions/1258a4cf33df?raw)
