New: AI video tools. Cut, clip, caption and dub your videos. See all video tools →

Cloud API

Hosted at api.vcp.name. Needs an API key from a Starter or Premium plan and uses the plan's monthly tokens.

OpenAPI spec · Base URL https://api.vcp.name

Generate speech, clone and design voices, change voices, transcribe audio, and make avatar videos, dubs and cuts.

Quickstart

Create a key in Settings > API at app.voicecreator.pro. The API needs a Starter or Premium plan.

curl -X POST https://api.vcp.name/v1/speech \
  -H "Authorization: Bearer $VCP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello from the API.", "voice": "af_alloy"}'

curl "https://api.vcp.name/v1/jobs/JOB_ID?wait=60" \
  -H "Authorization: Bearer $VCP_API_KEY"

When the job succeeds, result.audio_url links to the WAV. GET /v1/voices lists voice ids.

Authentication

Send your key as a bearer token: Authorization: Bearer vcp_live_.... Keep it secret.

Jobs

Endpoints that generate media return 202 with a job. GET /v1/jobs/{id}?wait=60 returns when the job finishes, or after at most 60 seconds. Call it again while the status is queued or running, or use webhooks. Results are kept for 24 hours.

Files

Send audio as audio_file_id or audio_url, photos as photo_file_id or photo_url, and videos as video_file_id. To upload, call POST /v1/uploads, PUT the file to upload_url with the same Content-Type within 2 hours, then pass file_id. Uploads are kept for 24 hours.

TypeFormatsUploadLink
AudioWAV, FLAC, Ogg/Opus, MP3200 MB25 MB
PhotoJPEG, PNG, WEBP20 MB20 MB
VideoMP4, MOV, MKV, WEBM2 GBNot supported

Avatar audio can be up to 20 seconds.

Errors

Errors return an HTTP status and a body with a code, a message and, when one field is at fault, a param.

{ "error": { "code": "invalid_request", "message": "text is required.", "param": "text" } }

Retry 429, 500 and 503 with exponential backoff, waiting at least Retry-After when it is set. Send an Idempotency-Key so a retried POST cannot start a second job. Other errors fail again until the request changes.

Every response has a Request-Id header. Include it when you contact support.

StatusCodeMeaning
400invalid_requestA parameter is missing or invalid. param names it.
400invalid_jsonThe body is not JSON.
400model_not_supportedThe model cannot do this.
400url_fetch_failedThe audio or photo link could not be downloaded.
401unauthorizedThe API key is missing, invalid or revoked.
402out_of_tokensThe account is out of tokens for this period.
403paid_plan_requiredThe API needs a Starter or Premium plan.
403preset_read_onlyPreset voices cannot be renamed or deleted.
404not_foundNo such resource.
404voice_not_foundNo such voice.
404file_not_foundNo such upload. Uploads expire after 24 hours.
404speech_job_not_foundNo such speech job, or its audio expired.
405method_not_allowedThe path does not support this method.
409idempotency_conflictThe Idempotency-Key was used with a different body.
409job_not_readyThe job has not succeeded yet.
409design_expiredThe voice design is older than 24 hours.
409voice_unavailableThe voice has no reference audio.
409voice_save_failedThe voice could not be saved.
413too_largeThe file or text is too large.
413storage_fullThe account storage is full.
422photo_refusedThe photo cannot be used.
429rate_limitedToo many requests for this key.
429concurrency_limitToo many jobs in progress.
500internal_errorSomething went wrong on our side.
503unavailableTemporarily unavailable.

A failed job has status failed and an error with one of these codes:

CodeMeaning
out_of_tokensThe account ran out of tokens.
no_speechNo speech was found, or none was produced.
no_faceNo face was found in the photo.
many_facesThe photo shows more than one face.
too_longThe video is longer than 30 minutes for a dub or 3 hours for a cut.
unsupported_languageThe model cannot speak the target language.
bad_videoThe video has no audio track or cannot be read.
generation_failedThe job failed. Try again.

Idempotency

POST requests that start a job accept an Idempotency-Key header. Retrying with the same key and body returns the original job. The same key with a different body returns 409 idempotency_conflict. Keys are kept for 90 days.

Rate limits

LimitStarterPremium
Requests per minute, per key6060
Jobs in progress310

Over a limit, requests get 429 with a Retry-After header. Responses to a valid key have a RateLimit-Policy header.

Webhooks

Add up to 5 https endpoints in Settings > API. When a job made with an API key finishes, every enabled endpoint gets a POST with job.succeeded, job.failed or job.cancelled. data is the job.

Requests are signed with HMAC-SHA256 in the webhook-id, webhook-timestamp and webhook-signature headers of Standard Webhooks. Verify them with your whsec_ secret and the raw request body:

import { Webhook } from 'standardwebhooks'

const event = new Webhook(process.env.VCP_WEBHOOK_SECRET).verify(rawBody, headers)
import os
from standardwebhooks.webhooks import Webhook

event = Webhook(os.environ["VCP_WEBHOOK_SECRET"]).verify(raw_body, headers)

verify fails when the signature is wrong or the timestamp is more than 5 minutes off.

Respond with a 2xx within 10 seconds. Redirects are not followed. Failed deliveries are retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 8 hours and 12 hours, up to 7 attempts over about 23 hours. An endpoint that fails for 3 days is turned off. Use webhook-id to skip duplicates. Events can arrive out of order.

Usage

Jobs use tokens from your plan. tokens_charged on the job shows the cost. API requests stay out of History. List them in Settings > API or with GET /v1/requests.

Endpoints

Speech

Voices

Transcriptions

Voice changer

Avatar videos

Dubs

Cuts

Jobs

Uploads

Account

Webhooks