Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/bithuman-ai:bithuman-ai-files-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Bithuman Ai Files API
version: '1.0'
contact:
name: bitHuman Support
url: https://www.bithuman.ai/discord
x-logo:
url: https://docs.bithuman.ai/bithuman-mark.png
description: 'Operations tagged Files across 2 of this provider''s published API definitions: openapi.yaml, bithuman-ai-openapi.yaml. Each path carries the servers of the definition it was published in.'
servers:
- url: https://api.bithuman.ai
description: Production
security:
- apiSecret: []
tags:
- name: Files
description: Upload images, videos, audio, and documents.
paths:
/v1/files/upload:
post:
operationId: uploadFile
x-codeSamples:
- lang: shell
label: cURL
source: "curl -X POST https://api.bithuman.ai/v1/files/upload \\\n -H \"api-secret: $BITHUMAN_API_SECRET\" \\\n -H \"content-type: application/json\" \\\n -d '{\"file_url\": \"https://example.com/avatar.jpg\", \"file_type\": \"image\"}'\n"
summary: Upload a file
description: 'Upload images, videos, audio, or documents — by public URL or as
base64. Files are organized by type, and the type is read from the
file''s own bytes: `file_type` and the filename extension are both
cross-checked against them, never trusted over them. Files are stored
privately. The response returns a signed `file_url` (valid 7 days) and
a `file_id` to pass to other endpoints instead of the URL.'
tags:
- Files
requestBody:
required: true
content:
application/json:
schema:
oneOf:
- type: object
title: Upload by URL
required:
- file_url
properties:
file_url:
type: string
description: Public URL to download the file from.
example: https://example.com/avatar.jpg
file_type:
type: string
enum:
- auto
- image
- video
- audio
- document
- pdf
default: auto
description: Optional cross-check, not an override — the stored category always comes from the file's own bytes. Give a value and the bytes must agree with it, or the upload is refused with `415`. `document` and `pdf` are the same category. Any other value is refused with `400 VALIDATION_ERROR`; omit it, or send `auto`, to let the bytes decide. The filename here comes from the URL's path, and its extension must be one of the supported ones.
- type: object
title: Upload by base64
required:
- file_data
- file_name
properties:
file_data:
type: string
description: Base64-encoded file data.
file_name:
type: string
description: Original filename. The extension is required and must be one of the supported ones (see `415`); a name without one is refused.
example: avatar.jpg
file_type:
type: string
enum:
- auto
- image
- video
- audio
- document
- pdf
default: auto
description: Optional cross-check, not an override — the stored category always comes from the file's own bytes. Give a value and the bytes must agree with it, or the upload is refused with `415`. `document` and `pdf` are the same category. Any other value is refused with `400 VALIDATION_ERROR`; omit it, or send `auto`, to let the bytes decide.
responses:
'200':
description: File uploaded
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
example: File uploaded successfully
data:
type: object
properties:
file_id:
type: string
description: Private reference to the uploaded file. Pass it instead of a URL to the endpoints that take an uploaded file; it works only for files your own account uploaded.
example: 3f2b9c14-8a7e-4d21-9f10-2c5b6e0a11dd
file_url:
type: string
description: Signed link to the private file, valid 7 days.
url_expires_in:
type: integer
description: Lifetime of `file_url` in seconds.
example: 604800
original_source:
type: string
description: Original URL or filename.
file_type:
type: string
description: Detected file type category.
file_size:
type: integer
description: File size in bytes.
mime_type:
type: string
description: MIME content type.
asset_category:
type: string
description: Storage category (images, videos, audio, docs).
uploaded_at:
type: string
format: date-time
'400':
description: "One of:\n\n- `DOWNLOAD_FAILED` — `file_url` could not be downloaded:\n unreachable, not publicly readable, or not an ordinary public\n `http(s)` address.\n- `VALIDATION_ERROR` — `file_data` was not valid base64, both\n `file_url` and `file_data` were sent, or `file_type` was a value\n this API does not define. The accepted values are `auto`,\n `image`, `video`, `audio`, `document` and `pdf`; anything else is\n refused rather than quietly treated as `auto`, so a typo cannot\n silently change where your file lands.\n- `MISSING_PARAM` — neither `file_url` nor `file_data` was sent.\n"
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: VALIDATION_ERROR
message: 'Invalid file_type ''picture''; must be one of: auto, image, video, audio, document, pdf'
httpStatus: 400
status: error
status_code: 400
'401':
$ref: '#/components/responses/Unauthorized'
'413':
description: '`FILE_TOO_LARGE` — the file is over the limit for its category:
**10 MB** images, **100 MB** video, **25 MB** audio and documents.
The category is read from the file''s own bytes, so the limit that
applies is the one for what the file actually is.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: FILE_TOO_LARGE
message: file is 31 MB; the limit for image is 10 MB
httpStatus: 413
status: error
status_code: 413
'415':
description: "`UNSUPPORTED_TYPE` — this API will not store the file. Four things\nraise it:\n\n- **The bytes are not a supported type.** Supported: JPEG, PNG,\n GIF, WebP, BMP · MP4, MOV, WebM, AVI, WMV, FLV, Matroska ·\n MP3, WAV, FLAC, AAC, OGG, M4A · PDF, Word, Excel, PowerPoint,\n RTF and plain text.\n- **The bytes contradict `file_type`.** Sending\n `file_type: \"image\"` with a text file is refused here rather than\n stored under the wrong category.\n- **The filename extension is not one of the supported ones.** For\n a base64 upload that is `file_name`; for a URL upload it is the\n last path segment of `file_url`. A name with no extension, or\n one like `.exe` or `.sh`, is refused.\n- **The file would run in a browser.** SVG, HTML and any text\n carrying a script are refused outright: an uploaded file is\n served from a public address, and a file that executes there\n would run as if it came from us.\n"
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: UNSUPPORTED_TYPE
message: file_type was declared 'image' but the uploaded bytes are text/plain
httpStatus: 415
status: error
status_code: 415
'429':
$ref: '#/components/responses/RateLimited'
'500':
description: '`INTERNAL_ERROR` — the file was accepted but could not be stored. Nothing is kept and nothing is charged; retrying is safe.'
servers:
- url: https://api.bithuman.ai
description: Production
components:
responses:
Unauthorized:
description: 'Authentication failed. `UNAUTHORIZED` when the `api-secret` header is
present but invalid; `MISSING_AUTH` when it is absent. The HTTP status
equals `status_code` (401).
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: UNAUTHORIZED
message: Invalid API secret
httpStatus: 401
status: error
status_code: 401
RateLimited:
description: 'Too many requests. The limiter is **per account** — every API secret on
the account draws from one bucket — and **per cost tier**, so a burst of
reads never uses up your generate budget. Your plan sets the number for
each tier; the matrix, the tier each route belongs to and a retry
recipe are on
[Rate limits](https://docs.bithuman.ai/api/rate-limits).
Wait `Retry-After` seconds and retry. The `X-RateLimit-*` headers let a
client slow down *before* it gets here, but header coverage is uneven
across routes — read them defensively and fall back to exponential
backoff when they are absent.
On a route that can also be called without an API secret, an anonymous
call is metered per network address instead: same body, same
`Retry-After`, no `X-RateLimit-*`.
'
headers:
Retry-After:
schema:
type: integer
description: Seconds to wait before retrying.
example: 1
X-RateLimit-Limit:
schema:
type: integer
description: Requests per minute your plan allows on this request's cost tier.
example: 30
X-RateLimit-Remaining:
schema:
type: integer
description: Whole requests left in the bucket right now.
example: 0
X-RateLimit-Reset:
schema:
type: integer
description: Unix time at which the bucket is fully refilled.
example: 1758380460
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: RATE_LIMITED
message: Too many generate requests for this api-secret. Retry in ~1s.
httpStatus: 429
status: error
status_code: 429
schemas:
Error:
type: object
properties:
error:
type: object
properties:
code:
type: string
example: UNAUTHORIZED
message:
type: string
example: Invalid API secret
httpStatus:
type: integer
example: 401
upgrade_url:
type: string
description: 'On `PLAN_REQUIRED`, `AGENT_LIMIT_REACHED` and `CONCURRENCY_LIMIT_REACHED` (403): where to choose a plan. Send the user there instead of retrying. See [Plan and credit refusals](https://docs.bithuman.ai/api/errors#plan-and-credit-refusals).'
example: https://www.bithuman.ai/pricing
topup_url:
type: string
description: 'On `INSUFFICIENT_BALANCE` (402): where to top up credits.'
example: https://www.bithuman.ai/billing#credits
details:
type: object
description: Code-specific fields. `CONCURRENCY_LIMIT_REACHED` sends `tier`, `cap`, `active` and `upgrade_url`.
additionalProperties: true
status:
type: string
example: error
status_code:
type: integer
example: 401
securitySchemes:
apiSecret:
type: apiKey
name: api-secret
in: header
description: 'Your bitHuman API secret. Get one at
[www.bithuman.ai/developer/api-keys](https://www.bithuman.ai/developer/api-keys).
'
bearerApiSecret:
type: http
scheme: bearer
description: 'The same API secret, sent as `Authorization: Bearer <api-secret>`. Self-
hosted runtimes send it this way; the classic `api-secret` header works
on the same routes.
'
x-refined-from:
- openapi.yaml
- bithuman-ai-openapi.yaml
x-tagGroups:
- name: Get started
tags:
- overview
- quickstart
- auth-guide
- models
- pricing
- name: Core concepts
tags:
- avatars-imx
- audio-streaming
- agent-lifecycle
- name: SDKs
tags:
- sdk-python
- sdk-swift
- cli
- name: Guides
tags:
- local-mode
- building-avatars
- name: Deployment
tags:
- deploy-livekit
- deploy-self-hosted
- deploy-embed
- name: API reference
tags:
- Authentication
- Agent Generation
- Agent Management
- Agent Context
- Files
- Dynamics
- Embedding
- Video
- Billing
- Account
- Self-hosting
- API secrets
- Providers
- Runtime sessions
- Knowledge
- Realtime
- Status
- Webhooks
- name: Resources
tags:
- community
- changelog
- support