Skip to content

Concepts

crate is cluster-first: cluster_id is the prime key, the artist is the root, and master / bandcamp are dimensions of the artist dossier. These are the terms that recur across the API and SDK.

crate’s one true name for an artist — a pe-norm-v1 hex string that collapses the same artist’s Discogs, MusicBrainz, and Bandcamp identities into a single canonical key. Key all artist data off it. It’s an opaque string: pass it through verbatim, never numericize it. cluster_id:null is an honest gap (couldn’t resolve), not an error.

See: IdentityResolution (resolveIdentity, GET /api/v2/resolve); ArtistDossierContract.cluster_id (GET /api/v2/artist/{key})

The full picture crate composes for one entity by joining every fleet signal. Each facet carries a classified state plus a provenance manifest (producer, source table, refresh cadence, tier). Read /dossier/manifest to discover the whole field surface without calling every endpoint.

See: DossierManifest (GET /api/v2/dossier/manifest); ArtistDossierContract / LabelDossierContract / FestivalDossierContract

Which kind of agent a dossier is about: artist, label, or festival. Releases are not a top-level grain in v2 — release/master detail attaches to the artist dossier’s discography dimension. The dossier manifest also lists deliberately-unavailable grains (e.g. song — no fleet track key; and the demoted master grain).

See: GET /api/v2/dossier/artist/{slug}, /api/v2/dossier/label/{slug}, /api/v2/dossier/festival/{slug}; ArtistDossierContract.discography; DossierManifest.unavailable_grains

An unresolved or empty lookup returns HTTP 200 with present:false, a null field, or state:“honest_gap” — this is NORMAL, not an error. crate shows what it can see and is explicit about what it can’t, rather than 404-ing or faking data. Only 4xx/5xx are errors; branch on the body, not the status.

See: Error schema (the inverse: only 4xx/5xx); ArtistDossierContract.identity:null; dossier facets with state:“honest_gap”

The binding TIER of a resolved identity: ‘discogs’ = canonical Discogs-bound (verified); ‘cluster’ = OBSERVED/unverified from the booking graph (surface flagged-unverified, never as canonical); null = unresolved. A 64-hex cluster_id address is always ‘cluster’ by design.

See: IdentityResolution.resolved_via; ArtistDossierContract.resolved_via

How you addressed the artist on /resolve: ‘url’ (pasted link), ‘name’, or ‘locator’ (a foreign id). Paired with matched_on (which surface matched) and note (why a recognized link didn’t resolve).

See: IdentityResolution.resolved_from (GET /api/v2/resolve)

crate’s behavioral-signal model: a 3-bit string code (e.g. “101”) placing a release on three axes — who OWNS it (collector), who PLAYS it (DJ), who WRITES about it (critic). Codes run “000” (no signal) to “111” (full intersection). null = not yet classified (honest gap). owner_count/dj_count/critic_count give the magnitude. You meet it on the result rows of /api/v2/search.

See: ResultRow.cube_quadrant + owner_count/dj_count/critic_count + link_to_cube (GET /api/v2/search)

A discovery surface of influential curators plus crate’s richest artist-grain analytics (rank, own-tier, brokerage score, lead-times, Bandcamp demand). Served from an offline snapshot, fail-soft: state is present/empty/degraded (degraded = 200 honest-gap), stale=true if older than 7 days.

See: TastemakersResponse (GET /api/v2/tastemakers); OnesToWatchResponse (GET /api/v2/tastemakers/ones-to-watch)

A discovery surface of emerging artists on the rise (‘ones to watch’) — booking momentum cross-validated against press. Filter by ?tier=breakout|rising and ?corroboration=corroborated|booking_ahead; ?limit= clamped to 200. Fail-soft state present/empty/degraded.

See: BreakoutsResponse (GET /api/v2/breakouts)

Client-side search-event telemetry (observed = cache hit, refined = facet change). Authenticated NOT with X-API-Key but with a short-lived per-search JWT bound to one search_event_id, sent as Authorization: Bearer. Bodies <=512 bytes, idempotent (duplicate = 204 no-op).

See: ObservedBeaconRequest / RefinedBeaconRequest (POST /api/v2/search-events/observed, /refined); BeaconBearerAuth security scheme; BeaconError

The v2 artist dossier is default-rich (one round-trip). ?fields=identity,discography TRIMS to the named top-level facets (opt-out, not opt-in); omit it for the full dossier. An unknown field → 400 invalid_fields with the exact valid set + a copy-pasteable example.

See: GET /api/v2/artist/{key}?fields=…; the invalid_fields error (valid set + example)

In v2 Bandcamp is an ANALYTICAL dimension of the artist dossier (keyed by cluster_id), not a release surface: bandcamp_emergence = purchase-backed demand signals (emergence class, demand lead/ratio, owner reach, wishlist demand), bandcamp_tastemaker = early-supporter quality scores. Per-release Bandcamp listings (and bandcamp_item_id / track_url) are NOT a v2 surface — they belong to the v1 Bandcamp endpoints.

See: ArtistDossierContract.bandcamp_emergence / bandcamp_tastemaker (signals; GET /api/v2/artist/{key})

crate is link-only wherever it carries links: every artwork item is a hotlink url with rehost:false — crate never fetches or re-hosts bytes (a Cover Art Archive URL is best-effort, may 404). crate never stores Bandcamp audio streams (tokenized, expiring, out of ToS).

See: ArtworkItem (rehost:false) on the dossiers

cluster_id is always a string and always opaque — round-trip it verbatim, never parse, increment, or numericize. The same discipline applies to any id crate hands you. This keeps clients correct across id-scheme changes.

See: IdentityResolution.cluster_id; ArtistDossierContract.cluster_id

The API major version is the URL path (/api/v2). The spec’s info.version (2.0.0) bumps on every spec change and is drift-guarded because the document is generated from code. v2 is the cluster-first stable major; the frozen v1 predecessor is in a time-boxed deprecation (migration map at /docs/migration/v1-to-v2). Operations carry stable operationIds; keyed 2xx responses declare X-RateLimit-* headers.

See: info.version; GET /api/v2/openapi.json; the migration guide at /docs/migration/v1-to-v2