API documentation
Turn short text into a complete, watermarked WAV. One Project Key connects your application to the available speech models.
Complete, watermarked WAV responses from the enabled model catalog.Permanent audio asset storage is outside this release. Program generation uses credits; the signed-in Playground is free.
On this page
Your first watermarked clip
Create a Project in the Console, create a Project API Key, and prepare wallet credits and a sufficient Key budget. Keep the Key in your server environment.
- Set up accessCreate a Project Key and configure
TIMBRELAY_API_KEYon your server. - Choose a model & voiceRead the live catalogs, then set
TIMBRELAY_MODELandTIMBRELAY_VOICEto compatible IDs. - Send a stable operation IDSave the request and its idempotency ID before sending. The same business action must reuse both on recovery.
For the Node.js example, download and install the SDK first. cURL and Python use the HTTP API directly.
import { writeFile } from "node:fs/promises";
import { Timbrelay } from "@timbrelay/sdk";
const client = new Timbrelay({
apiKey: process.env.TIMBRELAY_API_KEY!,
baseURL: "https://api.timbrelay.com",
});
const [models, voices] = await Promise.all([
client.models.list(),
client.speakers.list(),
]);
// Choose IDs from the live catalog, not an assumed default.
const model = models.data.find(
(m) => m.available && m.id === process.env.TIMBRELAY_MODEL,
);
const voice = voices.data.find(
(v) => v.id === process.env.TIMBRELAY_VOICE && v.models.includes(model?.id ?? ""),
);
if (!model || !voice) throw new Error("Choose a compatible model and voice.");
// Persist this action ID and exact input before sending.
const result = await client.audio.speech.create(
{ model: model.id, voice: voice.id, input: "Welcome to our application. Your announcement is ready." },
{ idempotencyKey: "announcement-123-action-456" },
);
await writeFile("speech.wav", result.audio);
// result.watermarkApplied is true for every resolved call.Examples do not run in this page. A generation you send from your application may spend credits. Very short audio may not meet the configured watermark minimum.
Authentication & API origin
Program requests use a Project API Key as a bearer token. Your Key selects the Project; do not supply a Project ID in the speech request.
Authorization: Bearer <YOUR_PROJECT_API_KEY>| Environment | API origin | Access |
|---|---|---|
| Production | https://api.timbrelay.com | Invited accounts |
| Staging | https://api.staging.timbrelay.com | Invited testers |
| Local | http://localhost:8000 | Your configured development API |
Examples on this build use https://api.timbrelay.com. Append the endpoint path for HTTP calls; pass only the origin to the SDK.
Never place a Project Key in frontend bundles, URLs, browser storage or logs. Console Cognito tokens, TTS Gate keys and OfSpectrum credentials cannot replace a Project Key.
Node.js & TypeScript SDK
The preview package includes prebuilt ESM JavaScript, TypeScript declarations, examples and integration documentation. It requires Node.js 20+ and has zero runtime dependencies.
Save the download in your application directory, then install it from the file. The package has not been published to npm.
npm install ./timbrelay-sdk-0.1.0-preview.1.tgzSHA-256 checksumOpenAPI snapshotChinese integration guide
Verify the download with shasum -a 256 -c SHA256SUMS in the same directory as timbrelay-sdk-0.1.0-preview.1.tgz.
| Method | Purpose |
|---|---|
client.models.list() | Read available models and current program prices. |
client.speakers.list() | Read preset voices and model compatibility. |
client.audio.speech.create(input, options) | Generate and return confirmed watermarked WAV. |
client.watermark.decode(wavBytes) | Explicitly detect a service-level watermark. |
Every method sends one HTTP request. The SDK has no automatic retries, new operation IDs or fallback providers. Encoding is handled by Timbrelay; customers do not install the OfSpectrum SDK. CommonJS applications can use await import("@timbrelay/sdk") inside an async function.
Find models & compatible voices
/v1/modelsReturns { "object": "list", "data": [...] }. Select a model with available: true. Model fields include id, name, sample_rate_hz, languages, capabilities, response_formats, price_per_generation_micros and price_version.
/v1/speakersReturns the same list envelope. Each voice provides id, name, language and compatible model IDs in models. Both endpoints require a Project Key and do not generate audio.
curl --fail-with-body "https://api.timbrelay.com/v1/models" \
-H "Authorization: Bearer $TIMBRELAY_API_KEY"
curl --fail-with-body "https://api.timbrelay.com/v1/speakers" \
-H "Authorization: Bearer $TIMBRELAY_API_KEY"Catalog metadata can change. Do not assume that an example model, voice, price or internal upstream format will always be available.
Generate speech
/v1/audio/speechSend JSON with Content-Type: application/json and a required Idempotency-Key header. The server completes synthesis, watermark encoding and persistence before returning the deliverable audio.
| Field | Type | Requirement | Description |
|---|---|---|---|
model | string | Required | An enabled model ID from GET /v1/models. Check available=true. |
voice | string | Required | A preset ID from GET /v1/speakers whose models include your model ID. |
input | string | Required | Nonblank short text, at most 1,000 Unicode code points. No unsupported control characters. |
speed | number | Default: 1 | A finite number from 0.25 to 4. |
response_format | string | Default: wav | Only wav is supported. The response is a complete audio file. |
Unknown fields are rejected, including project_id or free. The idempotency header accepts 1–128 ASCII letters, digits, underscores or hyphens. Output is a complete WAV; streaming is not supported.
Watermark failure does not deliver original audio or settle the failed generation. The SDK also rejects missing or unapplied watermark status. It never pads silence or falls back to raw audio.
Read the audio response & charge
A successful HTTP response is 200 with complete audio/wav bytes. It is not JSON, a stream, or an asset URL. Check status, watermark confirmation and WAV integrity before exposing direct HTTP results to users.
| Header | Meaning |
|---|---|
Content-Type | audio/wav on a successful complete audio response. |
X-Timbrelay-Watermark | Only applied confirms persisted watermark completion. Reject a missing or not-applied value. |
X-Timbrelay-Generation-Id | Generation UUID. This is not a permanent asset ID. |
X-Timbrelay-Charged-Micros | Original generation charge in USD micros (1 USD = 1,000,000 micros), including on replay. |
X-Timbrelay-Idempotent-Replay | true when returning the saved result of the same request; no second settlement. |
Cache-Control | no-store. Save the delivered WAV in your own application if you need to retain it. |
The SDK exposes audio as a Uint8Array, plus generationId, watermarkApplied, chargedMicros, replayed, idempotencyKey, sampleRateHz and durationSeconds.
Model prices come from the current catalog. Check the selected model price and project spending limit before generating. On replay, the charge header reports the original settlement amount; it does not mean another charge. Successful replay audio expires after 24 hours, so save the WAV in your own application.
Detect a watermark
/v1/audio/watermark/decodeTimbrelay uses OfSpectrum Neo for watermark detection. Authenticate with your Project Key; no separate OfSpectrum Key is needed.
Upload raw WAV bytes with a Project Key and Content-Type: audio/wav. Use standard PCM16 WAV, mono or stereo, 8–48 kHz, up to 180 seconds and 6,356,992 bytes. This is a separate, explicit call.
curl --fail-with-body "https://api.timbrelay.com/v1/audio/watermark/decode" \
-H "Authorization: Bearer $TIMBRELAY_API_KEY" \
-H "Content-Type: audio/wav" \
--data-binary @speech.wav{
"watermarked": true,
"matches_service_token": true,
"attribution_scope": "service"
}import { readFile } from "node:fs/promises";
const result = await client.watermark.decode(await readFile("speech.wav"));
// { watermarked, matchesServiceToken, attributionScope: "service" }
// Explicit detection; generation never calls decode automatically.A match identifies only the current service token, not a Project, user, generation or ownership. A negative result does not prove the absence of all watermarks. Detection failures are errors, never fabricated negative results. Uploaded audio is not persisted by Timbrelay.
Generation does not run decode automatically. Detection does not create a speech generation or debit the Timbrelay wallet. Speech idempotency IDs and audio replay do not apply to this endpoint: each call is independent, and the SDK does not retry it automatically.
| HTTP status & code | Meaning | Next step |
|---|---|---|
| 502 · decode_invalid_result / decode_failed | Detection failed or the service returned an invalid result. | Treat the outcome as unknown, never as a negative detection. |
| 503 · decode_busy / decode_unavailable | Detection capacity or the detection service is unavailable. | Wait before a deliberate retry. Persistent failures need service support. |
| 504 · decode_timeout | Detection timed out without a confirmed result. | Do not infer a negative result. Any repeat is a new detection request. |
Idempotency & safe recovery
One business action gets one stable ID. Persist it with the exact request before sending, then reuse the same Project Key, ID and input on uncertain-result retries—even after your application restarts.
Save the operation
Store the ID and original parameters in your business records.
Repeat the same request
After uncertainty, recover with the original input and Key.
Reuse the saved result
A completed replay returns the stored WAV without another settlement.
The hosted edge waits up to 120 seconds without response bytes; the backend task lease is 300 seconds. The SDK defaults to a 130-second request timeout. A timeout, connection loss or client cancellation can leave the backend running or already settled.
Do not automatically create a new ID after a timeout. An in-progress operation returns 409 generation_in_progress; wait before recovering. A terminal failed request remains failed under its ID without charge; a deliberate new attempt needs a new ID. Changing the Project Key changes the idempotency scope.
A response rejected by the SDK may already have been settled by the server. Investigate repeated invalid responses and recover under the original ID; SDK rejection alone does not establish billing failure.
Errors & current limits
{
"detail": {
"code": "generation_in_progress",
"message": "This request is still running; retry the same request ID later"
}
}
// Other failures may use a string detail or a validation-error array.
// A gateway can return HTML. Check HTTP status before parsing audio.| Status / code | Meaning | Next step |
|---|---|---|
| 401 / 403 | Invalid Key or unavailable Project permissions/billing. | Check the Project Key, expiration, revocation and Project status. |
| 402 | Insufficient credits or Project Key budget. | Resolve the wallet or Key limit before retrying. |
| 409 · generation_in_progress | The original operation is still running. | Wait, then repeat identical input with the same Key and idempotency ID. |
| 409 · idempotency_conflict | The ID was already used with different input. | Restore the original input, or deliberately start a new business action. |
| 410 · result_expired | The successful replay WAV expired after 24 hours. | Use your saved audio. The old ID is not charged again. |
| 413 / 415 / 422 | Upload, format or input validation failed. | Check size, PCM16 WAV, text length, voice/model and speed. Very short clips may be insufficient for the watermark token. |
| 429 | Capacity or active generation limit reached. | Use bounded backoff. Preserve the original ID when recovering an existing action. |
| 502 / 503 / 504 | Service failure, unavailability or timeout. | For speech, recover with the original ID before deciding on a new attempt. For detection, follow the decode error guidance above. |
SDK failures extend TimbrelayError. APIError includes HTTP status and a safe error code; TimeoutError, ConnectionError and RequestAbortedError describe uncertain outcomes. WatermarkError and InvalidResponseError expose no audio.
Short text and complete WAV responses only. Streaming, MP3, SSML, long/batch tasks, voice cloning, third-party BYOK and permanent S3 audio assets are not available. Python is supported through HTTP examples; a Python SDK has not been released.
Ready to test your integration?
Inspect authentication and catalog responses before sending a generation.