{
  "openapi": "3.1.0",
  "info": {
    "title": "Brizm Audio Intelligence API",
    "version": "v1",
    "description": "Brizm Audio API \u2014 25+ audio endpoints behind one integration.\n\nStems, analysis, transcription, mastering. Built for media SaaS and\ncreator-tool teams who'd rather ship product than wire up five audio vendors.\n\nOpen models, production-hardened: HTDemucs FT for 4-stem, BS-RoFormer for\nvocals, madmom for beat grids, MAEST for mood features.\n\n## Billing (V2)\n\nPricing is usage-based with a dual-counter model:\n\n- **Monthly compute credits** refresh at the start of each UTC billing period.\n  Different operations consume different amounts (1cr for ID lookups, 2cr for\n  cache misses, 3-10cr for compute endpoints).\n- **Cache lookups** are rate-limited separately with a per-tier monthly\n  allowance (e.g. Pro tier: 300K lookups/month). Cache hits do not consume\n  compute credits.\n- **Free tier** is restricted to cheap operations only (lookups + CPU\n  endpoints). GPU compute requires a paid tier.\n- **Prepaid packs** cover overage. Auto-topup can be enabled with a monthly $\n  cap. Packs never expire and carry across billing periods.\n- **Grace buffer** (tier-specific: Starter -500cr, Pro -2000cr, Scale\n  -10000cr) allows a temporary negative balance for up to 24 hours.\n- **Failed compute (5xx)** is automatically refunded. See the pricing page at\n  https://developers.brizm.dev/pricing for full tier details.\n",
    "contact": {
      "name": "Brizm",
      "url": "https://developers.brizm.dev",
      "email": "hello@brizm.dev"
    }
  },
  "servers": [
    {
      "url": "https://api.brizm.dev",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key (tl_live_* or tl_test_*)"
      }
    },
    "schemas": {
      "MetaEnvelope": {
        "type": "object",
        "properties": {
          "cache": {
            "type": "string",
            "enum": [
              "hit",
              "miss",
              "bypass"
            ],
            "description": "Whether the response came from cache"
          },
          "latency_ms": {
            "type": "integer",
            "description": "Processing time in milliseconds"
          },
          "credits_used": {
            "type": "integer"
          },
          "credits_remaining": {
            "type": "integer"
          },
          "trace_id": {
            "type": "string"
          }
        }
      },
      "Features": {
        "type": "object",
        "properties": {
          "artist": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "tempo": {
            "type": "number",
            "format": "float",
            "description": "BPM, float precision (e.g. 116.01)"
          },
          "key": {
            "type": "string",
            "description": "Musical key (C, C#, D, ..., B)"
          },
          "mode": {
            "type": "string",
            "enum": [
              "major",
              "minor"
            ]
          },
          "camelot": {
            "type": "string",
            "description": "Camelot wheel notation (e.g. \"10A\")"
          },
          "energy": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "danceability": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "happiness": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "acousticness": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "instrumentalness": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "_meta": {
            "$ref": "#/components/schemas/MetaEnvelope"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable error code"
          },
          "message": {
            "type": "string",
            "description": "Human-readable error message"
          },
          "trace_id": {
            "type": "string"
          }
        }
      },
      "SpotifyFeatures": {
        "type": "object",
        "description": "Spotify-compatible audio features shape, returned when `?format=spotify`\nis set on `/v1/audio-features*` routes. Mood values are 0.0-1.0 floats\n(not 0-100 ints), key is a pitch-class integer (C=0 .. B=11, unknown=-1),\nand mode is an integer (major=1, minor=0, unknown=-1). Field names match\nSpotify's deprecated /v1/audio-features endpoint.\n",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "audio_features"
            ]
          },
          "uri": {
            "type": "string",
            "description": "Brizm-namespaced URI (afa:track:<id>)"
          },
          "track_href": {
            "type": "string",
            "format": "uri"
          },
          "analysis_url": {
            "type": "string",
            "format": "uri"
          },
          "key": {
            "type": "integer",
            "minimum": -1,
            "maximum": 11,
            "description": "Pitch class of root note (C=0..B=11, -1=unknown)"
          },
          "mode": {
            "type": "integer",
            "enum": [
              -1,
              0,
              1
            ],
            "description": "1=major, 0=minor, -1=unknown"
          },
          "tempo": {
            "type": "number",
            "format": "float"
          },
          "loudness": {
            "type": "number",
            "format": "float",
            "description": "Loudness in dB (LUFS preferred)"
          },
          "time_signature": {
            "type": "integer",
            "minimum": 3,
            "maximum": 7
          },
          "duration_ms": {
            "type": "integer",
            "minimum": 0
          },
          "energy": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "maximum": 1
          },
          "danceability": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "maximum": 1
          },
          "valence": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "maximum": 1
          },
          "acousticness": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "maximum": 1
          },
          "instrumentalness": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "maximum": 1
          },
          "speechiness": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "maximum": 1
          },
          "liveness": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "maximum": 1
          }
        }
      },
      "JobEnvelope": {
        "type": "object",
        "description": "Async job envelope returned by `POST /v1/audio-features/{upload,url}`\nand by `GET /v1/jobs/{job_id}` polling. When `status=complete`, the\n`result` field carries the canonical `Features` shape (or\n`SpotifyFeatures` when `?format=spotify` is set).\n",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "complete",
              "failed"
            ]
          },
          "job_id": {
            "type": "string"
          },
          "result": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Features"
              },
              {
                "$ref": "#/components/schemas/SpotifyFeatures"
              }
            ],
            "nullable": true
          },
          "error": {
            "$ref": "#/components/schemas/Error",
            "nullable": true
          },
          "_meta": {
            "$ref": "#/components/schemas/MetaEnvelope"
          }
        }
      },
      "BatchRequest": {
        "type": "object",
        "required": [
          "ids"
        ],
        "properties": {
          "ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "string"
            },
            "description": "Track IDs (any supported form \u2014 Spotify, MBID, ISRC, Apple, Deezer, YouTube). Up to 100 per call."
          },
          "extended": {
            "type": "boolean",
            "default": false,
            "description": "When true, include Brizm fields (camelot, mix in/out, mood tags) beyond the Spotify-compatible set."
          }
        }
      },
      "AssetInput": {
        "type": "object",
        "description": "JSON body for referencing a previously uploaded asset on any POST\nprocessing endpoint. Pass `Content-Type: application/json` with this\nbody instead of raw audio bytes.\n",
        "required": [
          "asset_id"
        ],
        "properties": {
          "asset_id": {
            "type": "string",
            "description": "Asset ID returned by POST /v1/assets/upload (afa_ prefix)."
          }
        }
      },
      "AssetMetadata": {
        "type": "object",
        "properties": {
          "asset_id": {
            "type": "string",
            "description": "Opaque asset identifier (afa_ prefix)."
          },
          "sha256": {
            "type": "string",
            "description": "Hex-encoded SHA-256 of the stored audio bytes."
          },
          "size_bytes": {
            "type": "integer"
          },
          "content_type": {
            "type": "string",
            "description": "MIME type of the uploaded file (e.g. audio/mpeg)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the asset is automatically deleted (24 h BASIC / 7 d PRO)."
          }
        }
      },
      "AssetListResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AssetMetadata"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Pass as `cursor` query param to retrieve the next page. Null when there are no more items."
          },
          "count": {
            "type": "integer",
            "description": "Number of items in this page."
          }
        }
      },
      "BatchResponse": {
        "type": "object",
        "description": "Batch audio-features response. The `audio_features` array preserves\npositional mapping to the request `ids`: each slot is either a feature\nobject (Spotify shape when `?format=spotify`, canonical otherwise) or\n`null` when that specific ID could not be resolved. Length always\nmatches the request `ids` length.\n",
        "required": [
          "audio_features"
        ],
        "properties": {
          "audio_features": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/Features"
                },
                {
                  "$ref": "#/components/schemas/SpotifyFeatures"
                },
                {
                  "type": "null"
                }
              ]
            }
          },
          "_meta": {
            "$ref": "#/components/schemas/MetaEnvelope"
          }
        }
      }
    }
  },
  "paths": {
    "/v1/assets/upload": {
      "post": {
        "tags": [
          "Assets"
        ],
        "summary": "Upload audio \u2014 get a reusable asset_id",
        "description": "Upload raw audio bytes to receive an `asset_id` that can be referenced on\nany POST processing endpoint. Supports MP3, WAV, FLAC, OGG, M4A (and any\nother ffmpeg-supported format). Maximum upload: 15 MB on BASIC tier,\n50 MB on PRO.\n\n**Zero credits charged** \u2014 this call only stores the audio. Credits are\nconsumed when you call a processing endpoint with the returned `asset_id`.\n\n**SHA-256 deduplication**: uploading the same bytes twice (same owner)\nreturns the existing `asset_id`. It is safe to call this unconditionally\nbefore each processing batch.\n\n**Asset TTL**: 24 hours on BASIC, 7 days on PRO. Assets expire\nautomatically \u2014 no manual deletion is required.\n",
        "requestBody": {
          "required": true,
          "content": {
            "audio/*": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Raw audio bytes. Set Content-Type to the appropriate MIME type (audio/mpeg, audio/wav, audio/flac, etc.)."
              }
            },
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Asset stored. Returns asset_id, SHA-256, size, and expiry.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "asset_id": {
                      "type": "string",
                      "description": "Opaque identifier (afa_ prefix). Pass to any processing endpoint."
                    },
                    "sha256": {
                      "type": "string",
                      "description": "Hex SHA-256 of the stored bytes. Useful for client-side dedup."
                    },
                    "size_bytes": {
                      "type": "integer"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Upload exceeds tier size limit (15 MB BASIC / 50 MB PRO)"
          },
          "415": {
            "description": "Unsupported media type \u2014 must be audio/* or application/octet-stream"
          }
        }
      }
    },
    "/v1/assets": {
      "get": {
        "tags": [
          "Assets"
        ],
        "summary": "List uploaded assets",
        "description": "Returns a paginated list of assets owned by the authenticated API key.\nAssets from other tenants are never visible.\n",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "description": "Number of items per page (default 50, max 200)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Asset ID to paginate from (exclusive). Use `next_cursor` from the previous response."
          }
        ],
        "responses": {
          "200": {
            "description": "Asset list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/v1/assets/{id}": {
      "get": {
        "tags": [
          "Assets"
        ],
        "summary": "Get asset metadata",
        "description": "Returns metadata for a single asset. Returns 404 if the asset has expired\nor never existed. Does not download audio bytes.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Asset ID (afa_ prefix) returned by POST /v1/assets/upload."
          }
        ],
        "responses": {
          "200": {
            "description": "Asset metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetMetadata"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Asset not found or expired"
          }
        }
      }
    },
    "/v1/audio-features": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "Audio features by metadata",
        "description": "Returns full audio features for a track identified by song + artist.\nCache hits are free; misses trigger on-demand compute and charge credits.\n",
        "parameters": [
          {
            "name": "song",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "Get Lucky"
          },
          {
            "name": "artist",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "Daft Punk"
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "spotify"
              ]
            },
            "description": "Set to `spotify` for Spotify-parity output shape."
          }
        ],
        "responses": {
          "200": {
            "description": "Features returned",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Features"
                    },
                    {
                      "$ref": "#/components/schemas/SpotifyFeatures"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits"
          },
          "404": {
            "description": "Track not found"
          }
        }
      },
      "post": {
        "tags": [
          "Analysis"
        ],
        "summary": "Batch audio features by IDs",
        "description": "Looks up audio features for up to 100 track IDs in a single call.\nPositional result: each slot in `audio_features` corresponds to the\nsame index in the request `ids` array \u2014 `null` marks an ID that could\nnot be resolved.\n\nBilling is per-slot via V2 sub-operations (not a flat route cost):\nresolved slots consume 2 credits each, null slots are refunded\nautomatically. Use `?format=spotify` to receive Spotify-compatible\nper-element shape.\n",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "spotify"
              ]
            },
            "description": "Set to `spotify` for Spotify-parity per-element shape."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Batch resolved (may contain null slots)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed batch request (missing `ids`, non-array, too many)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "402": {
            "description": "Insufficient credits"
          }
        }
      }
    },
    "/v1/key-bpm": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "Fast BPM + key lookup",
        "description": "Lightweight endpoint that returns only tempo, key, mode, and camelot.\nUses the same cache as /v1/audio-features but skips mood features.\n",
        "parameters": [
          {
            "name": "song",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "Get Lucky"
          },
          {
            "name": "artist",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "Daft Punk"
          }
        ],
        "responses": {
          "200": {
            "description": "BPM + key returned",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tempo": {
                      "type": "number"
                    },
                    "key": {
                      "type": "string"
                    },
                    "mode": {
                      "type": "string"
                    },
                    "camelot": {
                      "type": "string"
                    },
                    "_meta": {
                      "$ref": "#/components/schemas/MetaEnvelope"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/resolve/{id}": {
      "get": {
        "tags": [
          "Resolution"
        ],
        "summary": "Cross-platform ID resolution",
        "description": "Convert any track ID (Spotify, Apple, Deezer, ISRC, MusicBrainz) into\nall other platform IDs plus identity metadata. Zero-credit operation.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "spotify:2WfaOiMkCvy7F5fcp2zZ8L"
          }
        ],
        "responses": {
          "200": {
            "description": "Identity resolved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mbid": {
                      "type": "string"
                    },
                    "isrc": {
                      "type": "string"
                    },
                    "spotify_id": {
                      "type": "string"
                    },
                    "apple_id": {
                      "type": "string"
                    },
                    "deezer_id": {
                      "type": "string"
                    },
                    "youtube_id": {
                      "type": "string"
                    },
                    "artist": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "_meta": {
                      "$ref": "#/components/schemas/MetaEnvelope"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "ID not recognized"
          }
        }
      }
    },
    "/v1/beatgrid/{id}": {
      "get": {
        "tags": [
          "DJ Intelligence"
        ],
        "summary": "Beat grid with DJ-verified BPM",
        "description": "Returns frame-level beat and downbeat timestamps plus DJ-verified tempo.\nPerfect for syncing decks or building an auto-cue system.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Beat grid returned",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tempo": {
                      "type": "number"
                    },
                    "downbeat": {
                      "type": "number"
                    },
                    "beats": {
                      "type": "array",
                      "items": {
                        "type": "number"
                      }
                    },
                    "downbeats": {
                      "type": "array",
                      "items": {
                        "type": "number"
                      }
                    },
                    "_meta": {
                      "$ref": "#/components/schemas/MetaEnvelope"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/bpm": {
      "post": {
        "tags": [
          "Upload"
        ],
        "summary": "BPM detection from uploaded audio or asset",
        "description": "Detect tempo from audio. Supports two input modes:\n\n1. **Direct upload** \u2014 POST raw audio bytes with `Content-Type: audio/*`\n   (MP3, WAV, FLAC, OGG, M4A). Same as before, unchanged.\n2. **Asset reference** \u2014 POST `{\"asset_id\": \"afa_xxx\"}` with\n   `Content-Type: application/json` to reference audio already uploaded\n   via `POST /v1/assets/upload`. No re-upload, same credit cost.\n\nThis dual-input pattern applies to all POST processing endpoints.\nCharges 2 credits per request regardless of input mode.\n",
        "requestBody": {
          "required": true,
          "content": {
            "audio/*": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Raw audio bytes (direct upload mode)."
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetInput",
                "description": "Asset reference mode \u2014 omits re-upload."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "BPM detected",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tempo": {
                      "type": "number"
                    },
                    "confidence": {
                      "type": "number"
                    },
                    "asset_id": {
                      "type": "string",
                      "nullable": true,
                      "description": "Echo of the asset_id used (only present when called with asset reference mode)."
                    },
                    "asset_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "When the referenced asset expires (only present when called with asset reference mode)."
                    },
                    "_meta": {
                      "$ref": "#/components/schemas/MetaEnvelope"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Asset not found or expired (when using asset reference mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio-features/{id}": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "Audio features by track ID",
        "description": "Returns audio features for a track identified by any supported ID\nform \u2014 Spotify ID, MusicBrainz ID (MBID), ISRC, Apple Music ID,\nDeezer ID, or YouTube ID. Cache hits are free; misses trigger\non-demand compute and charge 2 credits.\n\nUse `?format=spotify` to receive Spotify-compatible shape (0.0-1.0\nfloats, pitch-class integer key, Spotify field names). See\nguides/replacing-spotipy-python.\n",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "2WfaOiMkCvy7F5fcp2zZ8L"
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "spotify"
              ]
            },
            "description": "Set to `spotify` for Spotify-parity output shape."
          }
        ],
        "responses": {
          "200": {
            "description": "Features returned",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Features"
                    },
                    {
                      "$ref": "#/components/schemas/SpotifyFeatures"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits"
          },
          "404": {
            "description": "Track not found"
          }
        }
      }
    },
    "/v1/audio-features/upload": {
      "post": {
        "tags": [
          "Upload"
        ],
        "summary": "Full analysis from uploaded audio",
        "description": "Upload raw audio for full analysis (BPM + key + mood + spectral).\nReturns 202 with a `job_id`; poll `GET /v1/jobs/{job_id}` until\n`status=complete`. Charges 10 credits on reserve, refunded on\nfailure. Maximum upload size is tier-dependent (15 MB Starter /\n50 MB Pro).\n\nUse `?format=spotify` to receive the result shape in Spotify-parity\nformat once the job completes.\n",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "spotify"
              ]
            }
          },
          {
            "name": "include_embedding",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "(PRO only) Include 768-dimensional MAEST embedding in result."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "audio/*": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job accepted; poll /v1/jobs/{job_id}",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "402": {
            "description": "Insufficient credits"
          },
          "413": {
            "description": "Upload exceeds tier size limit"
          }
        }
      }
    },
    "/v1/audio-features/url": {
      "post": {
        "tags": [
          "Upload"
        ],
        "summary": "Full analysis from an HTTP(S) URL",
        "description": "Analyze audio reachable at a public HTTP(S) URL (e.g. S3 pre-signed,\nCDN). Semantics mirror `/v1/audio-features/upload` \u2014 async 202 +\njob_id polling, 10 credits on reserve with failure refund. The URL\nmust return audio bytes directly (no HTML, no auth challenge).\n",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "spotify"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "include_embedding": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job accepted; poll /v1/jobs/{job_id}",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "Missing or malformed `url`"
          },
          "401": {
            "description": "Unauthorized"
          },
          "402": {
            "description": "Insufficient credits"
          }
        }
      }
    },
    "/v1/jobs/{job_id}": {
      "get": {
        "tags": [
          "Analysis"
        ],
        "summary": "Poll an async job",
        "description": "Returns the current state of an async job dispatched by\n`POST /v1/audio-features/{upload,url}`. Polling is free and\nrate-limited separately from feature credits.\n\nWhen `?format=spotify` is set, the `result` field (on complete)\ncarries the Spotify-compatible shape instead of the canonical one.\n",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "spotify"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobEnvelope"
                }
              }
            }
          },
          "404": {
            "description": "Unknown job_id"
          }
        }
      }
    },
    "/v1/identify": {
      "post": {
        "tags": [
          "Track Identification"
        ],
        "summary": "Identify a track from audio",
        "description": "Upload audio to identify the track via a multi-provider fingerprinting cascade.\nReturns artist, title, ISRC, and \u2014 if matched \u2014 free enrichment including BPM, key,\ngenre, streaming platform IDs, and artwork. Synchronous; typical response 3-10 seconds.\nCharges 3 credits per request (cache hits are free).\n",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Audio file (any ffmpeg-supported format \u2014 MP3, WAV, FLAC, OGG, M4A, etc.)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Identification complete (matched or unmatched)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "matched",
                    "services_tried",
                    "_meta"
                  ],
                  "properties": {
                    "matched": {
                      "type": "boolean",
                      "description": "Whether the track was identified"
                    },
                    "artist": {
                      "type": "string",
                      "description": "Artist name (present when matched)"
                    },
                    "title": {
                      "type": "string",
                      "description": "Track title (present when matched)"
                    },
                    "album": {
                      "type": "string"
                    },
                    "year": {
                      "type": "string"
                    },
                    "isrc": {
                      "type": "string",
                      "description": "International Standard Recording Code"
                    },
                    "confidence": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100,
                      "description": "Match confidence (0-100)"
                    },
                    "source_service": {
                      "type": "string",
                      "description": "Which cascade service produced the match"
                    },
                    "services_tried": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string",
                        "enum": [
                          "match",
                          "no_match",
                          "error",
                          "skipped"
                        ]
                      },
                      "description": "Status of each identification service attempted"
                    },
                    "enrichment": {
                      "type": "object",
                      "nullable": true,
                      "description": "Free enrichment data from Brizm's database (null when unmatched)",
                      "properties": {
                        "bpm": {
                          "type": "number"
                        },
                        "key": {
                          "type": "string"
                        },
                        "camelot": {
                          "type": "string"
                        },
                        "genre": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "styles": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "label": {
                          "type": "string"
                        },
                        "spotify_id": {
                          "type": "string"
                        },
                        "apple_id": {
                          "type": "string"
                        },
                        "deezer_id": {
                          "type": "string"
                        },
                        "youtube_id": {
                          "type": "string"
                        },
                        "artwork_url": {
                          "type": "string",
                          "format": "uri"
                        }
                      }
                    },
                    "_meta": {
                      "$ref": "#/components/schemas/MetaEnvelope"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request (missing file, invalid audio, or audio under 3 seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits"
          },
          "413": {
            "description": "File exceeds tier upload limit (15 MB BASIC / 50 MB PRO)"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "502": {
            "description": "All identification services unavailable"
          },
          "503": {
            "description": "Server overloaded \u2014 retry after backoff"
          }
        }
      }
    }
  }
}