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

‹ API reference

Billing & usage

Read a live credit balance and per-mode minute estimates.

The credits model

bitHuman bills in credits: time in a live session, talking or idle, bills by the exact second at a per-minute rate, and creating an agent or rendering a talking video is a one-time charge. Every rate is on Pricing & credits. These endpoints read your balance, your usage and the rate schedule.

Account status

GET /v1/me getMe

Returns your identity, plan and balance in one call: a good pre-flight check, and where to find your user_id.

credit_balance is plan plus top-up credits. Use user_id in the /v2/{user_id}/… account endpoints (API secrets, Runtime sessions, Providers).

curl

curl https://api.bithuman.ai/v1/me -H "api-secret: $BITHUMAN_API_SECRET"

Python

import os, requests

resp = requests.get(
    "https://api.bithuman.ai/v1/me",
    headers={"api-secret": os.environ["BITHUMAN_API_SECRET"]},
)
print(resp.json())

Node

const resp = await fetch("https://api.bithuman.ai/v1/me", {
  headers: { "api-secret": process.env.BITHUMAN_API_SECRET },
});
console.log(await resp.json());
{
  "data": {
    "user_id": "3f9a…-uuid",
    "email": "user@example.com",
    "plan": "pro",
    "plan_code": "membership_pro",
    "credit_balance": 1240,
    "plan_credits_remaining": 1000,
    "topup_credits_remaining": 240,
    "account_status": "active"
  },
  "status": "success",
  "status_code": 200
}

Get the pricing schedule

GET /v1/pricing getPricing

Returns the credit schedule, so you can estimate a cost before a billable call. Creation is priced per model in agent_generation.by_model; live sessions per model in realtime, for the cloud (hosted) and for self-hosted and on-device (self_hosted), each with its rounding rule (seconds_floor_carry: billed per exact second, rounded down per session, the remainder carried to your next session). Pricing & credits is generated from this response. The call needs the api-secret header; without one it returns 401 MISSING_AUTH.

by_model keys are the model values POST /v1/agent/generate accepts. auto is charged at the rate of the model it routes to (500 or 2000); the auto entry shows the higher one. Adding a model to an existing agent costs the same (adding expression-1 is free). The server enforces the actual charge; treat this schedule as an estimate.

curl

curl https://api.bithuman.ai/v1/pricing \
  -H "api-secret: $BITHUMAN_API_SECRET"

Python

import os, requests

resp = requests.get(
    "https://api.bithuman.ai/v1/pricing",
    headers={"api-secret": os.environ["BITHUMAN_API_SECRET"]},
)
print(resp.json())

Node

const resp = await fetch("https://api.bithuman.ai/v1/pricing", {
  headers: { "api-secret": process.env.BITHUMAN_API_SECRET },
});
console.log(await resp.json());
{
  "success": true,
  "data": {
    "unit": "credits",
    "agent_generation": {
      "unit": "credits",
      "by_model": {
        "essence-1": 250,
        "expression-1": 250,
        "expression-2": 2000,
        "essence-2": 500,
        "auto": 2000
      },
      "note": "One-time charge per agent created via POST /v1/agent/generate, PER MODEL …"
    },
    "talking_video": {
      "unit": "credits_per_minute",
      "billing": "ceil(minutes) * rate, minimum 1 minute",
      "rates": { "essence-1": 2, "expression-1": 4, "essence-2": 4, "expression-2": 4 }
    },
    "dynamics_generation": { "flat": 250, "note": "…" },
    "realtime": {
      "unit": "credits_per_minute",
      "hosted": {
        "by_model": { "essence-2": { "rate": 4, "rounding": "seconds_floor_carry", "basis": "…" }, "…": {} },
        "chat_line": { "rate": 10, "rounding": "seconds_floor_carry", "basis": "…" }
      },
      "self_hosted": { "by_model": { "essence-2": { "rate": 2, "rounding": "seconds_floor_carry", "basis": "…" }, "…": {} } }
    },
    "notes": "Authoritative charges are enforced server-side at request time. …"
  }
}

Check credit balance

GET /v2/credit-summaries getCreditSummaries

Returns the live balance of the account that owns the api-secret, split into plan and top-up credits, with an estimate of the minutes each session type can afford. It is safe to call often. It only ever returns your own balance; a user_id parameter is ignored.

Response fields

FieldTypeNotes
balancenumberplan + top-up + reward credits; can dip slightly below 0 before the account is suspended
plan_creditsnumberRemaining credits from the active subscription; resets at billing-period end.
topup_creditsnumberCredits from one-time top-ups; do not reset.
is_enterprisebooleantrue for org-pooled (enterprise) billing.
minutes_estimateobjectFloor-division of balance by each mode’s credits/min rate.

There is one minutes_estimate key per serving mode. The rate differs by model — read the key for the model you actually run:

KeyMeaningRate
essence_2_cloudEssence 2 on bitHuman cloudbalance ÷ 4
essence_2_self_hostedEssence 2 on your hardwarebalance ÷ 2
expression_2_cloudExpression 2 on bitHuman cloudbalance ÷ 4
expression_2_self_hostedExpression 2 on your hardwarebalance ÷ 2
essence_1_cloudEssence 1 on bitHuman cloudbalance ÷ 2
essence_1_self_hostedEssence 1 on your hardwarebalance ÷ 1
expression_1_cloudExpression 1 on bitHuman cloudbalance ÷ 4
voice_chatManaged voice chat (all-inclusive)balance ÷ 10
camera_chatManaged cloud agent, camera onbalance ÷ 30

essence_cloud, essence_self_hosted and expression_cloud are older aliases of the essence_1_* and expression_1_* keys, not Essence 2 or Expression 2. Ignore expression_1_self_hosted and expression_self_hosted: Expression 1 has no self-hosted mode. The estimates are advisory; the server computes the actual charge.

curl

# Your own balance — just your API secret:
curl https://api.bithuman.ai/v2/credit-summaries \
  -H "api-secret: $BITHUMAN_API_SECRET"

Python

import os, requests

resp = requests.get(
    "https://api.bithuman.ai/v2/credit-summaries",
    headers={"api-secret": os.environ["BITHUMAN_API_SECRET"]},
)
print(resp.json())

Node

const resp = await fetch("https://api.bithuman.ai/v2/credit-summaries", {
  headers: { "api-secret": process.env.BITHUMAN_API_SECRET },
});
console.log(await resp.json());
{
  "success": true,
  "data": {
    "user_id": "00000000-0000-0000-0000-000000000000",
    "balance": 1200.0,
    "plan_credits": 200.0,
    "topup_credits": 1000.0,
    "is_enterprise": false,
    "minutes_estimate": {
      "essence_2_cloud": 300,
      "essence_2_self_hosted": 600,
      "expression_2_cloud": 300,
      "expression_2_self_hosted": 600,
      "essence_1_cloud": 600,
      "essence_1_self_hosted": 1200,
      "expression_1_cloud": 300,
      "voice_chat": 120,
      "camera_chat": 40,
      "essence_cloud": 600,
      "essence_self_hosted": 1200,
      "expression_cloud": 300
    }
  }
}

Usage history

GET /v1/usage getUsage

Returns your account’s metered events, newest first. Paginate with limit (default 50, max 200) and offset; narrow with start / end (ISO-8601 timestamps) and agent_code.

The events are in data; pagination carries limit, offset, total and has_more.

Each row carries source (how the charge happened: chat, cloud, self_hosted, browser, offline_render, offline_pack, realtime_voice, video_api, creation, generation, refund, credit or other), activity_type, pricing_code, pricing_code_meaning, agent_code, credits_change, start_time, end_time and created_at.

credits_change is positive for charges and for grants alike: plan grants (membership_…) and top-ups add credits, and credit_refund_… rows return them. pricing_code_meaning decodes usage codes and is null for grants: read it (or source) rather than parsing pricing_code, whose spellings never change. activity_type is deprecated: it leaves the response on 2026-12-26; read source instead.

A talking-video render charges its maximum up front and refunds the difference, so every render, successful or not, writes a charge row and a credit_refund_… row. Only a refund equal to the whole charge means the render failed.

curl

curl "https://api.bithuman.ai/v1/usage?limit=50&start=2026-06-01T00:00:00Z" -H "api-secret: $BITHUMAN_API_SECRET"

Python

import os, requests

resp = requests.get(
    "https://api.bithuman.ai/v1/usage?limit=50&start=2026-06-01T00:00:00Z",
    headers={"api-secret": os.environ["BITHUMAN_API_SECRET"]},
)
print(resp.json())

Node

const resp = await fetch("https://api.bithuman.ai/v1/usage?limit=50&start=2026-06-01T00:00:00Z", {
  headers: { "api-secret": process.env.BITHUMAN_API_SECRET },
});
console.log(await resp.json());

Notes

  • Quote balance to users. The usage history is an audit trail and can differ from the balance by rounding.
  • A balance slightly below 0 is allowed before suspension; the minute estimates count it as zero.

Errors

HTTPCodeWhen
401UNAUTHORIZED / MISSING_AUTHMissing or invalid api-secret.
402INSUFFICIENT_BALANCEBalance too low for the requested operation.
429RATE_LIMITEDToo many requests; honour Retry-After.
500INTERNAL_ERRORServer error; retry with backoff.
503SERVICE_UNAVAILABLETransient; retry after Retry-After.

See Rate limits for the plan-tiered request limits and the full error reference.

Next steps