Realtime HTTP API

Capture an HTTP TTS service-frame stream

This is a direct platform HTTP operation.

POST/http/tts

This is a direct platform HTTP operation. JavaScript and Python SDK 0.18.0 use Socket.IO and do not call this route. Send it from a trusted backend with X-Api-Key and the TTS capability.

Send a fresh UUID id, top-level text containing at least one Unicode letter or number after trimming, and the explicit model key nebula. For predictable voice selection, send exactly one voice_id or one voice_references entry, never both. Obtain a voice_id through SDK listVoices() or list_voices(); no HTTP voice-list operation exists. The returned UUID identifies one of the seven multilingual voice profiles. Its physical variants are internal and direct use of a physical variant UUID is rejected. If model is omitted, the deployment uses its configured default model key, falling back to nebula. If the voice selector is omitted, voice selection is deployment-specific.

The service counts Unicode code points, not UTF-8 bytes or displayed grapheme clusters. Leading and trailing whitespace is preserved and counts toward the limit. Inclusive defaults are 500 code points for free accounts and 1,000 for standard and enterprise accounts. Missing or unknown tiers use the free limit. Deployments can independently override these limits with TTS_MAX_INPUT_CHARACTERS_FREE, TTS_MAX_INPUT_CHARACTERS_STANDARD, and TTS_MAX_INPUT_CHARACTERS_ENTERPRISE, so this schema intentionally does not declare a fixed maxLength.

Reference audio must be standard-base64 RIFF/WAVE containing nonempty mono PCM16 audio, accompanied by its transcript.

An HTTP 200 body is an undelimited sequence of service frames: 16 raw UUID bytes, one final-flag byte, then 16 kHz PCM16 little-endian bytes. Ordinary HTTP read boundaries do not preserve service-frame boundaries, so this body is neither generically decodable raw PCM nor WAV. Save it only as a protocol capture. Use Socket.IO TTS and the TTS-to-WAV recipe for playable output.

Apply finite connect, inactivity/read, and overall deadlines. EOF or cancellation without a boundary-aware final flag is incomplete. Aborting the HTTP request cancels only its in-flight synthesis. A failure after bytes were committed ends the partial binary stream; the service never appends an error JSON document to a binary 200 body. Keep partial bytes separate from complete output. This operation has no idempotency contract; use a fresh UUID for an application-approved retry.

Authorization

ApiKeyAuth
X-Api-Key<token>

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/octet-stream

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -sS --fail-with-body --connect-timeout 10 --max-time 120 -X POST \  "https://example.com/http/tts" \  -H "Origin: https://example.com" \  -H "Content-Type: application/json" \  --data '{  "id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",  "text": "Hello from HUMAIN Voice",  "model": "nebula"}'

Undelimited TTS service-frame sequence, not raw PCM or WAV. Ordinary HTTP read chunks are not service-frame boundaries. Only a client with an environment-specific framing mechanism can identify the final flag; EOF alone does not prove completion.

application/octet-stream

Malformed input, including an unparseable request id, or missing/unusable text or voice reference. These validation failures are non-retryable and occur before synthesis begins.

Valid text rejected by the TTS content policy is also reported here as TTS_INPUT_NOT_ALLOWED. It is non-retryable: the same text will not be accepted, so change the text before sending another request.

A malformed request id is reported as VALIDATION_INVALID_FORMAT, together with every other malformed-body failure: the id is parsed during JSON decoding, so an unparseable value fails the whole body rather than reaching a dedicated check. The request id itself never yields VALIDATION_INVALID_UUID on this route.

A caller-supplied voice_id IS reported here (SAU-2258): a voice_id that is not a valid UUID is VALIDATION_INVALID_UUID, and a well-formed voice_id that does not identify an available voice is TTS_VOICE_NOT_FOUND. Both are 400 and non-retryable — resending the same voice_id cannot succeed; fix it or send voice_references instead. (Voice data that is present but incomplete or corrupt, or a proven storage/database outage, are server-side conditions reported as 500/503 — see the 500 and 503 responses.)

Text and reference OVERAGES are not here: exceeding the tier character limit, the reference transcript limit or the reference count is 422, and an oversized decoded reference is 413.

application/json

Example invalid_body

{
  "error": "Invalid request body",
  "code": "VALIDATION_INVALID_FORMAT",
  "detail": "Invalid request body",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

The request `id` is not a valid UUID, so the body fails to decode

{
  "error": "Invalid request body",
  "code": "VALIDATION_INVALID_FORMAT",
  "detail": "Invalid request body",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

Text is empty or contains only Unicode whitespace

{
  "error": "TTS input must contain non-whitespace text",
  "code": "VALIDATION_REQUIRED_FIELD",
  "detail": "TTS input must contain non-whitespace text",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

voice_id and voice_references were both supplied

{
  "error": "voice_id and voice_references are mutually exclusive",
  "code": "VALIDATION_INVALID_PARAM",
  "detail": "voice_id and voice_references are mutually exclusive",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

An explicit empty array; omit the property instead

{
  "error": "voice_references must contain exactly one reference when present; omit the field to use the default voice",
  "code": "VALIDATION_INVALID_PARAM",
  "detail": "voice_references must contain exactly one reference when present; omit the field to use the default voice",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

Reference audio is not canonical base64 mono PCM16 RIFF/WAVE

{
  "error": "voice_references[0].audio is not valid reference audio: audio must be a RIFF/WAVE file",
  "code": "VALIDATION_INVALID_FORMAT",
  "detail": "voice_references[0].audio is not valid reference audio: audio must be a RIFF/WAVE file",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

Reference transcript is missing or whitespace-only

{
  "error": "voice_references[0].text must contain the reference transcript",
  "code": "VALIDATION_REQUIRED_FIELD",
  "detail": "voice_references[0].text must contain the reference transcript",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

voice_id is present but not a valid UUID

{
  "error": "voice_id must be a valid UUID",
  "code": "VALIDATION_INVALID_UUID",
  "detail": "voice_id must be a valid UUID",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

voice_id is a valid UUID but does not identify an available voice

{
  "error": "voice_id does not identify an available voice",
  "code": "TTS_VOICE_NOT_FOUND",
  "detail": "voice_id does not identify an available voice",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

Text rejected by the TTS content policy

{
  "error": "TTS input is not allowed",
  "code": "TTS_INPUT_NOT_ALLOWED",
  "detail": "TTS input is not allowed",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

Unauthorized

application/json

Example missing_key

{
  "error": "Invalid authentication",
  "code": "AUTH_UNAUTHORIZED",
  "detail": "Invalid authentication",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

The API key does not grant access to the requested voice capability

application/json

Example scope_denied

{
  "error": "scope not permitted",
  "code": "AUTH_FORBIDDEN",
  "detail": "scope not permitted",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

Method not allowed

application/json

Example wrong_method

{
  "error": "method not allowed",
  "code": "METHOD_NOT_ALLOWED",
  "detail": "method not allowed",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

The request body exceeded the configured limit for this route (16 MiB for TTS request bodies). This failure is non-retryable at the same size; send a smaller request.

The request-BODY form of this response carries no data object. The three audio routes answer an oversized body with the same status and code but DO include data; see their own 413 documentation.

POST /http/tts also answers this status when a voice reference's DECODED audio exceeds the deployment's per-reference byte ceiling (default 2 MiB), and that form DOES carry data with bound tts_voice_reference_bytes and unit bytes. It is checked from the base64 length before the payload is decoded, so an oversized reference is never materialised.

application/json

Example body_too_large

{
  "error": "request body too large",
  "code": "PAYLOAD_TOO_LARGE",
  "detail": "request body too large",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

Decoded reference audio exceeds the per-reference byte ceiling

{
  "error": "voice_references[0].audio decodes to 3145728 bytes; limit is 2097152",
  "code": "PAYLOAD_TOO_LARGE",
  "detail": "voice_references[0].audio decodes to 3145728 bytes; limit is 2097152",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z",
  "data": {
    "limit": 2097152,
    "observed": 3145728,
    "unit": "bytes",
    "bound": "tts_voice_reference_bytes"
  }
}

The request parsed correctly and every field is individually valid, but a SEMANTIC workload unit exceeds its ceiling (RFC 9110 15.5.21). A few hundred bytes of text can ask for far more synthesis work than its size suggests, so these bounds cannot be expressed as a byte cap and are never 413.

data.bound names which ceiling was hit:

  • tts_input_characters - text is longer than the account tier's character limit (defaults: 500 free, 1,000 standard and enterprise).
  • tts_voice_reference_text_characters - voice_references[0].text is longer than the reference-transcript limit (default 500).
  • tts_voice_reference_count - more than one entry in voice_references; the published maxItems is 1.
  • tts_voice_reference_duration - the decoded reference audio is longer than the deployment's ceiling (default 15 seconds), which matches the deployed model's own reference limit. data.observed is in whole seconds, rounded up.

Every one of these is checked before any model lookup, admission or charge, so a rejected request consumes no quota and no concurrency slot. Not retryable: resending the identical request cannot succeed.

application/json

Text exceeds the default free-tier runtime limit

{
  "error": "TTS input contains 501 characters; limit is 500",
  "code": "CHARACTER_COUNT_EXCEEDED",
  "detail": "TTS input contains 501 characters; limit is 500",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z",
  "data": {
    "limit": 500,
    "observed": 501,
    "unit": "characters",
    "bound": "tts_input_characters"
  }
}

Reference transcript exceeds its own independent limit

{
  "error": "voice_references[0].text contains 501 characters; limit is 500",
  "code": "CHARACTER_COUNT_EXCEEDED",
  "detail": "voice_references[0].text contains 501 characters; limit is 500",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z",
  "data": {
    "limit": 500,
    "observed": 501,
    "unit": "characters",
    "bound": "tts_voice_reference_text_characters"
  }
}

More than the published maxItems of 1

{
  "error": "voice_references contains 2 references; limit is 1",
  "code": "VOICE_REFERENCE_COUNT_EXCEEDED",
  "detail": "voice_references contains 2 references; limit is 1",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z",
  "data": {
    "limit": 1,
    "observed": 2,
    "unit": "references",
    "bound": "tts_voice_reference_count"
  }
}

Reference clip longer than the deployed model's reference limit

{
  "error": "voice_references[0].audio is 16 seconds long; limit is 15",
  "code": "AUDIO_DURATION_EXCEEDED",
  "detail": "voice_references[0].audio is 16 seconds long; limit is 15",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z",
  "data": {
    "limit": 15,
    "observed": 16,
    "unit": "seconds",
    "bound": "tts_voice_reference_duration"
  }
}

The account already has as many concurrent operations of this kind in flight as its plan allows, counted across every server instance (SAU-2181). The limit is per BILLABLE ACCOUNT, so several API keys belonging to one account share a single allowance and creating more keys does not raise it. Each workload has its own allowance, so realtime ASR and TTS do not compete with one another.

This is RETRYABLE and usually clears within seconds, as soon as one of the account's in-flight operations finishes. Honour the Retry-After header.

Do not confuse this with the other 429 on these routes: the gateway's per-key REQUEST-RATE limit reports RATE_LIMIT_EXCEEDED, and the per-connection HTTP session cap reports SESSION_SLOTS_EXHAUSTED. The code field distinguishes them. No credit or quota is consumed by a rejection.

application/json

Example account_concurrency_exhausted

{
  "error": "too many concurrent operations for this account",
  "code": "CONCURRENCY_LIMIT_EXCEEDED",
  "detail": "too many concurrent operations for this account",
  "retryable": true,
  "timestamp": "2026-01-15T10:30:00Z",
  "data": {
    "limit": 4,
    "observed": 4,
    "unit": "operations",
    "bound": "account_concurrency_tts"
  }
}

TTS failed before binary output was committed. If output was already committed, the partial binary 200 stream ends without an appended JSON error.

This status carries two distinct codes. TTS_SYNTHESIS_FAILED is the retryable case: a model-resolution, capacity, or inference failure that a later attempt may clear. TTS_VOICE_RESOLUTION_FAILED (SAU-2258) is non-retryable: a resolved voice whose stored data is incomplete or corrupt (missing audio or transcript, an unusable stored URI, or audio that is not INT16 PCM), or an unclassified database/storage error. Resending the identical request cannot fix broken server-side voice data.

Text and voice-REFERENCE validation failures do NOT reach here: they are reported as 400, 413 or 422 with a specific code before synthesis begins. A caller-supplied voice_id that is invalid or unknown is also not here — it is 400 (VALIDATION_INVALID_UUID / TTS_VOICE_NOT_FOUND); a proven database/storage outage during voice resolution is 503 (SERVER_DEPENDENCY_FAILURE, retryable).

application/json

Retryable model/capacity/inference failure

{
  "error": "TTS synthesis failed",
  "code": "TTS_SYNTHESIS_FAILED",
  "detail": "TTS synthesis failed",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": true,
  "timestamp": "2026-01-15T10:30:00Z"
}

Resolved voice has incomplete/corrupt stored data (non-retryable)

{
  "error": "selected voice could not be resolved",
  "code": "TTS_VOICE_RESOLUTION_FAILED",
  "detail": "selected voice could not be resolved",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

A required dependency was temporarily unavailable. The response is retryable: the identical request may succeed once that dependency recovers.

TTS_MODERATION_UNAVAILABLE means the content-moderation authority could not make a decision, so synthesis failed closed. It is deliberately distinct from TTS_INPUT_NOT_ALLOWED: an infrastructure failure must not be reported as a policy rejection.

SERVER_DEPENDENCY_FAILURE is a positively-classified transient database or object-storage outage while resolving voice_id (SAU-2258). It is distinct from 500 TTS_VOICE_RESOLUTION_FAILED, which identifies broken server-side voice data that a retry cannot fix. Both checks run before quota deduction, rate-limit charge or inference, so a retried request is not double-charged.

application/json

Transient database/storage outage during voice resolution

{
  "error": "voice resolution is temporarily unavailable",
  "code": "SERVER_DEPENDENCY_FAILURE",
  "detail": "voice resolution is temporarily unavailable",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": true,
  "timestamp": "2026-01-15T10:30:00Z"
}

Content-moderation authority temporarily unavailable

{
  "error": "TTS moderation is unavailable",
  "code": "TTS_MODERATION_UNAVAILABLE",
  "detail": "TTS moderation is unavailable",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": true,
  "timestamp": "2026-01-15T10:30:00Z"
}

The non-resetting 25-second synthesis deadline elapsed before a complete protocol-final result was available. This response is retryable and is returned only when binary output has not started; otherwise the partial binary stream ends without appended JSON.

application/json

Example deadline_exceeded

{
  "error": "TTS synthesis deadline exceeded",
  "code": "TTS_DEADLINE_EXCEEDED",
  "detail": "TTS synthesis deadline exceeded",
  "job_id": "7f51f2c2-e7bc-41c8-a850-f848df2ddfc8",
  "retryable": true,
  "timestamp": "2026-01-15T10:30:00Z"
}

Next steps

The direct HTTP response is an undelimited protocol capture, not recoverable raw PCM or WAV. Do not add a WAV header to it. For playable output, use the released Socket.IO SDK path and add a WAV header only after collecting the SDK’s final decoded PCM payload.

On this page