Overview
Patterns that keep an integration reliable: how to store keys, handle errors, avoid duplicate videos, receive results and keep an eye on costs.Authentication and security
Store API keys securely
Use different keys per environment
Rotate keys
Create the new key in Settings → Developer API, deploy it, confirm traffic works, then delete the old key. Deleted keys answer401 right away.
Error handling
Branch on status and code
400: fix the request; themessagenames the field.401: check the key.402: billing.subscription_required,INSUFFICIENT_CREDITSormissing_credentials(withmissingProviders).403: the team lacks the product, or the request uses another team’s files.404: not found, or not yours.429: your team is over its rate limit. WaitRetry-Afterseconds; nothing ran, so any request can be sent again.5xx: our side.
Retry GETs, not creates
Reading (GET /v1/project/{id}, lists) is safe to retry with backoff:
Avoiding duplicate videos
Send anIdempotency-Key (your job id works) with every create, and guard them on your side too:
- Give each job your own id and save it before calling the API.
- Send it in
metadata({ "jobId": "job_123" }), so every webhook tells you which job it belongs to. - Save the returned
projectIdwith the job immediately. - If the call failed without an answer, mark the job “unknown” and check your dashboard or
GET /v1/video/listbefore re-sending.
Performance
Cache resources
Avatars, voices and music change rarely. Cache the lists for a few hours instead of fetching them before every video.Batch operations
Each create starts real work and may charge credits. Keep a few requests in flight at a time rather than firing a whole list at once, and stop the batch on401 or 402. See Bulk Generation.
Minimize API calls
- Use webhooks so you do not need to poll at all, or poll every 10 to 15 seconds rather than every second.
- Poll the project you care about (
GET /v1/project/{projectId}), not the whole video list.
Webhook implementation
Webhooks plus a polling fallback
Webhooks are the cheapest way to hear about finished videos, but each one is tried only 3 times in a row and then dropped. Keep a periodic job that polls projects you have not heard about for a while.Protect your endpoint
Every webhook call is signed. Verify theHooked-Signature header against your signing secret (Settings → Webhooks) and reject anything that does not match or is older than five minutes. See Verify the signature for Node and Python code.
A secret token in the webhook URL (?token=...) still works as an extra check, but it is optional.
For sensitive actions, confirm the result with GET /v1/project/{projectId} before acting on it.
Handle duplicates
A late answer from your endpoint leads to a retry with the same payload. Make processing idempotent, keyed onvideoId (or projectId when videoId is null):
Return 2xx immediately
You have 10 seconds. Acknowledge first, then download the video or update records in the background:Costs
- On a managed team, generation is charged in credits. A
402 INSUFFICIENT_CREDITStells youcreditsNeededandcreditsAvailable. Credits for failed projects are refunded automatically. GET /v1/project/{projectId}returnsusedCreditsfor each project, so you can track spend per job (it goes back to0when a failed project is refunded).- On a byok team, generation is billed by your own providers; set up every key your formats need to avoid
402 missing_credentials. - Re-rendering with
POST /v1/renderis free.
Logging and monitoring
Structured logging
Log the ids you need to trace a video end to end:Track key metrics
- Projects created, completed and failed per day.
- Time from create to
COMPLETED. 402responses (credits or keys running out).- Webhooks that never arrived (caught by the polling fallback).
Data validation
Validate before sending
Catch obvious problems before they cost a request:Testing
Unit test your client
Mockfetch and check how your code handles each answer:
Integration testing
Run real requests against a development key on a few short scripts. Keep these tests out of every CI run: each one creates a real project.Code organization
Wrap the API in one small module so the base URL, headers, error handling and retries live in one place:Deployment
Environment configuration
Health checks
GET /v1/health needs no API key and reports whether the API is up:
status: ok, or 503 with status: error when the database does not answer, plus a timestamp and the database check (services.database). To check that your key still works, call a cheap authenticated endpoint such as GET /v1/avatar/list?limit=1.
Production checklist
1
Security
API key in a secret store, server-side only; webhook URL protected by a token.
2
Reliability
GETs retried with backoff; creates never retried blindly;
projectId stored right after each create.3
Results
Webhook endpoint answers 2xx within 10 seconds and deduplicates; polling fallback for missing webhooks; videos copied to your own storage.
4
Billing
Enough credits (managed) or every provider key the formats need (byok);
402 alerts in place.5
Monitoring
Logs with
projectId / videoId; failure rate and time to completion tracked.