Errors and retries
Public HTTP handler failures use a non-2xx status and a JSON error object. MCP service failures set isError: true and include the same error in structuredContent.error. Input validation failures can instead return text in content without structured content. An authentication or protocol failure may arrive before a tool result.
{
"error": {
"code": "project_busy",
"message": "The creator is still working on this project. Wait for the current run to finish, or stop it first."
}
}Retry one operation without starting twice
For create_video and send_message, reuse the same request_id and unchanged input after a timeout or transient failure. Save the ID before sending the request. Choose a new ID for a new video or edit. Request IDs belong to the person using the key; changing keys does not make the ID new.
400 invalid_request
Check required fields, supported values, file type and size. Correct the request before retrying.
400 cap_too_low
Increase the run's spending cap within the key's limit so the run can be admitted.
401 unauthorized
Send a valid bearer key. Check whether it expired, was revoked, or its owner left the workspace.
402 insufficient_credits
The workspace needs more credits. With an API key, an owner or admin can use the billing_url in details. An assistant connected by signing in gets no billing link.
402 allowance_exhausted
This key or connection has insufficient remaining allowance, including reservations for active runs. Wait for settlement, or use a key or connection with an appropriate allowance.
403 permission_denied
Check the key's scopes, workspace role and project authorship. Signed upload links must also be valid and unexpired.
404 not_found
Check the identifier and workspace. Inaccessible resources are also reported as not found.
409 project_busy
Wait for the project's current run to finish, or stop it before sending another message.
409 character_not_ready
A cast character has no version yet, or can't be cast. Wait for its run to finish (get_run, character.ready), or check list_characters.
409 idempotency_conflict
This request ID was used with different input. Reuse the original input for a retry, or choose a new ID for a new operation.
409 request_in_progress
The request is still being admitted. Retry the same ID and unchanged input after a short delay.
408 upload_too_slow
The upload exceeded its transfer deadline. Try again; partial files are removed. This legacy code does not imply a minimum upload speed.
409 upload_not_ready
Finish the upload before referencing it. If expired or consumed by another request, prepare and upload a new file.
429 rate_limited
Wait for Retry-After seconds before retrying. REST and MCP share credential limits. Upload admission uses the same code with details.reason=upload_capacity; that refusal has not saved the file.
500 internal_error
Retry with the same request ID and unchanged input after a delay.
Failures before a handler runs
During a deployment, a 503 can instead contain code: "GM_DRAINING" and an error string. Network proxies can also return non-JSON responses. Check the HTTP status before relying on a response shape, honor Retry-After when present, and retry creation or edits with the same request ID.
A run can fail after being accepted
A successful creation response only means the run was accepted. Poll the run. A later failure may include error_code: "creator_failed" and a readable error. Open project_url to inspect the saved project and continue. Do not assume a failed run was free.
Rate limits
The default limits are 300 requests per IP per minute and 120 per key per minute, shared across REST and MCP on each server instance. Uploads also have concurrency limits. Honor Retry-After on a 429 response and poll_after_seconds when following a run. Avoid rapid retry loops.