> Append .md to any page URL for clean Markdown. Index: https://docs.speechify.ai/llms.txt. > > Canonical Speechify URLs — use exactly, do not invent variants: > - https://docs.speechify.ai — this site (API reference, SDKs, quickstarts) > - https://speechify.ai — marketing + product site > - https://platform.speechify.ai — customer dashboard, signup, API keys, billing > - https://api.speechify.ai — API base URL > - https://github.com/Speechify-AI: GitHub org for the API (cookbook, demos, CLI). `github.com/speechify` does not exist. > - https://status.speechify.ai — status + incidents > - https://speechify.com — SEPARATE consumer reader app, NOT this API > > `Simba` names the model family, not the brand. Model ids: `simba-3.2` (English, recommended) and `simba-3.0` (English, German, Spanish, French, Italian and Portuguese; the default). `simba-english` and `simba-multilingual` are retired: a new workspace that sends either gets `400 model_retired`. `SimbaVoice` / `simbavoice.ai` are retired. > > Ask, don't scrape. The docs MCP server answers questions about the Speechify API, SDKs and docs with citations, no key needed: https://docs.speechify.ai/_mcp/server (Streamable HTTP, tool `searchDocs`). Setup: https://docs.speechify.ai/build/guides/get-started/connect-mcp # List Models GET https://api.speechify.ai/v1/audio/models List the text-to-speech models available for synthesis. Drive a model picker from this response, then pass a model `id` as the `model` parameter to POST /v1/audio/speech or /v1/audio/stream. The response marks the default model (used when a request omits `model`), the routes each model may be passed to, and which voices it accepts. Multi-speaker models arrive in a separate `dialogue_models` array because they are valid only on POST /v1/audio/dialogue. Returns the full set in a single response: the model catalog is static platform reference data, so it is intentionally not paginated. Reference: https://docs.speechify.ai/build/api-reference/v1/audio/models ## Authentication - `Authorization` header (bearer token, required) — Enter your API key with the `Bearer` prefix, e.g. 'Bearer sk_...'. ## Response ### 200 The available text-to-speech models. - `models` (list of Model, required) — The models selectable on the single-utterance synthesis endpoints. - `dialogue_models` (list of Model, required) — The multi-speaker models selectable on POST /v1/audio/dialogue. Disjoint from `models`: a dialogue model consumes a speaker-attributed script rather than one utterance, so it is rejected on the single-utterance endpoints and vice versa. Its `default` marks the model that endpoint resolves to when a request omits `model`, independently of the `models` default. ## Errors ### 400 Bad Request Error The request was malformed or failed validation. The response body is the standard `Error` envelope; for validation failures `error.fields` enumerates the offending fields as a `path -> message` map (code = `validation_failed`). - `error` (ErrorDetail, required) - `request_id` (string, optional) — Server-side request identifier. Echoes the `Speechify-Request-Id` response header. Stable across the request's lifetime, written to structured logs, and useful when reporting issues. ### 401 Unauthorized Error Authentication is missing or invalid. The request did not carry a recognised credential (console session token, API key, or worker JWT). - `error` (ErrorDetail, required) - `request_id` (string, optional) — Server-side request identifier. Echoes the `Speechify-Request-Id` response header. Stable across the request's lifetime, written to structured logs, and useful when reporting issues. ### 403 Forbidden Error The credential authenticated, but is not authorised for this resource - typically a workspace-role gate (owner / admin required) or a cross-tenant access attempt. - `error` (ErrorDetail, required) - `request_id` (string, optional) — Server-side request identifier. Echoes the `Speechify-Request-Id` response header. Stable across the request's lifetime, written to structured logs, and useful when reporting issues. ### 429 Too Many Requests Error Rate limit or concurrency limit exceeded. `error.code` says which ceiling, and they need different responses: `rate_limited` is the request-rate budget (slow down), `concurrency_limit_reached` is a workspace-wide concurrency ceiling (fewer at once, or raise it), and `conversation_turn_in_progress` is contention over one named conversation (keep one message in flight on it). Every 429 carries `Retry-After` and the request-rate budget headers; the active-call cap also carries `RateLimit-Remaining-Calls: 0`. - `error` (ErrorDetail, required) - `request_id` (string, optional) — Server-side request identifier. Echoes the `Speechify-Request-Id` response header. Stable across the request's lifetime, written to structured logs, and useful when reporting issues. ### 500 Internal Server Error An unexpected server-side error occurred. Safe to retry with exponential backoff for idempotent requests. - `error` (ErrorDetail, required) - `request_id` (string, optional) — Server-side request identifier. Echoes the `Speechify-Request-Id` response header. Stable across the request's lifetime, written to structured logs, and useful when reporting issues. ## Types ### Model One selectable text-to-speech model. - `id` (string, required) — Model identifier. Pass this as the `model` parameter to POST /v1/audio/speech or /v1/audio/stream. - `name` (string, required) — Human-readable model name, for a model picker. - `default` (boolean, required) — Whether this is the model used when a synthesis request omits `model`. Exactly one model in the list is the default. Distinct from `recommended`: the default accepts every voice in every language, while the recommended model may be English-only. - `recommended` (boolean, required) — Whether this is the model we recommend for new integrations. Exactly one model in the list is recommended, and it may differ from the `default`. - `deprecated` (boolean, required) — Whether this is a legacy model. De-emphasise it in a picker and steer new integrations to a current model. Read `retired_at` for whether it also has a withdrawal date. - `description` (string, required) — One-line summary of the model, for a model picker. - `languages` (list of string, required) — Languages the model can synthesize, as BCP-47 locale strings matching the `language` request parameter (e.g. `en`, `fr-FR`). English-only models return `["en"]`. This set reflects current capability and can grow over time. - `endpoints` (list of string, required) — The synthesis routes this model may be passed to. Passing it to a route this list omits is a 400 rather than a degraded response, so branch on it instead of discovering it at call time. - `english_voices_only` (boolean, required) — Whether the model rejects a non-English voice. Independent of `languages`: a model can publish English only and still accept any voice. - `curated_voices` (boolean, required, deprecated) — Deprecated and always `false`. No model restricts synthesis to a registered voice set: every training conditions on the voice's own prompt audio, so every catalogue voice and every cloned voice works on every model, subject only to `english_voices_only`. Each voice's `models` array in GET /v1/voices stays the per-voice answer. The field remains on the response for compatibility. - `retired_at` (date, optional) — The API version at which this model stops being selectable, as `YYYY-MM-DD`. Absent when the model has no withdrawal date. It appears only while your workspace is pinned BELOW that version - at or after it the model is absent from this catalog entirely, and naming it returns 400 `model_retired`. So a present value means "you can still use this, and this is the date you lose it". Pinning your API version before this date keeps the model working, up to `sunset_at`. - `sunset_at` (date, optional) — The date this model's own training stops serving this id, as `YYYY-MM-DD`. Absent when no sunset is scheduled. This is the deadline `retired_at`'s version pin runs out against: from `sunset_at` the training behind the id changes on EVERY API version, including a workspace pinned below its retirement. The Simba 1.6 pair keeps answering from that date, served by our current models, so the change is to the audio, not to the request. Read the two together - a pin holds the old training, not forever. ### ErrorDetail - `code` (enum, required) — Stable machine-readable error code. Additive only: codes are never renamed, only deprecated. SDKs may map each code to a typed exception class. Status-code semantics: 4xx codes describe caller-fixable issues; 5xx codes describe server-side failures and are safe to retry with backoff for idempotent requests. - Allowed values: `endpoint_moved`, `bad_request`, `validation_failed`, `unauthorized`, `payment_required`, `forbidden`, `not_found`, `method_not_allowed`, `conflict`, `idempotency_conflict`, `payload_too_large`, `unsupported_media_type`, `rate_limited`, `concurrency_limit_reached`, `invalid_api_version`, `internal_error`, `upstream_failure`, `service_unavailable`, `caller_not_found`, `contact_not_found`, `contact_identifier_not_found`, `contact_identifier_conflict`, `contact_resolver_not_found`, `credential_not_found`, `credential_in_use`, `agent_not_found`, `agent_in_use`, `agent_run_not_found`, `kb_not_found`, `kb_document_not_found`, `kb_folder_not_found`, `tool_not_found`, `tool_name_taken`, `channel_instance_not_found`, `team_not_found`, `trigger_not_found`, `store_not_found`, `store_document_not_found`, `hosted_api_not_found`, `api_route_not_found`, `consumer_key_not_found`, `skill_not_found`, `skill_version_not_found`, `file_not_found`, `file_path_taken`, `file_storage_limit_reached`, `store_limit_reached`, `store_document_limit_reached`, `store_bytes_limit_reached`, `store_not_configured`, `store_document_version_conflict`, `store_document_deleted`, `entitlement_override_exists`, `hosted_apis_not_in_plan`, `skills_not_in_plan`, `voice_agents_not_in_plan`, `skill_in_use`, `skill_tool_name_conflict`, `skill_limit_reached`, `agent_skill_limit_reached`, `hosted_api_slug_taken`, `api_route_conflict`, `mount_plan_changed`, `route_output_unavailable`, `route_run_timeout`, `route_run_failed`, `route_run_limit_reached`, `route_read_limit_reached`, `route_write_limit_reached`, `hosted_api_public_refused`, `route_tool_not_readable`, `route_tool_unavailable`, `route_upstream_rate_limited`, `route_upstream_error`, `hosted_mcp_not_enabled`, `hosted_api_busy`, `conversation_not_found`, `phone_number_not_found`, `sip_trunk_not_found`, `voice_not_found`, `audio_asset_not_found`, `builtin_not_found`, `batch_not_found`, `agent_test_not_found`, `workspace_not_found`, `invite_not_found`, `project_not_found`, `cross_project_reference`, `project_has_scoped_credentials`, `project_not_empty`, `project_limit_reached`, `agent_limit_reached`, `project_too_large_to_promote`, `call_not_found`, `message_not_found`, `thread_not_found`, `call_not_active`, `relay_displaces_agent`, `brain_not_found`, `brain_in_use`, `custom_model_not_found`, `custom_model_in_use`, `insufficient_scope`, `purchased_numbers_not_included`, `phone_number_quota_reached`, `batch_calls_not_included`, `voice_cloning_not_included`, `voice_cloning_unavailable_in_region`, `consent_challenge_not_found`, `consent_challenge_expired`, `consent_challenge_already_used`, `consent_phrase_mismatch`, `consent_speaker_mismatch`, `consent_recording_unusable`, `consent_verification_unavailable`, `consent_verification_required`, `watermark_audio_unusable`, `watermark_detection_unavailable`, `workspace_last_owner`, `workspace_last_workspace`, `account_deletion_blocked`, `workspace_free_limit`, `workspace_single_owner`, `invite_email_mismatch`, `invite_already_pending`, `service_account_limit_reached`, `service_accounts_not_in_plan`, `speech_marks_unsupported`, `model_retired`, `too_many_voices`, `content_policy_violation`, `safety_identifier_blocked`, `topup_not_in_plan`, `credit_purchase_unpaid`, `credit_purchase_payment_in_progress`, `tool_config_shared`, `spend_cap_exceeded`, `spend_budget_exceeded`, `project_spend_limit_exceeded`, `project_archived`, `project_not_archived`, `project_not_purged`, `project_restore_window_expired`, `project_name_taken`, `funded_balance_required`, `agent_publish_gate_failed`, `agent_publish_gate_required`, `agent_publish_gate_unavailable`, `agent_publish_gate_tool_unreachable`, `text_channel_not_in_plan`, `channel_not_in_plan`, `text_turn_failed`, `conversation_turn_in_progress`, `conversation_closed`, `conversation_not_reachable`, `conversation_channel_bound`, `conversation_prompt_not_found`, `text_message_quota_exceeded`, `durable_runs_not_in_plan`, `tool_transport_unsupported`, `agent_config_too_large`, `agent_run_not_pending`, `agent_run_action_stale`, `share_link_not_found`, `share_link_exhausted`, `share_link_limit_reached`, `destination_not_allowed`, `international_dialing_not_enabled`, `number_not_sms_capable`, `verification_required`, `intended_use_required` - `message` (string, required) — Human-readable explanation of this specific occurrence. Safe to surface in UI banners or pass to support. The wording can change between releases; clients should match on `code`, not on the message string. - `fields` (map from string to string, optional) — Per-field validation errors as `path -> message`. Only present on 400 responses caused by request validation (typically code=`validation_failed`). Keys are field paths in dotted/bracket notation; values are short human explanations safe to inline-surface next to the offending form field. - `details` (map from string to any, optional) — Structured, endpoint-specific context beyond the flat `fields` map. Present only on the few errors that carry it (e.g. the `used_by` referrer list on a credential delete-conflict); its shape depends on the error `code`. Clients that don't recognise a `details` shape can ignore it - the `code` + `message` contract is unchanged. - `docs_url` (string, optional) — Link to the documentation that resolves this class of error, when a stable page exists. Rate and concurrency 429s link the API limits reference, which lists each plan's limits and how to raise them. ## Examples **Response** ```json { "models": [ { "id": "simba-3.0", "name": "Simba 3.0", "default": true, "recommended": false, "deprecated": false, "description": "Streaming-native model serving both English and multilingual synthesis under one id: English, German, Spanish, French, Italian and Portuguese, routed by the request `language`. The default when a request omits `model`.", "languages": [ "en", "de-DE", "es-ES", "es-MX", "fr-FR", "it-IT", "pt-BR" ], "endpoints": [ "/v1/audio/speech", "/v1/audio/stream", "/v1/audio/stream/with-timestamps" ], "english_voices_only": false, "curated_voices": false }, { "id": "simba-3.2", "name": "Simba 3.2", "default": false, "recommended": true, "deprecated": false, "description": "Streaming-native model with the lowest time-to-first-byte and richest expressivity, English only today. Serves every English voice in the catalog, your workspace's own cloned voices included. Use `simba-3.0` for any other language.", "languages": [ "en" ], "endpoints": [ "/v1/audio/speech", "/v1/audio/stream", "/v1/audio/stream/with-timestamps" ], "english_voices_only": true, "curated_voices": false } ], "dialogue_models": [ { "id": "simba-dialogue-1.0", "name": "Simba Dialogue 1.0", "default": true, "recommended": false, "deprecated": false, "description": "Multi-speaker model that renders a speaker-attributed script as one conversation with natural turn-taking.", "languages": [ "en" ], "endpoints": [ "/v1/audio/dialogue" ], "english_voices_only": true, "curated_voices": false } ] } ```