Docs index: /llms.txt · every page as Markdown: add .md

‹ API reference

Errors

The error format, HTTP status codes and every error code, with fixes.

Error response format

Every error follows the same structured envelope:

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description of what went wrong.",
    "httpStatus": 401
  },
  "status": "error",
  "status_code": 401
}

The HTTP status always matches status_code and error.httpStatus; there is no “200 on error”. Branch on either the status or error.code.

Successful responses do not share one envelope: some wrap the result as {"success": true, "data": …} (agents, credits, video), some as {"status": "success", "status_code": 200, "data": …} (/v1/me, embed tokens), and some return a bare object (/v1/validate, /speak). Each endpoint’s page shows its response.

502 and 504 may not be JSON

A 502 or 504 comes either from the API (the envelope above, code UPSTREAM_UNAVAILABLE or UPSTREAM_TIMEOUT) or from the delivery network in front of it (an HTML page). Check Content-Type before parsing any error, and fall back to the HTTP status line when it is not application/json. Both are transient: retry after Retry-After seconds when present, otherwise back off.

HTTP status codes

StatusMeaningCodes
302Redirect, not an errorModel download redirects to the artifact URL.
400Bad RequestMISSING_PARAM, VALIDATION_ERROR, MODEL_NOT_DOWNLOADABLE, MODEL_NOT_OFFERED
401UnauthorizedUNAUTHORIZED, MISSING_AUTH
402Payment RequiredINSUFFICIENT_BALANCE, PAYWALL
403ForbiddenPlan limits, FORBIDDEN, RUNTIME_SUSPENDED, SESSION_DURATION_LIMIT, SECRET_REVEAL_CONSOLE_ONLY
404Not FoundNOT_FOUND, MODEL_ARTIFACT_NOT_READY, VOICE_NOT_FOUND
409Conflict: agent not ready for it, or a build already runningMODEL_NOT_GENERATED, AGENT_NOT_READY, BUILD_IN_PROGRESS, BUILD_CONCURRENCY, BUILD_DAILY_CAP
410GoneAGENT_DELETED, AGENT_PURGED, ENDPOINT_RETIRED
413 / 415File too large / unsupported typeFILE_TOO_LARGE, UNSUPPORTED_TYPE
422Input doesn’t fit the modelMODEL_SUBJECT_MISMATCH, MODEL_PREREQUISITE_MISSING, IMAGE_FACE_UNSUITABLE, KB_EMPTY
429Rate LimitedRATE_LIMITED (rate limits)
500Internal ErrorINTERNAL_ERROR, UPSTREAM_ERROR. Retry, or contact support.
502 / 504Bad Gateway / Gateway TimeoutTransient; may be HTML (above). Retry after Retry-After.
503Service UnavailableSERVICE_UNAVAILABLE, MODEL_NOT_YET_AVAILABLE. Retry after Retry-After, with backoff.

Error codes

Authentication

CodeHTTPResolution
UNAUTHORIZED401The api-secret header is present but invalid. Get a valid secret from Developer → API Secrets.
MISSING_AUTH401The api-secret header is absent. Add it to your request. REST endpoints do not read Authorization: Bearer; send the secret as api-secret: <secret>.
SECRET_REVEAL_CONSOLE_ONLY403An API secret tried to read a stored secret’s value. Reveal it in the Console, or create a new secret.
FORBIDDEN403A /v2/{user_id}/… path names another account’s user_id. Read your own from GET /v1/me.

Plan and credit refusals

A plan or credit refusal names its fix in a link field of error: send the user there rather than retrying.

CodeHTTPResolution
PLAN_REQUIRED403Your plan does not include this; the message says what, and upgrade_url links the fix. From 2026-10-19 00:00 UTC, a Free account’s API secret is refused, and Free accounts cannot create agents or buy top-ups. A model outside your plan: the message names the plan; contact sales.
AGENT_LIMIT_REACHED403A new agent would pass your plan’s agent limit (Creator 7, Pro 40, Business 200, Enterprise 1,000): “Your {Plan} plan includes {N} agents and you have {M}. Existing agents keep working; delete one or upgrade at https://www.bithuman.ai/pricing to create more.” Link: upgrade_url. At the Enterprise cap there is no higher plan: “…delete one or contact support@bithuman.ai to raise the limit.”, with no upgrade_url.
CONCURRENCY_LIMIT_REACHED403A new session would pass your plan’s concurrent cloud sessions; the message names the limit and how many are running. End a session or upgrade; live sessions are never cut off. An ended session frees its slot at once; to end one, terminate it. Link: upgrade_url, also in details.
INSUFFICIENT_BALANCE402Not enough credits for this action. Top up (Creator plan or higher; on Free, choose a plan), then retry. Link: topup_url.
PAYWALL402The account has no minutes left for a voice session: its plan’s credits and its top-ups are spent. bitHuman returns it for bitHuman Live sign-ins; an API secret that runs out of credits gets INSUFFICIENT_BALANCE instead. A retry does not help: choose a plan or top up, then start a new session.
ACCOUNT_SUSPENDED403Your balance is too far below zero. Top up; contact support if it persists. No link.
RUNTIME_SUSPENDED403A token endpoint refused the secret: it was revoked (create a new one), or runtime access is suspended (contact support). A plan change does not clear it. No link.

Until 2026-10-19, a Free account’s runtime-token and meter responses carry a plan_notice field and an X-Bithuman-Plan-Notice header: “Free-plan API and SDK access ends on 2026-10-19. Upgrade at https://www.bithuman.ai/pricing to keep it.” A Free account with top-up credits bought before 2026-09-27 keeps access until those credits are spent, and its notice says so. Show plan_notice as sent. Choose a plan · top up.

Agent operations

CodeHTTPResolution
NOT_FOUND404Returned both when no agent matches the code and when an agent has no active session for /speak / /add-context. Distinguish by the message string: "Agent not found for code: <code>" vs "No active rooms found for agent <code>".
VALIDATION_ERROR400Body failed schema validation. Include all required fields.
VIDEO_INPUT_NOT_SUPPORTED400Agent creation with a video input. Creation is image-only for every model — provide a portrait image; bitHuman generates the 10-second identity video internally so it loops without a seam (first frame == last frame). Nothing is charged; never send video.
MISSING_PARAM400A required parameter was not provided, or an agent update has nothing to change.
IMAGE_FACE_UNSUITABLE422Essence 2 creation or add, for a real person: the face is too small in frame, or one of several similar faces. Upload a closer waist-up or head-and-shoulders photo of one person. Nothing is charged. A photo with no face at all is MODEL_SUBJECT_MISMATCH.
MODEL_DEFAULT_DEPRECATED200 (warning)Agent creation without model: the agent is created as expression-1 and the response carries this warning. From 2026-12-26 model is required. Send model explicitly.
AGENT_DELETED / AGENT_PURGED410The agent was deleted; model download, gestures and talking video refuse it. Create a new agent.

Model errors

Agent creation, adding a model, model download, embed tokens and talking video share these codes:

CodeHTTPResolution
MODEL_NOT_GENERATED409The agent does not have that model yet. The message gives the fix: the exact add-a-model call and its cost (adding expression-1 is free and immediate), or the missing input when the agent cannot get it. Nothing is charged.
AGENT_NOT_READY409POST /v1/agent/{code}/models on an agent that is still generating or failed. Wait for the current generation to finish, or fix/re-create a failed agent first.
MODEL_SUBJECT_MISMATCH422Every model except Expression 2 needs a clear, real human face. A creation or model add for essence-2, essence-1 or expression-1 (also when model is omitted) is refused when the photo or prompt is a cartoon, a stylized character, an animal, a robot or a creature, or when no face can be found in the photo — e.g. "Expression 1 needs a clear, real human face, and this image looks like an animal. Use Expression 2, which animates any character: cartoons, animals, robots and stylized art. Nothing was charged." Nothing is billed and no agent is created. Use expression-2, or model: "auto" to route automatically. See Choosing a model.
MODEL_PREREQUISITE_MISSING422Adding that model needs an input this agent lacks: for essence-2, the video an Essence creation makes; for expression-2, a face image; for expression-1, an image and a voice; for essence-1, an image or that video. Add the missing image or voice, then retry.
MODEL_NOT_DOWNLOADABLE400Model download for a model with no file: expression-1 renders in the bitHuman cloud from the agent’s image.
MODEL_NOT_OFFERED400The request names a model that is not currently offered to any account; the message names it. Nothing is launched or charged, and no other model is used in its place. Pick one of the models.
MODEL_NOT_YET_AVAILABLE503A model is paused for your account (not returned in normal operation). Nothing is charged; retry later or use another model.
MODEL_ARTIFACT_NOT_READY404Model download before the file is published (shortly after the agent is ready). Retry; the message says when.

File operations

CodeHTTPResolution
FILE_TOO_LARGE413Images 10 MB, video 100 MB, audio and documents 25 MB.
UNSUPPORTED_TYPE415The bytes are not a supported type, they contradict file_type, the filename extension is not one File upload lists, or the file would run in a browser (SVG, HTML, scripted text).
DOWNLOAD_FAILED400Ensure the URL is publicly accessible and returns a valid file.

Session & infrastructure

CodeHTTPResolution
RATE_LIMITED429Back off and retry. See rate limits.
SESSION_DURATION_LIMIT403One session ran past the maximum continuous length. Start a new session; your account is fine.
SERVICE_UNAVAILABLE503A dependency is briefly unavailable or at capacity. Nothing was changed. Retry after Retry-After seconds, with backoff.
UPSTREAM_UNAVAILABLE / UPSTREAM_TIMEOUT502 / 504Transient. Retry with backoff.
INTERNAL_ERROR500Retry once. If persistent, report via Discord.
UPSTREAM_ERROR500A backing query failed or timed out (seen on runtime sessions). Nothing was changed. Retry with backoff.
ENDPOINT_RETIRED410The endpoint was removed; the message names its replacement. POST /v1/realtime/ephemeral-token answers it: connect through the Realtime relay.
MODEL_LOCKED—A Realtime relay error event: a session.update tried to change the model fixed at connect. Reconnect with the new model.

Knowledge bases

CodeHTTPResolution
KB_EMPTY422A build of a knowledge base with no source files. Upload files, then build.
BUILD_IN_PROGRESS409A build is already running on this knowledge base; the request is queued as a rebuild when it finishes.
BUILD_CONCURRENCY409Another build is running for the account. Retry when it finishes.
BUILD_DAILY_CAP409The account reached 20 builds today. Retry tomorrow.

The CLI’s exit codes, such as PUBLIC_BIND_REFUSED, are on CLI troubleshooting. The Flutter plugin’s codes, such as MODEL_REJECTED, are on Flutter errors, and the Android SDK’s refusals on Android troubleshooting.

Handling errors in Python

The Python examples use requests (pip install requests). This call is free: it asks for the status of an agent that does not exist.

import os, requests

resp = requests.get(
    "https://api.bithuman.ai/v1/agent/status/A00XXX0000",
    headers={"api-secret": os.environ["BITHUMAN_API_SECRET"]},
    timeout=30,
)
if resp.ok:
    print(resp.json()["data"]["status"])
elif resp.headers.get("content-type", "").startswith("application/json") and "error" in resp.json():
    err = resp.json()["error"]
    print(resp.status_code, err["code"], err["message"])  # 404 NOT_FOUND here
else:
    print(resp.status_code, "retry after", resp.headers.get("Retry-After"))

Retry 429 and 5xx with exponential backoff and jitter (rate limits). For a plan or credit refusal, follow its link field; fix the request for any other 4xx. Is the API down? Check status.bithuman.ai.

API readiness

GET /readyz getReadiness

Whether the API is refusing work right now. No credential required. It always answers HTTP 200: read the status field (ok, degraded or unhealthy). For the overall service status, use status.bithuman.ai.

curl

curl https://api.bithuman.ai/readyz
# → {"status":"ok","families":{"sessions":{"status":"ok"}, ...}}

Python

import requests

resp = requests.get("https://api.bithuman.ai/readyz")
print(resp.json())

Node

const resp = await fetch("https://api.bithuman.ai/readyz");
console.log(await resp.json());
{
  "status": "ok",
  "window_seconds": 900,
  "replica_scope": "this process only — not a fleet view"
}

This section moved: docs.bithuman.ai/api/errors#error-codes