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.

Asset upload is free.
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:

PlanAsset TTL
BASIC (Free / Starter)24 hours
PRO and above7 days
cURL
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
201 Created
{
  "asset_id":   "afa_abc123",
  "sha256":     "e3b0c44298fc1c149afb4c8996fb924...",
  "size_bytes": 8421376,
  "expires_at": "2026-05-16T14:30:00Z"
}
FieldTypeDescription
asset_idstringOpaque identifier, always afa_ prefix. Pass this to any processing endpoint.
sha256stringHex-encoded SHA-256 of the uploaded bytes. Useful for client-side dedup checks.
size_bytesintegerByte count of the stored audio.
expires_atstring (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
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"
200 OK
{
  "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 paramDefaultDescription
limit50Items per page (max 200).
cursorAsset 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
curl https://api.brizm.dev/v1/assets/afa_abc123 \
  -H "Authorization: Bearer tl_live_xxx"
200 OK
{
  "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.

cURL
# 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"}'
200 OK — note asset_id + asset_expires_at in response
{
  "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.

i
Billing summary.
Asset upload: free (0 credits). Processing via asset_id: same credit cost as direct upload. Listing/fetching asset metadata: free.

Next steps