HTTP API · v1

Voices & audio API

From your first request to a complete integration. Create voices, generate audio and use the characters in your plan.

The API is disabled in this environment. The reference is public; live requests are not available yet.

Quickstart

Quickstart

1. Sign in and open Account → Developers → API. Create a key with voices:read, speech:generate, jobs:read and audio:read. Store the secret in VOCLONER_API_KEY on your server.

2. Call GET /voices and choose an authorized identifier. Send POST /speech with voice_id, text, format and your own stable Idempotency-Key.

3. Save the job id and poll GET /jobs/{id}. Once completed, download GET /assets/{asset_id}/content with the same Authorization header. The downloadable examples include the complete flow.

POST /speech

curl --request POST 'https://api.vocloner.org/v1/speech' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"voice_id":"c816ce5b-22f5-4ed2-91a9-90e79b874a24","text":"Hola, esta es mi primera generación con Vocloner.","format":"mp3"}'

Authentication and permissions

Send Authorization: Bearer vcl_api_... with every request. REST and MCP keys are different credentials. Never place secrets in URLs, repositories or distributed applications.

Every key has explicit permissions, expiration and an optional budget. Keys cannot administer accounts or issue additional keys. Revoke a compromised key from the dashboard.

To rotate, create a successor, update your servers and revoke the old key. Rotation does not automatically revoke the existing key.

Reading a job requires jobs:read and its original operation permission. Canceling also requires jobs:cancel. Working with files requires files:write. Select these permissions when creating your key.

Cloning, design and consent

To clone, prepare a file with purpose: clone, upload it and confirm it. POST /voices requires consent_ownership: true. When a challenge is required, obtain its phrase from /consent-challenges, record it and upload the audio with purpose: consent.

New voices are private. Confirm consent_public_use: true to request publication. A voice becomes public only after required review and moderation. Report unauthorized use with /reports.

Design returns temporary candidates. Retrieve the batch and save a candidate using candidate_id before it expires. Saving requires an available voice slot and does not charge the design again.

Text, emotions and dialogues

POST /speech accepts MP3 or WAV and up to 12,000 text characters; your plan determines the effective per-request limit. Compatible expressive tags such as [excited] and [whispering] follow the web billing rules.

Dialogues support two to ten lines, authorized voices and gaps from 0 to 3,000 ms. Your plan must enable this feature. Current limits apply to each line.

Generated audio is processed and verified before it becomes available. Bytes without the forensic watermark are not delivered. A processing failure can prevent delivery even after the provider responds.

Files, tools and downloads

POST /files returns temporary upload instructions for private Storage. Upload the file following those instructions and confirm it with /files/{id}/complete. Pending files cannot be used.

The server validates format, actual size, duration and hash. Limits depend on purpose and operation; check /capabilities. Temporary files expire.

Tools accept exactly one file_id or generation_id. Check enabled operations and options before calling /audio-tools/{operation}. Derivatives of generated audio retain their provenance.

GET /assets/{id}/content requires authorization on every download. Retrieve /generations for history. Resources owned by someone else return 404; active jobs may prevent file deletion.

Upload limits: cloning 20 MiB and 5–270 seconds; remote tools 20 MiB and up to 20 minutes; local tools 25 MiB and up to 15 minutes; consent 5 MiB. Duration must be verifiable. The capabilities response is the reference for your environment.

Jobs, retries and idempotency

Long operations return 202 with id, status, status_url, result and usage. States are queued, running, reconciling, completed, failed and canceled. Reconciliation resolves an external effect whose outcome is not yet confirmed.

Use Idempotency-Key for creation and update operations. Reuse the same key and content after a timeout. Different content with the same key returns 409. Idempotency records are retained for thirty days.

Respect Retry-After when polling jobs or receiving 429/503. A POST with Prefer: wait=20 may return 200 or 202; both use the job resource. Never create another job just because the first one is slow.

Queued cancellation is immediate. Once work starts, cancellation is a request: wait for its final state and check usage before assuming no charge occurred.

The Postman collection keeps a different Idempotency-Key for each operation. Do not clear its variable when retrying. To begin a new operation, clear the corresponding idempotency_<operationId> collection variable.

Characters, limits and settlement

The API, web and MCP share the same plan. TTS charges billable text; a dialogue adds its lines. Cloning and designing a batch each cost 1,000 characters. Saving a candidate does not add a second design charge.

Reads and downloads do not consume characters. Tools retain their operation cost, which may depend on duration. /capabilities describes availability and limits; there is no account or balance endpoint.

Characters are reserved before execution, committed once on completion and released after definitive failure according to the operation policy. A dialogue may incur partial usage.

A key’s UTC monthly budget adds a limit to the shared balance and counts all active reservations, including those from a previous month. Creating more keys does not increase quota or concurrency. Results report reserved_characters, billed_characters and remaining_characters when applicable.

Signed notifications

Register HTTPS destinations in the developer dashboard for job.completed and job.failed. Save the signing secret when shown; polling is available without a destination.

Verify the signature against the original bytes before processing an event. Validate the timestamp and deduplicate by event identifier. Retries may deliver the same event more than once. Return 2xx after persisting it.

Events contain id, type, created_at and data: {job_id, status}. Destinations are managed in the dashboard. Use the verification example and project deployment guide when integrating your receiver.

Vocloner-Signature uses t=<unix>,v1=<hexadecimal HMAC-SHA256>. Sign the timestamp, a dot and the original body using the secret. Reject timestamps more than five minutes away. Vocloner-Event-Id identifies deliveries for deduplication.

Verify a notification on your server

import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(rawBody: Buffer, header: string, secret: string) {
  const match = /^t=(\d{1,12}),v1=([a-f0-9]{64})$/.exec(header);
  if (!match) return false;
  const timestamp = Number(match[1]);
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
  const expected = createHmac('sha256', secret)
    .update(String(timestamp) + '.').update(rawBody).digest();
  return timingSafeEqual(expected, Buffer.from(match[2]!, 'hex'));
}

// Read the ORIGINAL request bytes, before parsing JSON.
export async function handleWebhook(request: Request,
  persistEventOnce: (event: { id: string; type: string;
    data: { job_id: string; status: string } }) => Promise<void>) {
  const rawBody = Buffer.from(await request.arrayBuffer());
  const secret = process.env.VOCLONER_WEBHOOK_SECRET!;
  if (!secret || !verify(rawBody,
      request.headers.get('Vocloner-Signature') ?? '', secret)) {
    return new Response('Invalid signature', { status: 401 });
  }
  const event = JSON.parse(rawBody.toString('utf8'));
  if (event.id !== request.headers.get('Vocloner-Event-Id')) {
    return new Response('Invalid event ID', { status: 400 });
  }
  // Required: atomically insert event.id into a UNIQUE column and
  // persist the job notification in your database. A duplicate ID
  // returns 200 without applying the event again. On DB failure,
  // return 500 so Vocloner can retry. Query /jobs/{job_id} with
  // your API key when you need the authoritative result.
  await persistEventOnce(event);
  return new Response(null, { status: 200 });
}

Errors, retention and support

All errors use error.code, error.message, error.request_id and error.retryable. Keep X-Request-Id to diagnose a request without storing keys or audio in logs.

Pagination returns items and next_cursor. Treat cursors as opaque and pass them unchanged. Resource identifiers are UUIDs, not provider identifiers.

Results and files follow current retention policies. Download anything you need to keep before it expires. The first version does not offer early streaming, real-time conversation or a delivery SLA.

HTTPWhat to do
400 / 422Review fields, formats and limits in the contract.
401Replace an invalid, expired or revoked key.
403Review permissions, consent and plan capabilities.
404Check the resource ID and owner.
409Reuse the original content or choose a new key for a new operation.
413Reduce file size to match its purpose limits.
429Check quotas and concurrency; respect Retry-After.
500 / 503Keep request_id and retry only when appropriate, using the same Idempotency-Key.

Endpoint reference

Example identifiers and responses are illustrative. Replace them with authorized resources from your account.

26 / 26

GET/voicesList voices

Owned voices and authorized public voices. Paginate with cursor and limit.

Required permission
voices:read
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/voices' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "items": [
    {
      "id": "c816ce5b-22f5-4ed2-91a9-90e79b874a24",
      "name": "Example voice",
      "visibility": "private",
      "language": "es",
      "category": "narrator",
      "status": "ready",
      "avatar_url": null,
      "review_state": "approved",
      "created_at": "2026-10-29T12:00:00.000Z"
    }
  ],
  "next_cursor": null
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
GET/voices/{id}Get a voice

Retrieve metadata for a voice you are allowed to use.

Required permission
voices:read
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/voices/c816ce5b-22f5-4ed2-91a9-90e79b874a24' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "id": "c816ce5b-22f5-4ed2-91a9-90e79b874a24",
  "name": "Example voice",
  "visibility": "private",
  "language": "es",
  "category": "narrator",
  "status": "ready",
  "avatar_url": null,
  "review_state": "approved",
  "created_at": "2026-10-29T12:00:00.000Z"
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/voicesClone a voice

Upload and confirm a recording before cloning. Include a recorded challenge when required. New voices are private.

Required permission
voices:clone
Usage
1,000 characters

Request body

FieldType and limitsRequired
file_idstring · uuidRequired
namestring · length 1–120Required
consent_ownershipbooleanRequired
languagestring · length 2–40 · default: "es"Optional
categorystring · length 2–40 · default: "narrator"Optional
localestring · es | en · default: "es"Optional
consent_challenge_idstring · uuidOptional
consent_file_idstring · uuidOptional

Request examples

curl --request POST 'https://api.vocloner.org/v1/voices' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"file_id":"ab198ae5-9225-40f3-b176-56ed83861080","name":"Mi voz","consent_ownership":true,"language":"es","category":"narrator","locale":"es"}'

Response

202 Accepted · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "operation": "clone",
  "status": "queued",
  "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
  "created_at": "2026-10-29T12:00:00.000Z",
  "started_at": null,
  "completed_at": null,
  "cancel_requested": false,
  "result": null,
  "error": null,
  "usage": {
    "reserved_characters": 1000,
    "billed_characters": 0,
    "remaining_characters": 9000
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
PATCH/voices/{id}Update a voice

Update the name, language or category of an owned voice.

Required permission
voices:write
Usage
No character charge

Request body

FieldType and limitsRequired
namestring · length 1–120Optional
languagestring · length 2–40 · default: "es"Optional
categorystring · length 2–40 · default: "narrator"Optional

Request examples

curl --request PATCH 'https://api.vocloner.org/v1/voices/c816ce5b-22f5-4ed2-91a9-90e79b874a24' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"name":"Narración"}'

Response

200 · application/json

{
  "id": "c816ce5b-22f5-4ed2-91a9-90e79b874a24",
  "name": "Example voice",
  "visibility": "private",
  "language": "es",
  "category": "narrator",
  "status": "ready",
  "avatar_url": null,
  "review_state": "approved",
  "created_at": "2026-10-29T12:00:00.000Z"
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
DELETE/voices/{id}Delete a voice

Delete an owned voice. Existing generations keep their retention rules.

Required permission
voices:delete
Usage
No character charge

Request examples

curl --request DELETE 'https://api.vocloner.org/v1/voices/c816ce5b-22f5-4ed2-91a9-90e79b874a24' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "deleted": true
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/voices/{id}/publication-requestsRequest publication

Confirm public use permission and request review. A request does not automatically publish the voice.

Required permission
voices:publish
Usage
No character charge

Request body

FieldType and limitsRequired
consent_public_usebooleanRequired

Request examples

curl --request POST 'https://api.vocloner.org/v1/voices/c816ce5b-22f5-4ed2-91a9-90e79b874a24/publication-requests' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"consent_public_use":true}'

Response

201 · application/json

{
  "voice_id": "c816ce5b-22f5-4ed2-91a9-90e79b874a24",
  "review_state": "pending"
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/voices/{id}/reportsReport a voice

Report impersonation, missing consent or other abuse for review.

Required permission
voices:report
Usage
No character charge

Request body

FieldType and limitsRequired
reasonstring · impersonation | no_consent | offensive | spam | otherRequired
detailstring · length 0–1000Optional

Request examples

curl --request POST 'https://api.vocloner.org/v1/voices/c816ce5b-22f5-4ed2-91a9-90e79b874a24/reports' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"reason":"no_consent","detail":"Información para la revisión."}'

Response

200 · application/json

{
  "reported": true
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/voice-designsDesign voice candidates

Describe a voice to obtain temporary candidates. Save a candidate before using it for speech.

Required permission
voices:design
Usage
1,000 characters

Request body

FieldType and limitsRequired
promptstring · length 8–1000Required

Request examples

curl --request POST 'https://api.vocloner.org/v1/voice-designs' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"prompt":"Una voz cálida, clara y pausada para narración en español."}'

Response

202 Accepted · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "operation": "voice_design",
  "status": "queued",
  "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
  "created_at": "2026-10-29T12:00:00.000Z",
  "started_at": null,
  "completed_at": null,
  "cancel_requested": false,
  "result": null,
  "error": null,
  "usage": {
    "reserved_characters": 1000,
    "billed_characters": 0,
    "remaining_characters": 9000
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
GET/voice-designs/{id}Get a voice design

Retrieve candidates and expiration for an owned design batch.

Required permission
voices:design
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/voice-designs/c816ce5b-22f5-4ed2-91a9-90e79b874a24' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "operation": "voice_design",
  "status": "completed",
  "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
  "created_at": "2026-10-29T12:00:00.000Z",
  "started_at": "2026-10-29T12:00:00.000Z",
  "completed_at": "2026-10-29T12:00:00.000Z",
  "cancel_requested": false,
  "result": {
    "design_id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
    "candidates": [
      {
        "id": "6e657fb6-cf58-46d8-9311-7f3828b203c7",
        "index": 0,
        "duration_ms": 3500,
        "audio_url": "https://api.vocloner.org/v1/assets/6e657fb6-cf58-46d8-9311-7f3828b203c7/content"
      }
    ]
  },
  "error": null,
  "usage": {
    "reserved_characters": 46,
    "billed_characters": 46,
    "remaining_characters": 9000
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/voice-designs/{id}/voicesSave a candidate

Create a reusable private voice without charging the design again. Requires an available voice slot.

Required permission
voices:design
Usage
No character charge

Request body

FieldType and limitsRequired
candidate_idstring · uuidRequired
namestring · length 1–120Required
languagestring · length 2–40 · default: "es"Optional
categorystring · length 2–40 · default: "narrator"Optional

Request examples

curl --request POST 'https://api.vocloner.org/v1/voice-designs/c816ce5b-22f5-4ed2-91a9-90e79b874a24/voices' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"candidate_id":"c816ce5b-22f5-4ed2-91a9-90e79b874a24","name":"Narradora","language":"es","category":"narrator"}'

Response

202 Accepted · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "operation": "voice_design_select",
  "status": "queued",
  "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
  "created_at": "2026-10-29T12:00:00.000Z",
  "started_at": null,
  "completed_at": null,
  "cancel_requested": false,
  "result": null,
  "error": null,
  "usage": {
    "reserved_characters": 46,
    "billed_characters": 0,
    "remaining_characters": 9000
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/speechGenerate speech

Convert text to MP3 or WAV. Supports compatible expressive tags. Prefer: wait=20 waits up to twenty seconds; the response may still be 202.

Required permission
speech:generate
Usage
Billable text characters

Request body

FieldType and limitsRequired
voice_idstring · uuidRequired
textstring · length 1–12000Required
formatstring · mp3 | wav · default: "mp3"Optional

Request examples

curl --request POST 'https://api.vocloner.org/v1/speech' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"voice_id":"c816ce5b-22f5-4ed2-91a9-90e79b874a24","text":"Hola, esta es mi primera generación con Vocloner.","format":"mp3"}'

Response

202 Accepted · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "operation": "speech",
  "status": "queued",
  "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
  "created_at": "2026-10-29T12:00:00.000Z",
  "started_at": null,
  "completed_at": null,
  "cancel_requested": false,
  "result": null,
  "error": null,
  "usage": {
    "reserved_characters": 46,
    "billed_characters": 0,
    "remaining_characters": 9000
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/dialoguesGenerate a dialogue

Between two and ten lines. Every voice must be authorized and the plan must enable dialogues.

Required permission
speech:generate
Usage
Billable text characters

Request body

FieldType and limitsRequired
linesarray · items 2–10Required
lines[].voice_idstring · uuidRequired
lines[].textstring · length 1–12000Required
gap_msinteger · 0–3000 · default: 400Optional

Request examples

curl --request POST 'https://api.vocloner.org/v1/dialogues' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"lines":[{"voice_id":"c816ce5b-22f5-4ed2-91a9-90e79b874a24","text":"Hola."},{"voice_id":"c816ce5b-22f5-4ed2-91a9-90e79b874a24","text":"Bienvenido."}],"gap_ms":400}'

Response

202 Accepted · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "operation": "dialogue",
  "status": "queued",
  "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
  "created_at": "2026-10-29T12:00:00.000Z",
  "started_at": null,
  "completed_at": null,
  "cancel_requested": false,
  "result": null,
  "error": null,
  "usage": {
    "reserved_characters": 46,
    "billed_characters": 0,
    "remaining_characters": 9000
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/filesPrepare an upload

Obtain a temporary authorization for a direct upload to private Storage. Confirm the upload using /complete afterwards.

Required permission
files:write
Usage
No character charge

Request body

FieldType and limitsRequired
file_namestring · length 1–180Required
content_typestring · audio/mpeg | audio/mp3 | audio/wav | audio/x-wav | audio/wave | audio/ogg | audio/flac | audio/x-flac | audio/mp4 | audio/m4a | audio/x-m4a | audio/webmRequired
size_bytesinteger · …–26214400Required
purposestring · clone | audio_tool | local_tool | consentRequired

Request examples

curl --request POST 'https://api.vocloner.org/v1/files' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"file_name":"voz.wav","content_type":"audio/wav","size_bytes":1048576,"purpose":"clone"}'

Response

201 · application/json

{
  "id": "ab198ae5-9225-40f3-b176-56ed83861080",
  "file_name": "voz.wav",
  "content_type": "audio/wav",
  "size_bytes": 1048576,
  "duration_ms": null,
  "sha256": null,
  "purpose": "clone",
  "status": "pending",
  "created_at": "2026-10-29T12:00:00.000Z",
  "expires_at": "2026-10-30T12:00:00.000Z",
  "upload_url": "https://storage.example.com/signed-upload/illustrative-only",
  "upload_token": "ILLUSTRATIVE_UPLOAD_TOKEN",
  "upload_expires_at": "2026-10-29T12:00:00.000Z",
  "upload_method": "PUT",
  "upload_headers": {
    "Content-Type": "audio/wav"
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/files/{id}/completeComplete an upload

Validate actual content, size, duration and hash before allowing use.

Required permission
files:write
Usage
No character charge

Request examples

curl --request POST 'https://api.vocloner.org/v1/files/c816ce5b-22f5-4ed2-91a9-90e79b874a24/complete' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES'

Response

200 · application/json

{
  "id": "ab198ae5-9225-40f3-b176-56ed83861080",
  "file_name": "voz.wav",
  "content_type": "audio/wav",
  "size_bytes": 1048576,
  "duration_ms": 12000,
  "sha256": null,
  "purpose": "clone",
  "status": "ready",
  "created_at": "2026-10-29T12:00:00.000Z",
  "expires_at": "2026-10-30T12:00:00.000Z"
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
GET/files/{id}Get a file

Retrieve status, duration and expiration of an owned file.

Required permission
files:write
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/files/c816ce5b-22f5-4ed2-91a9-90e79b874a24' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "id": "ab198ae5-9225-40f3-b176-56ed83861080",
  "file_name": "voz.wav",
  "content_type": "audio/wav",
  "size_bytes": 1048576,
  "duration_ms": 12000,
  "sha256": null,
  "purpose": "clone",
  "status": "ready",
  "created_at": "2026-10-29T12:00:00.000Z",
  "expires_at": "2026-10-30T12:00:00.000Z"
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
DELETE/files/{id}Delete a file

Delete an owned file when no active job needs it.

Required permission
files:write
Usage
No character charge

Request examples

curl --request DELETE 'https://api.vocloner.org/v1/files/c816ce5b-22f5-4ed2-91a9-90e79b874a24' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "id": "ab198ae5-9225-40f3-b176-56ed83861080",
  "deleted": true
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/consent-challengesCreate a consent challenge

Obtain a temporary phrase, record it and upload the audio with purpose: consent. Include both identifiers when cloning.

Required permission
voices:clone
Usage
No character charge

Request body

FieldType and limitsRequired
localestring · es | en · default: "es"Optional

Request examples

curl --request POST 'https://api.vocloner.org/v1/consent-challenges' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"locale":"es"}'

Response

201 · application/json

{
  "id": "ab198ae5-9225-40f3-b176-56ed83861080",
  "phrase": "Read the challenge returned by your live request.",
  "expires_at": "2026-10-29T12:00:00.000Z",
  "consent_version": "example-version",
  "consent_text": "The live response provides the applicable consent text.",
  "recording_required": true
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/audio-tools/{operation}Process audio

Check /capabilities for available operations and options. Supply exactly one owned file or generation.

Required permission
audio:process
Usage
Per operation; check capabilities

Request body

FieldType and limitsRequired
file_idstring · uuidOptional
generation_idstring · uuidOptional
optionsobject · default: {}Optional
options.start_msinteger · 0–9007199254740991Optional
options.end_msinteger · …–9007199254740991Optional
options.volumenumber · 0–4Optional
options.fade_in_msinteger · 0–30000Optional
options.fade_out_msinteger · 0–30000Optional
options.target_peak_dbnumber · -24–-0.1Optional

Request examples

curl --request POST 'https://api.vocloner.org/v1/audio-tools/trim' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES' \
  --header 'Content-Type: application/json' \
  --data '{"file_id":"ab198ae5-9225-40f3-b176-56ed83861080","options":{"start_ms":0,"end_ms":5000}}'

Response

202 Accepted · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "operation": "audio_tool",
  "status": "queued",
  "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
  "created_at": "2026-10-29T12:00:00.000Z",
  "started_at": null,
  "completed_at": null,
  "cancel_requested": false,
  "result": null,
  "error": null,
  "usage": {
    "reserved_characters": 46,
    "billed_characters": 0,
    "remaining_characters": 9000
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
GET/jobsList jobs

Paginated owned jobs ordered by creation.

Required permission
jobs:read
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/jobs' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "items": [
    {
      "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
      "operation": "speech",
      "status": "completed",
      "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
      "created_at": "2026-10-29T12:00:00.000Z",
      "started_at": "2026-10-29T12:00:00.000Z",
      "completed_at": "2026-10-29T12:00:00.000Z",
      "cancel_requested": false,
      "result": {
        "generation_id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
        "asset_id": "6e657fb6-cf58-46d8-9311-7f3828b203c7",
        "audio_url": "https://api.vocloner.org/v1/assets/6e657fb6-cf58-46d8-9311-7f3828b203c7/content",
        "format": "mp3",
        "duration_ms": 3500
      },
      "error": null,
      "usage": {
        "reserved_characters": 46,
        "billed_characters": 46,
        "remaining_characters": 9000
      }
    }
  ],
  "next_cursor": null
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
GET/jobs/{id}Get a job

Retrieve status, result and billed characters. Respect Retry-After before polling again.

Required permission
jobs:read
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/jobs/c816ce5b-22f5-4ed2-91a9-90e79b874a24' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "operation": "speech",
  "status": "completed",
  "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
  "created_at": "2026-10-29T12:00:00.000Z",
  "started_at": "2026-10-29T12:00:00.000Z",
  "completed_at": "2026-10-29T12:00:00.000Z",
  "cancel_requested": false,
  "result": {
    "generation_id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
    "asset_id": "6e657fb6-cf58-46d8-9311-7f3828b203c7",
    "audio_url": "https://api.vocloner.org/v1/assets/6e657fb6-cf58-46d8-9311-7f3828b203c7/content",
    "format": "mp3",
    "duration_ms": 3500
  },
  "error": null,
  "usage": {
    "reserved_characters": 46,
    "billed_characters": 46,
    "remaining_characters": 9000
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
POST/jobs/{id}/cancelCancel a job

Cancel queued work immediately. For running work, request cancellation and check the final status and usage.

Required permission
jobs:cancel
Usage
No character charge

Request examples

curl --request POST 'https://api.vocloner.org/v1/jobs/c816ce5b-22f5-4ed2-91a9-90e79b874a24/cancel' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Idempotency-Key: REUSE_THIS_KEY_FOR_RETRIES'

Response

200 · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "operation": "speech",
  "status": "canceled",
  "status_url": "https://api.vocloner.org/v1/jobs/f261e35c-420f-4c82-bd88-a0e370c936ab",
  "created_at": "2026-10-29T12:00:00.000Z",
  "started_at": "2026-10-29T12:00:00.000Z",
  "completed_at": "2026-10-29T12:00:00.000Z",
  "cancel_requested": true,
  "result": null,
  "error": null,
  "usage": {
    "reserved_characters": 46,
    "billed_characters": 0,
    "remaining_characters": 9000
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
GET/generationsList generations

List owned generations from the web, MCP and API using a stable cursor.

Required permission
generations:read
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/generations' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "items": [
    {
      "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
      "kind": "tts",
      "voice_id": "c816ce5b-22f5-4ed2-91a9-90e79b874a24",
      "status": "completed",
      "char_count": 46,
      "duration_ms": 3500,
      "format": "mp3",
      "audio_asset_id": "6e657fb6-cf58-46d8-9311-7f3828b203c7",
      "audio_url": "https://api.vocloner.org/v1/assets/6e657fb6-cf58-46d8-9311-7f3828b203c7/content",
      "created_at": "2026-10-29T12:00:00.000Z",
      "completed_at": "2026-10-29T12:00:00.000Z",
      "error_code": null
    }
  ],
  "next_cursor": null
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
GET/generations/{id}Get a generation

Retrieve metadata and the audio reference of an owned generation.

Required permission
generations:read
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/generations/c816ce5b-22f5-4ed2-91a9-90e79b874a24' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "id": "f261e35c-420f-4c82-bd88-a0e370c936ab",
  "kind": "tts",
  "voice_id": "c816ce5b-22f5-4ed2-91a9-90e79b874a24",
  "status": "completed",
  "char_count": 46,
  "duration_ms": 3500,
  "format": "mp3",
  "audio_asset_id": "6e657fb6-cf58-46d8-9311-7f3828b203c7",
  "audio_url": "https://api.vocloner.org/v1/assets/6e657fb6-cf58-46d8-9311-7f3828b203c7/content",
  "created_at": "2026-10-29T12:00:00.000Z",
  "completed_at": "2026-10-29T12:00:00.000Z",
  "error_code": null
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
DELETE/generations/{id}Delete a generation

Delete an owned generation according to retention rules.

Required permission
generations:delete
Usage
No character charge

Request examples

curl --request DELETE 'https://api.vocloner.org/v1/generations/c816ce5b-22f5-4ed2-91a9-90e79b874a24' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "deleted": true
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
GET/assets/{id}/contentDownload audio

Return authorized audio bytes. Send Bearer on every download; never put the key in the URL.

Required permission
audio:read
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/assets/c816ce5b-22f5-4ed2-91a9-90e79b874a24/content' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 OK · audio/mpeg / audio/wav

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery
GET/capabilitiesGet capabilities

Check formats, operations and limits supported in this environment before integrating.

Required permission
Valid API key
Usage
No character charge

Request examples

curl --request GET 'https://api.vocloner.org/v1/capabilities' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Response

200 · application/json

{
  "api_version": "v1",
  "formats": {
    "speech": [
      "mp3",
      "wav"
    ],
    "dialogue": [
      "mp3"
    ]
  },
  "operations": [
    "speech",
    "dialogue",
    "clone",
    "voice_design",
    "voice_design_select",
    "audio_tool"
  ],
  "audio_tools": {
    "trim": true,
    "volume": true,
    "fade": true,
    "reverse": true,
    "normalize": true,
    "denoise": false,
    "separate": false
  },
  "files": {
    "clone": {
      "max_bytes": 20971520,
      "min_seconds": 5,
      "max_seconds": 270
    },
    "consent": {
      "max_bytes": 5242880
    },
    "audio_tool": {
      "max_bytes": 20971520,
      "max_seconds": 1200
    },
    "local_tool": {
      "max_bytes": 26214400,
      "max_seconds": 900
    }
  },
  "consent": {
    "version": "example-version",
    "recording_required": true
  },
  "jobs": {
    "default_mode": "async",
    "max_wait_seconds": 20
  },
  "idempotency": {
    "retention_days": 30
  }
}

Long operations return a job. Poll status_url until a terminal state. All errors include request_id.

Errors and recovery

Try a generation

Your key stays in memory and is cleared when you leave. Audio downloads require authorization. Never ship production keys in browser code.

The API is disabled in this environment. The reference is public; live requests are not available yet.

Estimated usage: 49 characters. The server confirms final usage and applies your plan limits.

Changelog

v1 · Voices, audio and jobs with shared quotas. Actual availability depends on the environment and is reported by capabilities.