> 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 Voices

GET https://api.speechify.ai/v1/voices

Lists the voices available to the caller - the shared voice
catalog plus the cloned voices they can reach, whichever member or
service-account key created them. A clone filed under a project is
listed only for a caller who can reach that project; a clone no
project filed is shared with the whole workspace and is listed for
everyone in it. By default
the full catalogue is returned in one response. Pagination is
opt-in: pass `limit` (and then `cursor` from the previous
response) to page through the list while `has_more` is true. Max
page size is 200. Narrow the list with the `type` and `locale`
filters.

A page can come back with fewer than `limit` voices, and a short
page - an empty one included - is not the end of the list. Keep
following `next_cursor` while `has_more` is true.

Reference: https://docs.sws.speechify.com/build/api-reference/v1/voices/get

## Authentication

- `Authorization` header (bearer token, required) — Enter your API key with the `Bearer` prefix, e.g. 'Bearer sk_...'.

## Request

### Query parameters

- `cursor` (string, optional) — Opaque pagination cursor from a previous response.
- `limit` (integer, optional, default: 50) — Max items per page (default 50, max 200).
- `type` (enum, optional) — Filter by voice type: `personal` (the workspace's cloned voices) or `shared` (the public catalogue). Omit to return both.
  - Allowed values: `personal`, `shared`
- `locale` (string, optional) — Filter to voices whose locale matches this BCP-47 language range, prefix-matched: `en` matches `en-US` and `en-GB`; `en-US` matches only `en-US`. Case-insensitive. Omit to return all locales.
- `gender` (enum, optional) — Filter by voice gender. Omit to return all genders.
  - Allowed values: `male`, `female`, `not_specified`
- `model` (string, optional) — Filter to voices that support this model (as listed in each voice's `models[]`), e.g. `simba-3.2`. Omit to return voices for all models.
- `project_id` (string, optional) — Filter cloned voices by workspace project: omit for every voice you can reach, pass the literal `shared` for the clones no project filed, or a `proj_...` id for the clones filed under that project. The shared catalog carries no project and is returned either way. A clone is filed under a project when a project-pinned key created it. A clone with no project is shared with the whole workspace rather than sitting in a Default project, so the literal here is `shared`, never `default` - passing `default` is a 400. Returns 404 project_not_found for a malformed id and for any project outside your reach: a project-pinned key reaches only its pinned project, and a member holding project grants reaches only the granted ones. That 404 is the same in every case and does not reveal whether such a project exists. `shared` is always inside your reach.

## Response

### 200

The voice catalogue (or a page of it when `limit` is set).

- `next_cursor` (string, required, nullable) — Opaque keyset cursor for the next page. Pass back as the `cursor` request parameter. `null` when the caller has reached the end of the list (`has_more` is also `false` in that case).
- `has_more` (boolean, required) — True when more rows exist beyond this page.
- `voices` (list of GetVoice, required)

## 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

### GetVoice

- `display_name` (string, required)
- `gender` (enum, required)
  - Allowed values: `male`, `female`, `not_specified`
- `locale` (string, required)
- `id` (string, required)
- `models` (list of GetVoicesModel, required)
- `type` (enum, required)
  - Allowed values: `shared`, `personal`
- `avatar_image` (string, optional, nullable)
- `preview_audio` (string, optional, nullable)
- `project_id` (string, optional) — The workspace project this cloned voice is filed under, set when a project-pinned key created it. Returned wherever a cloned voice is: the list, a single-voice read, and the create response. Omitted for a shared-catalog voice and for a cloned voice no project filed, which is shared with the whole workspace and listed for every member of it.
- `can_manage` (boolean, optional) — Whether this workspace may delete the voice and download its sample through this API. `true` for a cloned voice the workspace owns. `false` for a shared-catalog voice, and for a cloned voice that reaches this workspace only through its creator's personal account (a voice cloned before workspace ownership, or under another Speechify product), which is managed where it was made.
- `tags` (list of string, optional, nullable)

### 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`, `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`, `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.

### GetVoicesModel

- `languages` (list of GetVoiceLanguage, required)
- `name` (enum, required) — A model this voice can be synthesized with. The set is filtered to what YOUR workspace's API version can select, so a voice never advertises a model your own synthesis request would reject. The legacy `simba-english` / `simba-multilingual` values appear only for a workspace pinned before API version `2026-09-21`.
  - Allowed values: `simba-english`, `simba-multilingual`, `simba-3.0`, `simba-3.2`

### GetVoiceLanguage

- `locale` (string, required)
- `preview_audio` (string, optional, nullable)

## Examples

**Response**

```json
{
  "next_cursor": "string",
  "has_more": true,
  "voices": [
    {
      "display_name": "string",
      "gender": "male",
      "locale": "string",
      "id": "string",
      "models": [
        {
          "languages": [
            {
              "locale": "string",
              "preview_audio": "string"
            }
          ],
          "name": "simba-english"
        }
      ],
      "type": "shared",
      "avatar_image": "string",
      "preview_audio": "string",
      "project_id": "proj_01kwxwcbyb6wk952swa0432cf1",
      "can_manage": true,
      "tags": [
        "string"
      ]
    }
  ]
}
```