{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/freqblog-com/json-schema/freqblog-com-identify-response-schema.json",
  "title": "IdentifyResponse",
  "x-generated": "2026-10-30",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/freqblog-com-openapi.json#/components/schemas/IdentifyResponse",
  "properties": {
    "matched": {
      "type": "boolean",
      "title": "Matched",
      "description": "True when the fingerprint matched a known recording in the AcoustID database."
    },
    "score": {
      "type": "number",
      "maximum": 1.0,
      "minimum": 0.0,
      "title": "Score",
      "description": "AcoustID match confidence, 0–1."
    },
    "acoustid": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Acoustid",
      "description": "AcoustID UUID for the recording group, when known."
    },
    "mbid": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Mbid",
      "description": "MusicBrainz Recording ID for the matched recording."
    },
    "isrc": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Isrc",
      "description": "ISRC, when resolvable from the matched recording."
    },
    "track_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Track Name",
      "description": "Track title from the AcoustID/MusicBrainz match."
    },
    "artist_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Artist Name",
      "description": "Artist name(s) from the AcoustID/MusicBrainz match."
    },
    "in_catalog": {
      "type": "boolean",
      "title": "In Catalog",
      "description": "True if the matched recording is already in the FreqBlog catalog. When true, `audio_features` is populated.",
      "default": false
    },
    "audio_features": {
      "anyOf": [
        {
          "$ref": "#/$defs/TrackLookupResponse"
        },
        {
          "type": "null"
        }
      ],
      "description": "Full FreqBlog audio features for the matched recording — populated when the MBID resolves to a catalog row, otherwise null. Call `/lookup` separately if you want to trigger an on-demand analysis for unknown recordings."
    },
    "fingerprint_duration_seconds": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "title": "Fingerprint Duration Seconds",
      "description": "Duration of the fingerprinted audio (seconds), as reported by Chromaprint."
    },
    "analysis": {
      "anyOf": [
        {
          "$ref": "#/$defs/AudioAnalysisResponse"
        },
        {
          "type": "null"
        }
      ],
      "description": "Audio features computed directly from the file you uploaded, populated when the recording could not be resolved to a catalog row (unknown fingerprint, or matched but not in the catalog). Set `analyze=false` to skip this and get identification only."
    },
    "features_from": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Features From",
      "description": "Where the returned features came from — `catalog` (a known recording, in `audio_features`) or `upload` (computed from your file, in `analysis`); null when no features were produced. Deliberately explicit: catalog values come from our 30-second-preview pipeline and upload values from your full file, so they are not interchangeable and a caller should never have to guess which it got."
    }
  },
  "type": "object",
  "required": [
    "matched",
    "score"
  ],
  "$defs": {
    "AudioAnalysisResponse": {
      "properties": {
        "bpm": {
          "type": "number",
          "maximum": 300.0,
          "minimum": 20.0,
          "title": "Bpm",
          "description": "Tempo in beats per minute. Same field name/role as `tempo` in Spotify's response shape."
        },
        "bpm_alt": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Bpm Alt",
          "description": "Half-time corrected alternative BPM (twice the detected `bpm`), when our heuristic is fairly confident the detector locked onto half the beat grid. Only offered for tracks detected at 70-88 BPM; null otherwise. Never replaces `bpm`. Drum & bass is the one exception: a track detected at 108-122 BPM gets 1.5x the detected `bpm` (e.g. 115 -> 172.5), because the detector often reads a 174 BPM break at two-thirds speed."
        },
        "bpm_confidence": {
          "type": "number",
          "title": "Bpm Confidence",
          "description": "Beat-strength score from Essentia's RhythmExtractor2013. Higher = stronger rhythmic pulse. Range about 0–5.3, catalogue median ~2.9. Values below 1.0 indicate weak or absent rhythm (ambient, spoken word)."
        },
        "key": {
          "type": "string",
          "title": "Key",
          "description": "Musical key and scale as a human-readable string, e.g. `A-Minor` or `F#-Major`. Combines Spotify's integer `key` + `mode` fields into one readable value."
        },
        "key_confidence": {
          "type": "number",
          "maximum": 1.0,
          "minimum": 0.0,
          "title": "Key Confidence",
          "description": "Key detection confidence [0–1]. Below 0.4 indicates atonal, modal, or harmonically ambiguous content."
        },
        "mode": {
          "anyOf": [
            {
              "type": "integer",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Mode",
          "description": "Musical mode as a Spotify-compatible integer: `0` = minor, `1` = major. Direct drop-in for Spotify's deprecated `mode` field."
        },
        "key_int": {
          "anyOf": [
            {
              "type": "integer",
              "maximum": 11.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Key Int",
          "description": "Pitch-class integer for the key, Spotify-compatible: `0` = C, `1` = C♯/D♭, `2` = D, … `11` = B. `null` when the key is undetected/atonal (Spotify used `-1`)."
        },
        "camelot": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Camelot",
          "description": "Camelot wheel notation for harmonic mixing, e.g. `8A` (A-Minor) or `5B` (D-Major). Used by DJs to find harmonically compatible tracks. A = minor keys, B = major keys. Numbers 1–12."
        },
        "open_key": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Open Key",
          "description": "Open Key notation for harmonic mixing, e.g. `1m` (A-Minor) or `1d` (C-Major). Alternative to Camelot — used by Serato DJ and Mixed In Key. d = major (dominant), m = minor. Numbers 1–12."
        },
        "acousticness": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Acousticness",
          "description": "Acousticness [0–1]. Where the recording has AcousticBrainz features we serve their trained-classifier value. Otherwise, a model that listens to the preview (PANNs embeddings, CC BY 4.0, trained on AcousticBrainz's CC0 labels) as each track is re-analysed since 2026-09-27, most-requested first; tracks not yet reached carry our spectral-flatness estimate rescaled onto the same distribution, which is a sorting signal rather than a verdict on one track."
        },
        "danceability": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Danceability",
          "description": "How suitable the track is for dancing [0–1], on AcousticBrainz's scale: its own classifier value where the recording has AcousticBrainz features, otherwise a model that listens to the preview (PANNs embeddings, CC BY 4.0, trained on AcousticBrainz's CC0 labels). Rolling out since 2026-09-27, most-requested first; tracks not yet reached carry our earlier tempo/beat-strength estimate. Re-derive thresholds rather than copying them from another service."
        },
        "instrumentalness": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Instrumentalness",
          "description": "Likelihood the 30-second preview contains no vocals [0–1] (above 0.5 = likely instrumental), from a PANNs-based model trained on the vocal/no-vocal labels of the MUSAN corpus (Snyder et al. 2015, CC BY 4.0). Describes the preview, not the whole track. Null where a track has not been through the model yet."
        },
        "liveness": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Liveness",
          "description": "Likelihood the track was performed live [0–1]. **Null for tracks from our own audio analysis**: our signal-based estimate was not reliable enough to serve (it read most studio recordings as live), so we return null rather than a misleading value. Populated where an external source supplies it."
        },
        "speechiness": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Speechiness",
          "description": "Presence of spoken words [0–1] (above ~0.33 = rap or mixed speech, above ~0.66 = mostly spoken). **Null for tracks from our own audio analysis**: our signal-based estimate was not reliable enough to serve, so we return null rather than a misleading value. Populated where an external source supplies it."
        },
        "valence": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Valence",
          "description": "Musical positiveness [0–1]. High = happy/euphoric, low = sad/dark. Estimated from scale, tempo, brightness and energy — a coarse signal; treat it as a sorting aid rather than a per-track verdict."
        },
        "mood": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Mood",
          "description": "MIREX-style mood category derived from valence and energy. One of: happy, calm, sad, tense, energetic, melancholic, neutral. Maps the four-quadrant mood model: high valence + high energy = happy; low valence + high energy = tense; etc."
        },
        "representative_segment_start": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Representative Segment Start",
          "description": "Start time in seconds of the highest-energy 30-second window. Identifies the most sonically representative (e.g. chorus or drop) segment. Useful for sync licensing, preview generation, and waveform thumbnails. 0.0 for tracks ≤ 30 s."
        },
        "rms_energy": {
          "type": "number",
          "maximum": 1.0,
          "minimum": 0.0,
          "title": "Rms Energy",
          "description": "Perceptual intensity [0–1] from RMS loudness, on our own scale (loud masters sit near the top of it). Computed over the same 30-second window as BPM and key."
        },
        "loudness_db": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Loudness Db",
          "description": "Integrated loudness in dBFS (decibels relative to full scale). Same field role as `loudness` in Spotify's response shape. Typical mastered pop/electronic: -10 to -5 dBFS. Quiet/acoustic: -20 to -15."
        },
        "time_signature": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "Time Signature",
          "description": "Beats per bar. ASSUMED 4 (4/4) for every analysed track, not measured: no meter estimator we have tested beats a constant 4 on a mostly 4/4 catalogue. Same field role as `time_signature` in Spotify's response shape, kept for compatibility; do not filter or branch on it."
        },
        "mood_vector": {
          "anyOf": [
            {
              "additionalProperties": {
                "type": "number"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "title": "Mood Vector",
          "description": "Dimensional mood scores [0–1] across five axes: `happy`, `sad`, `aggressive`, `relaxed`, `party`. Populated when an AcousticBrainz high-level match is found; `null` otherwise. Use these for fine-grained mood filtering beyond the single-label `mood` field."
        },
        "cached": {
          "type": "boolean",
          "title": "Cached",
          "description": "True if this result was served from the server-side cache. Cached responses are < 100 ms. The underlying analysis is identical to a fresh result.",
          "default": false
        },
        "bpm_snapped": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "Bpm Snapped",
          "description": "`bpm` rounded to a whole number — the grid tempo, in the form every DJ tool reports. Traktor, Serato and Rekordbox return clean integers because they derive a BEAT GRID, and a grid has exactly one tempo by construction; our `bpm` is a *measurement* of the audio, so it carries a decimal. For grid-produced music the true tempo is almost certainly the whole number and the decimal is our error — `bpm_confidence` correlates with how close we land to an integer, which is the evidence for that. **Always populated, never null.** Use `bpm` when you want the measurement (beatmatching by ear, where 127.89 vs 128.00 is the point) and `bpm_confidence` to judge how far to trust either.",
          "readOnly": true
        }
      },
      "type": "object",
      "required": [
        "bpm",
        "bpm_confidence",
        "key",
        "key_confidence",
        "rms_energy",
        "bpm_snapped"
      ],
      "title": "AudioAnalysisResponse"
    },
    "ExtendedAudioFeatures": {
      "properties": {
        "gender": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Gender",
          "description": "Always null since 2026-10-02. Was a vocal-gender classification (`male` / `female`) from AcousticBrainz; it was too unreliable on real catalogue tracks to serve. The key is kept so existing parsers don't break."
        },
        "timbre": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Timbre",
          "description": "Timbral brightness classification: `bright` / `dark`. Bright = strong high-frequency content (cymbals, electric guitar); dark = bass-dominant."
        },
        "tonal_atonal": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Tonal Atonal",
          "description": "Tonality classification: `tonal` / `atonal`. Tonal = clear key centre; atonal = ambiguous or shifting tonality (typical of avant-garde / drone)."
        }
      },
      "type": "object",
      "title": "ExtendedAudioFeatures",
      "description": "Higher-level categorical labels from AcousticBrainz. Each value is the\nmost-confident class from a binary classifier — useful for filtering /\nbucketing but not for fine-grained analysis."
    },
    "TrackLookupResponse": {
      "properties": {
        "track_name": {
          "type": "string",
          "title": "Track Name",
          "description": "Track name as indexed in the catalogue or from MusicBrainz."
        },
        "artist_name": {
          "type": "string",
          "title": "Artist Name",
          "description": "Artist name."
        },
        "album_name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Album Name",
          "description": "Album or single title. Populated for catalog tracks."
        },
        "itunes_track_id": {
          "type": "string",
          "title": "Itunes Track Id",
          "description": "iTunes track ID for catalog tracks; 'mb:{mbid}' for AcousticBrainz-sourced tracks. (The former 'fma:' / 'msd:' ids no longer resolve.)"
        },
        "isrc": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Isrc",
          "description": "International Standard Recording Code. Uniquely identifies this specific master recording."
        },
        "mbid": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Mbid",
          "description": "MusicBrainz Recording ID (UUID). Cross-reference to the open music encyclopedia."
        },
        "is_remix": {
          "type": "boolean",
          "title": "Is Remix",
          "description": "True when this recording is a third-party remix/bootleg (not an original mix or same-performance version). Parsed from the title + credit at ingest. Always present; false for originals and fallback-layer tracks.",
          "default": false
        },
        "remixer": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Remixer",
          "description": "The third-party artist credited with the remix, when attributable; null for style-descriptor or unnamed remixes."
        },
        "mix_name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Mix Name",
          "description": "Version/mix descriptor for any variant (remix OR version), e.g. 'Extended Mix', 'Alesso Remix'. Null for a plain original."
        },
        "remix_of_isrc": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Remix Of Isrc",
          "description": "ISRC of the ORIGINAL recording this remix is based on, when the original is in the catalog (matched by base title + artist). Lets you jump from a remix to its source recording. Null for originals, unmatched remixes, and fallback-layer tracks."
        },
        "release_date": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Release Date",
          "description": "Release date in ISO 8601 format (YYYY-MM-DD), from catalogue metadata. Null for fallback-layer tracks."
        },
        "duration_ms": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "Duration Ms",
          "description": "Full track duration in milliseconds, from catalogue metadata. Distinct from `duration_seconds` (which is the analysed 30s window)."
        },
        "explicit": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "title": "Explicit",
          "description": "True if the track is marked explicit by the source. Null when not reported."
        },
        "bpm": {
          "type": "number",
          "maximum": 300.0,
          "minimum": 20.0,
          "title": "Bpm",
          "description": "Tempo in beats per minute."
        },
        "bpm_alt": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Bpm Alt",
          "description": "Half-time corrected alternative BPM (twice the detected `bpm`), when our heuristic is fairly confident Essentia locked onto half the beat grid. Only offered for tracks detected at 70-88 BPM; null otherwise (drum & bass detected at 108-122 BPM instead gets 1.5x, e.g. 115 -> 172.5: the detector often reads a 174 BPM break at two-thirds speed). **Never** replaces `bpm` — use this when your downstream tooling expects the perceived rather than detected tempo (e.g. pop tracks like 'Blinding Lights' where Essentia returns ~85 but the perceived BPM is ~171)."
        },
        "bpm_confidence": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Bpm Confidence",
          "description": "Beat-strength score from Essentia RhythmExtractor2013, about 0–5.3 (catalogue median ~2.9). Below ~1.5 the tempo is worth checking by ear: on crowd-tapped electronic tracks our BPM matched a listener's tempo 57% of the time below 1.0 and 99% at 3.5–4. Null for AcousticBrainz-sourced tracks."
        },
        "key": {
          "type": "string",
          "title": "Key",
          "description": "Musical key and scale, e.g. `C#-Minor`."
        },
        "key_confidence": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Key Confidence",
          "description": "Key detection confidence [0–1]. Null for AcousticBrainz-sourced tracks."
        },
        "mode": {
          "anyOf": [
            {
              "type": "integer",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Mode",
          "description": "Spotify-compatible mode integer: 0 = minor, 1 = major."
        },
        "key_int": {
          "anyOf": [
            {
              "type": "integer",
              "maximum": 11.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Key Int",
          "description": "Spotify-compatible pitch-class integer for the key: 0 = C, 1 = C♯/D♭, 2 = D, … 11 = B. `null` when the key is undetected/atonal (the Spotify-shaped `/v1/audio-features/{id}` endpoint reports `-1` in that case, matching Spotify's convention)."
        },
        "camelot": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Camelot",
          "description": "Camelot wheel notation, e.g. `12A`."
        },
        "open_key": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Open Key",
          "description": "Open Key notation, e.g. `5m` (C#-Minor). d=major, m=minor."
        },
        "energy": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Energy",
          "description": "Perceived energy [0–1] of the 30-second preview: a PANNs-based model (Kong et al. 2020, CC BY 4.0) placed on our existing energy scale (median ~0.65). It agrees better with human listener ratings than the RMS loudness it replaced (checked on two independent rating datasets); tracks the model has not reached yet still carry the RMS value."
        },
        "loudness_db": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Loudness Db",
          "description": "Integrated loudness in dBFS."
        },
        "danceability": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Danceability",
          "description": "How suitable the track is for dancing [0–1], on AcousticBrainz's scale: AcousticBrainz's classifier where a recording has it, otherwise a model built on PANNs embeddings (Kong et al. 2020, CC BY 4.0) and trained on AcousticBrainz labels."
        },
        "valence": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Valence",
          "description": "Musical positiveness [0–1] of the 30-second preview (high = happy/uplifting, low = sad/dark), from a PANNs-based model (Kong et al. 2020, CC BY 4.0) placed on our existing valence scale (median ~0.48). It agrees better with human listener ratings than the signal heuristic it replaced on two of three independent rating datasets; it still partly tracks energy, so treat it as a sorting aid. Tracks the model has not reached yet carry the heuristic value."
        },
        "speechiness": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Speechiness",
          "description": "Spoken word presence [0–1]. Null for catalogue tracks for now."
        },
        "instrumentalness": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Instrumentalness",
          "description": "Likelihood [0–1] that the 30-second preview has no vocals, from a model on PANNs embeddings (Kong et al. 2020, CC BY 4.0) trained on the vocal/no-vocal labels of the MUSAN corpus (Snyder et al. 2015, CC BY 4.0). Describes the preview, not the whole track. Null where a track has not been through the model yet."
        },
        "liveness": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Liveness",
          "description": "Live performance likelihood [0–1]. Null for catalogue tracks for now (not measured reliably enough to serve)."
        },
        "acousticness": {
          "anyOf": [
            {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0
            },
            {
              "type": "null"
            }
          ],
          "title": "Acousticness",
          "description": "Acousticness [0–1]: AcousticBrainz's classifier where available, otherwise a model built on PANNs embeddings (Kong et al. 2020, CC BY 4.0) and trained on AcousticBrainz labels."
        },
        "time_signature": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "Time Signature",
          "description": "Beats per bar. ASSUMED 4 (4/4) for every track we analyse, not measured: no meter estimator we have tested beats a constant 4 on a mostly 4/4 catalogue. Kept in the Spotify response shape for compatibility; do not filter or branch on it."
        },
        "mood": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Mood",
          "description": "MIREX-style mood category: happy, calm, sad, tense, energetic, melancholic, or neutral."
        },
        "mood_vector": {
          "anyOf": [
            {
              "additionalProperties": {
                "type": "number"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "title": "Mood Vector",
          "description": "Dimensional mood scores [0–1] across five axes: `happy`, `sad`, `aggressive`, `relaxed`, `party`. Populated when an AcousticBrainz high-level match is found; `null` otherwise."
        },
        "onset_rate": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Onset Rate",
          "description": "Onset events per second from AcousticBrainz low-level analysis. Higher values indicate more rhythmic or percussive content. Populated when an AcousticBrainz match is found; `null` otherwise."
        },
        "dynamic_complexity": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Dynamic Complexity",
          "description": "Loudness variation over the track (dB), from AcousticBrainz low-level analysis. Higher values mean wider dynamic range; lower values mean more compressed mastering. Populated when an AcousticBrainz match is found; `null` otherwise."
        },
        "tuning_frequency": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Tuning Frequency",
          "description": "Estimated A4 reference frequency in Hz, from AcousticBrainz tonal analysis. Modern recordings cluster near 440 Hz; older or non-Western recordings may diverge. Populated when an AcousticBrainz match is found; `null` otherwise."
        },
        "average_loudness": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Average Loudness",
          "description": "Average loudness as a normalised value [0–1] from AcousticBrainz low-level analysis. Distinct from `loudness_db` (which is dBFS from this service's own analysis). Populated when an AcousticBrainz match is found; `null` otherwise."
        },
        "genre": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Genre",
          "description": "Broad genre classification (e.g. electronic, rock, pop, hip-hop, jazz). From catalogue metadata, with AcousticBrainz as a fallback."
        },
        "extended": {
          "anyOf": [
            {
              "$ref": "#/$defs/ExtendedAudioFeatures"
            },
            {
              "type": "null"
            }
          ],
          "description": "Higher-level AcousticBrainz classifications. Populated when the track has an AcousticBrainz match — null otherwise. Counts as ONE of the 43 response fields (it is a single nested object), but its members are categorical labels rather than analysis values, so they are not counted individually."
        },
        "feature_source": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Feature Source",
          "description": "Provenance of the audio feature data. One of: `essentia_preview` (analysed from a 30s preview by this service), `acousticbrainz` (matched by MBID against the AcousticBrainz dump), `user_upload` (analysed from a file the user uploaded). (`fma` and `msd` were retired on 2026-09-29 and no longer appear.)"
        },
        "backfill_status": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Backfill Status",
          "description": "Backfill job status if one was queued: 'queued', 'processing', 'completed', 'failed'. Null if no backfill was needed."
        },
        "backfill_notification_id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Backfill Notification Id",
          "description": "Notification ID for tracking backfill progress. Use to query backfill_notifications table."
        },
        "chart_peak": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "Chart Peak",
          "description": "Best chart position we know this track reached, 1-100 where **100 = a number-one**. `null` means no chart placement we hold — which is the vast majority of the catalogue, so treat null as *unknown*, not as *unpopular*. ⚠ NOT an audience-size measure: it does not tell you monthly listeners or followers. Placements come from the Apple Music and Deezer charts we track (best position seen since August 2026) and Billboard's year-end charts (1960-2025), so most tracks have none. Present on the browse endpoints too — see `TrackStub.chart_peak`."
        },
        "bpm_snapped": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "Bpm Snapped",
          "description": "`bpm` rounded to a whole number — the grid tempo, in the form every DJ tool reports. Traktor, Serato and Rekordbox return clean integers because they derive a BEAT GRID, and a grid has exactly one tempo by construction; our `bpm` is a *measurement* of the audio, so it carries a decimal. For grid-produced music the true tempo is almost certainly the whole number and the decimal is our error — `bpm_confidence` correlates with how close we land to an integer, which is the evidence for that. **Always populated, never null.** Use `bpm` when you want the measurement (beatmatching by ear, where 127.89 vs 128.00 is the point) and `bpm_confidence` to judge how far to trust either.",
          "readOnly": true
        }
      },
      "type": "object",
      "required": [
        "track_name",
        "artist_name",
        "itunes_track_id",
        "bpm",
        "key",
        "bpm_snapped"
      ],
      "title": "TrackLookupResponse"
    }
  }
}