Errors & Quotas
The error envelope, every error code the API returns, and how the daily free quota behaves.
Error format
Every error is JSON with the same envelope:
{
"error": {
"code": "DAILY_QUOTA_USED",
"message": "Today's free generation has been used. Come back tomorrow to create another video."
}
}code is stable and safe to branch on; message is human-readable and may change.
Error codes
| HTTP | Code | When | What to do |
|---|---|---|---|
400 | INVALID_INPUT | The body fails validation — missing prompt, bad enum value, or a rule like audio-without-pro. | Fix the request; the message names the offending field. |
404 | JOB_NOT_FOUND | The job ID doesn't exist or doesn't belong to your key/browser session. | Check the ID you stored from job creation. |
429 | DAILY_QUOTA_USED | Today's free generation is already used. | Retry after the next UTC midnight, or see pricing for volume. |
502 | CREATE_JOB_FAILED | The render pipeline rejected or failed to accept the task. | Transient — retry with exponential backoff. |
500 | UNKNOWN_ERROR | Something unexpected on our side. | Retry once; if it persists, contact us. |
Failures after a job is accepted don't use this envelope — the job itself moves to status: "failed" with the reason in errorMessage, as described in job lifecycle.
The daily quota
- Every browser guest gets one free generation per UTC day; the counter resets at UTC midnight.
- Approved API keys use the quota assigned to that workspace.
- The quota is consumed when a job is accepted.
- Guests (no account) get the same one-per-day allowance, tracked per browser.
A clean integration pattern:
const res = await fetch(`${BASE}/api/ai-video/jobs`, { method: 'POST', headers, body });
if (res.status === 429) {
const { error } = await res.json();
if (error.code === 'DAILY_QUOTA_USED') {
// schedule the render for after UTC midnight instead of hard-failing
}
}Need more than the free tier? Contact us and we'll help set up the right volume.