Browse API documentation
Apply for API access

Authentication and errors

Authentication and errors

Authenticate with a server-side API key. Use request IDs to trace failures and idempotency keys to retry an operation without starting it twice.

Updated October 18, 2026 · API version 1

Send a server-side Bearer key

Test keys begin with vm_test_ and live keys begin with vm_live_. Send the complete key in the Authorization header. Never embed either key in browser JavaScript, a mobile application bundle, a public repository, logs, analytics, or a URL.

Authorization: Bearer vm_test_…
Content-Type: application/json

Developer generation routes do not allow browser CORS. Call the API from infrastructure you control, then return only the result your client needs.

Use idempotency for safe retries

Synchronous POST endpoints accept an optional Idempotency-Key containing 8–128 printable ASCII characters. Production asynchronous Basic POST /v1/speech/jobs requires one; asynchronous Premium remains limited to development and staging. Keep the same key only when retrying the exact same endpoint and JSON payload. VowelMarks retains the completed result or job identity for 24 hours.

  • Same key and payload: replay the successful result without a second usage charge.
  • Same key with a different payload: 409 idempotency_conflict.
  • A duplicate while the first request is still running: retryable 409 request_in_progress.
  • A failed validation or generation does not consume usage.

Read the rate-limit headers

Successful authenticated JSON responses include RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. The published limit is shared by every key in the same organization and environment, so adding keys does not multiply capacity. Authenticated malformed requests, idempotent replays, and job create/read/stream/cancel requests still count toward requests per minute. This request limit is an API admission ceiling; Premium Speech also depends on the speech provider's separate capacity.

X-Request-Id: 95b…
RateLimit-Limit: 20
RateLimit-Remaining: 18
RateLimit-Reset: 41

RateLimit-Reset is the number of seconds until the current window resets, not a Unix timestamp. On a retryable failure, Retry-After tells your client how many seconds to wait. Neither header describes remaining speech minutes; read those from GET /v1/usage.

Handle the structured error envelope

Every API error has a request ID plus a stable machine-readable code. Branch on error.code and error.retryable rather than comparing message text. Include X-Request-Id when contacting VowelMarks.

{
  "request_id": "95b…",
  "error": {
    "code": "service_unavailable",
    "message": "The request could not be completed.",
    "category": "service",
    "action": "Retry the request later.",
    "retryable": true
  }
}
HTTP statusMeaningWhat to do
400Invalid JSON, input, or optionsCorrect the request using error.code and error.action.
401Missing, invalid, or revoked API keyCheck the full Bearer key and replace it if needed.
402Insufficient text or speech allowanceCheck usage and the approved plan. Do not loop on the same request.
403Inactive access or insufficient scopeReview the organization, entitlement, and key scopes.
404Unknown route or inaccessible resourceCheck the URL, organization, and environment.
409Request conflictFor request_in_progress, wait and retry with the same key. For idempotency_conflict, restore the original payload or use a new key for a genuinely new operation.
413Request body too largeReduce both the text and serialized JSON size.
429Request rate exceededWait for Retry-After; do not send parallel retries.
5xxService or generation failureRead error.retryable. Some unavailable capabilities are deliberately non-retryable.

The table summarizes common responses, not every error code. The returned error.action gives the next step for that specific failure.

Set a complete-response deadline

Some processing origins sleep while idle, so the first request after an idle period can spend tens of seconds waiting for the service to wake. Warm latency is usually lower. Input length, the selected capability, upstream provider time, and capacity can add more variation. API v1 does not publish a latency or availability SLA.

Configure both a connection timeout and a deadline that remains active until the complete JSON response body has been read. A practical starting point is 120 seconds for text generation. The synchronous speech route may need several minutes for long passages; allow up to 15 minutes for a maximum-size request or split it into smaller sections. Tune these budgets from your own measurements.

If your deadline expires after the request was sent, treat the outcome as unknown. Do not create a new idempotency key. Wait briefly, then retry the same endpoint, body, and key so a completed result can replay safely or an in-progress request can report its state.

Retry policy

  • Retry only when retryable is true.
  • Honor Retry-After and add random jitter before the next attempt.
  • Reuse the original Idempotency-Key and exact payload.
  • Do not retry validation, authentication, authorization, or quota errors until the stated action has been taken.
  • Keep the deadline active while reading the complete response body, not only until response headers arrive.
  • A network error or client timeout has an unknown outcome. Retry with the original key and exact payload.