Help

FAQ: API

The questions developers ask before they open the Developer API pages, from keys and base URLs to jobs, webhooks, rate limits, credits and errors.

How do I get an API key?

Open Developers in the portal, select the API Keys tab and select Create Key. The workspace needs an active or trial subscription. The secret starts with ek_ and is shown once, so use Copy or Download JSON before you close the dialog; afterwards the portal displays only its first 8 characters, and a lost secret means deleting the key and creating a new one. See Get an API key.

How do I send the key with a request?

In the Authorization header with the Bearer scheme, as Authorization: Bearer YOUR_API_KEY. The header is read strictly: Bearer is case-sensitive, the token must start with ek_, and a key sent as a query parameter, a cookie or another header is ignored, so the request gets 401. See Authentication.

Which base URL do I call?

Every request goes to one host, and the callout at the top of every developer page shows it. A key works only for the workspace that owns it, and keys, jobs, webhooks and request logs never cross workspaces. See Base URL.

Why do I get 401 Unauthorized?

Every 401 carries the same message, so work through the five causes in order: the header is missing or is not Bearer followed by an ek_ token, no key matches the token because it was mistyped or is unknown, the key was deleted, the key is disabled, or the account that owns the key is closed. Compare the first 8 characters with the list under API Keys and check the key's Status. See Authentication.

Which endpoints does the API have?

Fifteen, all under /v1, which is the only version. Text to Speech has generate synchronously, start a job, list voices, list jobs, get a job and delete a job; Speech to Text has transcribe synchronously, start a job, list jobs, get a job and delete a job; Sound Cleaning has clean audio, list jobs, get a job and delete a job. Every response is one JSON object with success, statusCode, errorMessage and data, and a successful call returns HTTP 200 even for POST. Any key in the workspace with access to a product can list, get and delete that product's API jobs, whichever key created them. Assets and agents are in the portal. See Developer API overview.

How do I generate speech?

Call GET /v1/text-to-speech/voices, keep the id of the voice you want, then send text and voiceId to POST /v1/text-to-speech/sync for the audio link in the same response, or to POST /v1/text-to-speech for a job id. speed, cfg, numSteps and tashkeel are optional, text takes 1 to 500 characters on both endpoints, and audioUrl is a signed link to a WAV file that expires, so download the file when it arrives. See Text to Speech quickstart.

How do I transcribe audio?

Send the file as the file part of a multipart/form-data request to POST /v1/speech-to-text/sync or to POST /v1/speech-to-text, for audio of up to 10 minutes; both take 150 MB at most, and the part's Content-Type must start with audio/ and is set by you, because the file extension is not read. The transcript is one string with its durationSeconds. Send identify_speakers=true to also get the transcript as timed segments, each with its speaker, and download any finished job as TXT, SRT subtitles or JSON from GET /v1/speech-to-text/jobs/{jobId}/export. There are no word timestamps. An optional language field takes auto, ar or en. Auto lets the service decide, which is Arabic today and also handles mixed and clean English speech. Use ar for Arabic and mixed Arabic/English. Use en only for wholly English speech, because Arabic sent as en comes back garbled. See Speech to Text quickstart.

Should I use the synchronous or the asynchronous endpoint?

Synchronous when a person is waiting for the result in the same request and the input is inside the synchronous limit; asynchronous for batches, clients with a short HTTP timeout, or when you want a webhook to tell you the job ended. Both cost the same credits for the same input, and both Text to Speech endpoints share the 500-character limit, so text length never forces the choice. See Synchronous and asynchronous calls.

How do I know when an asynchronous job is done?

Poll GET /v1/text-to-speech/jobs/{jobId} or GET /v1/speech-to-text/jobs/{jobId} every few seconds until status is completed or failed, or register a webhook and receive job.completed with the result inside it. A job that stays processing for more than 10 minutes is marked failed within 15 minutes of the POST with its credits refunded, and that timeout sends no webhook, so poll the job once if no event has arrived after 15 minutes. See Synchronous and asynchronous calls.

How do I set up a webhook?

Open Developers, select the Webhooks tab and select Create Webhook, giving it a name, an endpoint URL (HTTPS is recommended) and at least one of Job completed, Job failed, Spending warning and Spending exhausted. The signing secret starts with whsec_ and is shown once, in the add-endpoint dialog right after you select Create, with a Copy button. Copy it and store it. It cannot be shown again; afterwards only its first 12 characters are shown. See Configure a webhook.

How do I verify a webhook signature?

Take the raw request body as bytes, join X-Webhook-Timestamp, a dot and the body, compute HMAC-SHA256 over that string keyed with the full whsec_ secret, and compare the lowercase hex result with X-Webhook-Signature in constant time. Reject a timestamp more than 300 seconds from your clock, the recommended window, answer 2xx within 10 seconds, and only then process the event. See Verify a webhook signature.

Why did my endpoint get the same event twice, or the webhook turn itself off?

A delivery gets 3 attempts, 5 and then 10 seconds apart, and any response other than a 2xx within 10 seconds counts as a failure, so a slow handler is retried and sees the event again; de-duplicate on jobId plus the X-Webhook-Event header, answer first and process after. When 5 deliveries in a row fail after all their attempts, the webhook is disabled and the portal shows Disabled; fix the endpoint and enable it again. Events that fired while it was off are not replayed. See Delivery, retries and failures.

What are the rate limits?

100 requests per 60 seconds, counted for one API key on one endpoint; two keys have separate counts, and one key's calls to one endpoint do not count against its calls to another. Every poll counts, and once a key exceeds the limit that endpoint rejects it for 60 seconds with 429, ThrottlerException: Too Many Requests and a Retry-After header, so wait that many seconds before you retry. See Rate limits.

How much do API calls cost?

Text to Speech costs 1 credit per character of text, spaces included, and Speech to Text 100 credits per minute of audio, charged per second. Each charge is taken before the work runs and refunded if the job fails, creditsConsumed on every job is the number charged, a whole number of credits, and GET calls cost nothing. See Credits.

What does the Credit Limit on a key do?

It caps how many credits that one key may spend per billing cycle; it adds no credits and does not change prices. A Text to Speech call that would cross the limit is rejected with 429, Monthly spending limit exhausted and no Retry-After header, while a Speech to Text call always runs and counts afterwards; a key with a limit also sends spending.warning once per cycle at 80% and spending.exhausted on every call at or past the limit. See Credits.

What does an error look like, and which ones can I retry?

An error is the same envelope with success set to false, data set to null and the reason in errorMessage, and nothing is charged for a request that ends in an error. Retry only the rate-limit 429 after Retry-After seconds and the 503 and 504 responses, with backoff; a 400, 401, 402, 403 or 404 returns the same answer until you change the request, the key or the balance, and never put a POST behind an automatic retry, because every POST creates a new job and a new charge. See Errors and Retry requests safely.

Where do I find code samples?

Every developer page shows its request in cURL, Python and Node, and Code samples has two complete programs per language: an asynchronous Text to Speech job from request to saved audio file, and an asynchronous Speech to Text job from upload to transcript. Each one runs with a single edit, your API key.

Where do my API jobs show up in the portal?

On the Request Log tab under Developers, which lists the 50 most recent requests made with a known key, any method and any status, with their status, method, path, key name and time. Requests rejected with 401 (missing or invalid key), the per-IP 429, a per-key 429 after the first one of its limit window, a body over 100 KB (413) and a body that is not valid JSON (400) are not recorded. Jobs made with an API key are not on the Assets page or in History; read them from GET /v1/text-to-speech/jobs, GET /v1/speech-to-text/jobs and GET /v1/sound-cleaning/jobs, which return the API jobs of the workspace, whichever key created them. See Read the request log.