Izwi serves a local HTTP API from the same process that powers the web UI and desktop app. By default the base URL is:
Most API routes are under /v1. The exceptions are /docs, /openapi.json, /livez, and /readyz. When izwi serve is running:
  • http://localhost:8080/docs opens the local Scalar reference.
  • http://localhost:8080/openapi.json returns the generated OpenAPI document. It includes Scalar sidebar entries for preview first-party, operator, and realtime route families with lightweight summaries.
  • This page is the detailed contract guide for the broader first-party, preview, operator, and realtime route surface.

Surface Maturity

Common Conventions

Request IDs

Clients may send x-request-id. If absent, the server generates one. Responses include the same header and structured logs use it as the correlation ID.

Errors

JSON errors use this envelope:
Common status codes: Enterprise builds can inject authentication and policy hooks. Community builds use local anonymous defaults. If an enterprise hook rejects a request, the response can be 401, 403, or 500 before the route handler runs.

Security And CORS

Community builds do not require API keys by default. Treat the server as a local trusted process unless you deliberately expose it.
  • izwi serve defaults to port 8080.
  • --host 0.0.0.0 binds beyond loopback. Use it only on trusted networks or behind your own access controls.
  • --cors enables wildcard browser CORS responses.
  • Desktop origins such as tauri://localhost are allowed for the native app.

Pagination

Preview list APIs use cursor pagination where the response includes a pagination object. Query parameters: Response shape:
Some older list routes return arrays or route-specific wrapper names. The route sections below note those families.

Limits And Runtime Controls

Streaming

HTTP streaming routes use server-sent events (SSE):
  • Response content type is text/event-stream.
  • Each payload is sent as a data: frame.
  • OpenAI-compatible chat and Responses streams end with data: [DONE].
  • Some preview first-party streams emit JSON objects with an event field and close after the terminal event.
  • Client disconnects cancel delivery; some model work may finish internally before cleanup.

OpenAI-Compatible APIs

Models

GET /v1/models Returns enabled model variants in OpenAI list format.
GET /v1/models/{model} Returns one enabled model in the same object shape. Unknown or disabled variants return 404. Use /v1/admin/models when you need download, load, unload, local path, status, or speech-capability details.

Chat Completions

POST /v1/chat/completions Basic request:
Supported request fields: Compatibility profile:
Streaming sequence:
Tool behavior:
  • Assistant messages may include tool_calls.
  • Tool responses can be sent with role tool.
  • Model-emitted tool calls are returned with finish_reason: "tool_calls" when detected.
Multimodal content parts:
Image and video inputs are validated against the selected model. Text-only chat models reject media parts.

Audio Speech

POST /v1/audio/speech Generates audio bytes. JSON request:
Request fields: Non-stream response:
  • Body is binary audio.
  • Content type follows the actual generated format.
  • X-Requested-Response-Format and X-Actual-Response-Format are exposed. Explicit fallbacks also include X-Response-Format-Fallback and an HTTP Warning header.
SSE events: Example SSE request:

Audio Transcriptions

POST /v1/audio/transcriptions Accepts JSON or multipart input. JSON request:
Multipart fields: json response:
verbose_json response:
SSE events: Example multipart request:

Audio Alignment

POST /v1/audio/align Forced alignment accepts JSON or multipart input and aligns reference text to audio at word level. JSON request:
Multipart fields: json response:
verbose_json adds model, language, word_count, and processing_time_ms. Example multipart request:

Responses

POST /v1/responses Preview OpenAI-compatible Responses API shape.
Request fields: Stored records are process-local:
  • They are lost on server restart.
  • They can be evicted after IZWI_MAX_RESPONSE_STORE_ENTRIES.
  • Streaming records are stored only after a terminal completion or failure.
  • cancel does not provide durable active-response cancellation semantics.
Lifecycle routes: Streaming events:

First-Party Workflow APIs

These routes are preview APIs used by the web UI and desktop app. They are local, SQLite-backed stores unless otherwise noted. Non-streaming first-party speech-to-text and text-to-speech create routes are backed by durable runtime jobs. Route-specific records remain the compatibility contract for web and desktop clients; the generic /v1/jobs/* APIs expose runtime traces, artifacts, cancellation, and retry controls once a runtime job ID is known.

Route Rename Migration

The following preview route names were replaced by canonical names. The old runtime routes were removed. The speech history and speech-to-text renames keep response payloads, record IDs, pagination, audio download behavior, and SSE event names unchanged. The removed direct saved transcription routes now use job_kind=transcription on the persisted speech-to-text job flow. The removed direct audio diarization routes use the same job flow with job_kind=diarization: create a job, poll the returned record until processing_status is ready, and then read the diarization fields from that job record. Direct /v1/diarizations* routes remain supported first-party APIs. Use /v1/speech-to-text/jobs?job_kind=diarization when an app wants a unified speech-text list across transcription and diarization. Use /v1/diarizations* when an app wants diarization-specific resource names and does not need to mix transcription records into the same collection.

Speech-Text Jobs

Canonical saved transcription, speaker-attributed ASR, and diarization job routes: The job_kind query parameter is important for shared IDs and for clients that want a specific record family. speaker_attributed_asr and saa select the Granite Speech speaker-turn transcript mode. For transcription job creation, JSON and multipart requests accept generate_summary. It defaults to false; set it to true to generate an AI summary automatically after the transcript finishes. Records created without an automatic summary can still use POST /v1/speech-to-text/jobs/{record_id}/summary/regenerate?job_kind=transcription later. For speaker-attributed ASR, use:
SAA requests use the transcription store but require Granite-Speech-4.1-2B-Plus. JSON and multipart requests accept model_id/model, language, generate_summary, min_speakers, and max_speakers. SAA does not support streaming, timestamp alignment, or include_timestamps; the server clears aligner/timestamp fields for this mode. Non-streaming transcription and SAA creates return 202 with the route record as before, then run through the durable batch worker. The runtime records the source media asset, input artifact, execution stage, transcript text asset, and output transcript artifact. Streaming ASR remains on the SSE path and does not use the batch runtime in this phase.

Diarization Records

Persisted diarization routes:

Speech History

All three speech history families share list/create, member, audio, pagination, and deletion behavior. Create routes can generate audio and persist the resulting record. Routes: Non-streaming /v1/text-to-speech creates return 202 with a pending history record, then run through the durable batch worker. The runtime records the input text asset and generated WAV media asset/artifact before projecting the finished state back into the speech history record. Streaming TTS, voice design, and voice cloning stay on their route-specific execution paths. Streaming create responses emit JSON SSE events with an event field:

Durable Runtime Jobs

Preview runtime job routes expose the durable batch execution graph for first-party ASR and non-streaming text-to-speech jobs: Runtime jobs use statuses such as created, queued, running, paused, retrying, postprocessing, completed, failed, cancelled, and expired. Stages and artifacts include IDs, capability/model metadata, attempt counts, timing/error fields, media/text asset references, and storage keys when available.

Saved Voices

Reusable voice clone references: Use saved_voice_id on /v1/audio/speech or first-party generation routes to reuse a saved voice without resending reference audio. Saved voice records include a local permission baseline: permission_scope, consent_status, allowed_uses, permission_provenance, and permission_revoked_at. Newly created local voices default to permission_scope: "local_owner", consent_status: "granted", and allowed_uses containing local_tts. Migrated local voices use permission_scope: "legacy_local". Reuse through saved_voice_id returns 403 when consent is not granted, the voice is revoked, or local_tts is not allowed.

Studio

Studio is the long-form TTS project API. Project and folder routes: Audio export query parameters: Pronunciations and snapshots: Render jobs: Segment editing: Render-job statuses are route-specific preview values such as queued, running, completed, failed, cancelled, or stale. Clients should preserve unknown statuses.

Chat Threads

Durable local chat history: Send-message request fields: Streaming thread events:

Agent Sessions

Agent session metadata is process-local preview state. The linked chat thread is durable. Create fields include agent_id, model_id, system_prompt, planning_mode (off, auto, on), and title. Turn responses include assistant text, optional plan steps, tool calls, and ordered events such as turn_started, plan_created, tool_call_started, tool_call_completed, assistant_message, and turn_completed.

Voice Profile, Memory, And Sessions

Voice-mode persisted state: Observational memory is applied to modular voice conversations. Updates are stored locally and can be cleared by the user.

Media

Media lifecycle routes: Serves persisted media objects used by chat attachments and local workflows. The server route is a catch-all, so {path} can contain nested segments such as images/example.png or chat/thread-1/attachment.wav. Upload request:
audio_base64 is accepted as an alias for data_base64, and data URLs such as data:audio/wav;base64,... are accepted. Upload responses include path, url, content_type, filename, size_bytes, media_asset_id, canonical_media_asset_id, canonical_path, and canonical_url. For audio uploads, the server preserves the original object at path/url, registers it as a media_assets row, and writes a canonical 16 kHz mono WAV derivative when decoding succeeds. The canonical derivative has its own media asset ID and media path/URL. Non-audio uploads keep the existing object lifecycle behavior and leave canonical audio fields empty. Rules:
  • The path is relative to the media root.
  • Nested paths are allowed.
  • Absolute paths and .. traversal are rejected.
  • Unknown media returns 404.
  • Treat media URLs as local API resources, not stable public object-store URLs.

Onboarding And Preferences

Small first-party UI state APIs:

Operator APIs

Health And Readiness

/v1/health includes requested and selected backend, compiled backend support, detected device capabilities, dtype policy, CUDA runtime diagnostics, and fused-attention status.

Metrics

Batch runtime metrics include queued_stages, jobs_by_status, stages_by_status, and a local worker snapshot. Prometheus output appends izwi_batch_runtime_queued_stages, izwi_batch_runtime_jobs, izwi_batch_runtime_stages, and izwi_batch_runtime_worker_running.

Admin Model Management

Preview local admin routes. Use these routes as the OSS model lifecycle and discovery surface for voice apps: each model record includes local status, broad modalities, speech-generation capabilities when present, and route-level capability booleans. Model status values:
Speech model capabilities, when present:
Model records also expose route and batch capability flags so clients can discover which models can drive OpenAI-compatible speech, persisted speech-to-text jobs, diarization records, Studio projects, realtime voice sessions, saved voices, forced alignment, tokenizer workflows, and durable ASR/TTS jobs:
Download progress SSE payload:
Progress status can be downloading, completed, error, or cancelled.

Realtime WebSocket APIs

Realtime routes are preview browser protocols. They use JSON text messages for control events and binary PCM16 frames for audio.

Transcription Realtime

GET /v1/speech-to-text/realtime/ws Server starts with:
Client JSON messages: Client binary frame: Server events: Constraints:
  • Binary frames larger than 512 KiB are rejected.
  • Sample rate must remain stable during a session.
  • Sample rates outside the accepted runtime range return an error.

Voice Realtime

GET /v1/voice/realtime/ws Server starts with:
Client JSON messages: mode values: input_stream_start fields: Client binary frame: Assistant audio binary frame: Server events: Voice realtime persists voice sessions and turns in the local store. Modular turns can also update observational memory when that feature is enabled.