Assets
Upload a track once and reference it by asset_id across every processing
endpoint — BPM, key, stems, mastering, transcription, and more. No redundant uploads,
no bandwidth waste, no duplicate billing.
Storing audio via POST /v1/assets/upload costs zero credits. Credits are only charged when you actually process the asset (same rates as a direct upload).
How it works
Every POST processing endpoint accepts two input modes side-by-side:
| Content-Type | Body | Behaviour |
|---|---|---|
audio/* or application/octet-stream |
Raw audio bytes | Direct upload — works today, unchanged |
application/json |
{"asset_id": "afa_xxx"} |
Reference a previously uploaded asset |
The JSON input mode applies to every endpoint that previously accepted raw bytes:
/v1/bpm, /v1/key, /v1/lufs,
/v1/key-bpm, /v1/beatgrid, /v1/chords,
/v1/master, /v1/pitch,
/v1/separate/2stem, /v1/separate/4stem,
/v1/transcribe, /v1/segment-transcribe,
/v1/analyze/upload, and /v1/identify.
When a processing endpoint is called with an asset_id, its response
includes two extra fields: asset_id (echo of the input) and
asset_expires_at (ISO 8601 timestamp when the stored audio is deleted).
Endpoints
POST /v1/assets/upload
Upload raw audio bytes to receive a reusable asset_id. Supported formats:
MP3, WAV, FLAC, OGG, M4A — anything ffmpeg understands. Maximum upload size is
15 MB on BASIC tier and 50 MB on PRO.
Deduplication is automatic: if you upload the same file twice (same owner, same SHA-256),
the API returns the existing asset_id rather than creating a duplicate.
No extra storage, no extra cost.
Assets auto-expire — no manual deletion is needed. TTL depends on your plan:
| Plan | Asset TTL |
|---|---|
| BASIC (Free / Starter) | 24 hours |
| PRO and above | 7 days |
curl -X POST https://api.brizm.dev/v1/assets/upload \
-H "Authorization: Bearer tl_live_xxx" \
-H "Content-Type: audio/mpeg" \
--data-binary @track.mp3
{
"asset_id": "afa_abc123",
"sha256": "e3b0c44298fc1c149afb4c8996fb924...",
"size_bytes": 8421376,
"expires_at": "2026-05-16T14:30:00Z"
}
| Field | Type | Description |
|---|---|---|
asset_id | string | Opaque identifier, always afa_ prefix. Pass this to any processing endpoint. |
sha256 | string | Hex-encoded SHA-256 of the uploaded bytes. Useful for client-side dedup checks. |
size_bytes | integer | Byte count of the stored audio. |
expires_at | string (ISO 8601) | When the asset will be automatically deleted. |
GET /v1/assets
List all assets owned by the API key. Useful for auditing, building upload UIs, or garbage-collecting client-side state before expiry.
curl https://api.brizm.dev/v1/assets \
-H "Authorization: Bearer tl_live_xxx"
# With pagination
curl "https://api.brizm.dev/v1/assets?limit=10&cursor=afa_prev" \
-H "Authorization: Bearer tl_live_xxx"
{
"items": [
{
"asset_id": "afa_abc123",
"sha256": "e3b0c44298fc1c149afb4c8996fb924...",
"size_bytes": 8421376,
"content_type": "audio/mpeg",
"created_at": "2026-05-15T10:00:00Z",
"expires_at": "2026-05-22T10:00:00Z"
}
],
"next_cursor": null,
"count": 1
}
| Query param | Default | Description |
|---|---|---|
limit | 50 | Items per page (max 200). |
cursor | — | Asset ID to paginate from (exclusive). Use next_cursor from the previous response. |
GET /v1/assets/{id}
Fetch metadata for a single asset. Returns 404 if the asset has expired
or never existed. Does not download the audio bytes — this is metadata only.
curl https://api.brizm.dev/v1/assets/afa_abc123 \
-H "Authorization: Bearer tl_live_xxx"
{
"asset_id": "afa_abc123",
"sha256": "e3b0c44298fc1c149afb4c8996fb924...",
"size_bytes": 8421376,
"content_type": "audio/mpeg",
"created_at": "2026-05-15T10:00:00Z",
"expires_at": "2026-05-22T10:00:00Z"
}
Using an asset in processing calls
Pass Content-Type: application/json and a body of
{"asset_id": "afa_xxx"} to any processing endpoint that
previously accepted raw bytes. Credit cost is identical to a direct upload.
# Use an asset for BPM detection
curl -X POST https://api.brizm.dev/v1/bpm \
-H "Authorization: Bearer tl_live_xxx" \
-H "Content-Type: application/json" \
-d '{"asset_id": "afa_abc123"}'
{
"tempo": 128.03,
"confidence": 0.97,
"asset_id": "afa_abc123",
"asset_expires_at": "2026-05-22T10:00:00Z",
"_meta": {
"cache": "miss",
"latency_ms": 420,
"credits_used": 2,
"credits_remaining": 11998,
"trace_id": "afa-7f3e8a"
}
}
Tenant isolation
Assets are scoped to the API key that uploaded them. You cannot reference another
tenant’s asset. Attempting to use an asset_id that belongs to a
different key returns 404, not 403 — we don’t
confirm or deny ownership across tenants.
Asset upload: free (0 credits). Processing via asset_id: same credit cost as direct upload. Listing/fetching asset metadata: free.
Next steps
- Guide: Upload Once, Process Many — full workflow with Python and cURL examples.
- Credits & Rate Limits — understand what each processing endpoint costs.
- Errors — 404 on expired asset, 413 on size limit, 402 on credits.