Music-data gateway · API-first

One canonical ID for every artist — across every catalogue.

crate resolves any name, link, or third-party id to a single cluster_id, then hands you the whole fleet's data on it — discography, bookings, press, momentum signals — in one call. And it's honest about what it doesn't know.

No SDK lock-in · plain REST + a typed client · X-API-Key and you're in.
resolve.sh
# any name, link, or id -> the canonical cluster
curl https://crate.hosaka.fm/api/v2/resolve?q=Burial \
  -H "X-API-Key: $CRATE_KEY"

{
  "cluster_id": "b3a9f2c1...e7",        // the prime key
  "slug": "burial",
  "resolved_via": "discogs",            // verified bind
  "locators": {
    "discogs": 31337,
    "musicbrainz": "a4f1...",
    "bandcamp": "burial.bandcamp.com"
  }
}
Try it now — no key needed
keyless-preview.sh
curl 'https://crate.hosaka.fm/api/v2/preview/artist?q=four+tet'

{
  "object": "artist.preview",
  "present": true,
  "display": "Four Tet",
  "cluster_id": null,
  "resolved_via": "discogs",
  "emergence_tier": "steady",
  "arc": [
    { "year": 1996, "tier": "press",   "label": "first press mention" },
    { "year": 1998, "tier": "bandcamp","label": "first release" },
    { "year": 2001, "tier": "radio",   "label": "first radio airplay" }
  ],
  "arc_truncated": true,
  "booked_with": ["Ben UFO","Floating Points","Pearson Sound"],
  "press_count": 50,
  "note": "Education preview — a capped subset of the artist dossier."
}
100 req/hr · no key · IP-rate-limited · fails closed 503

As of 2026-08-04: v2 spec = 2.47.0 · 22 documented resources on the self-describing index (/api/v2) — including title-first track search (/api/v2/tracks) · 15 catalogued errors with copy-pasteable fixes · v1 frozen (deprecation shim) · 2 keyless surfaces (/api/v2/preview/artist + /api/v2/openapi.json) · billed on 2xx only — errors and 429s are never charged.

The cold-start recipe

Three calls to everything we know.

You don't need to learn crate's internals. Convert whatever identifier you're holding into a cluster, then read the dossier. That's it.

01 · resolve

Hand us an identifier

A name, a Discogs/MusicBrainz id, an ISRC, an artist+track pair, or any artist link — Bandcamp, SoundCloud, Spotify, a website. We reverse-match it to one cluster.

GET /api/v2/resolve?url=…
02 · dossier

Read the whole picture

One call returns the canonical dossier: discography, live bookings, press, and emergence signals — composed across the fleet of producers.

GET /api/v2/artist/{cluster_id}
03 · ship

Render it

Flat, source-tagged JSON with an honest-gap state on every field — so your UI never guesses. Same shape across artists, labels, releases.

200 · private, no-store · typed
Why a gateway

The hard part is already done.

Five music catalogues disagree about who an artist even is. crate reconciles them once, so you integrate one API instead of five.

cluster-first

One key, not five

Every artist, label, and release rolls up to a single cluster_id — Discogs, MusicBrainz, Bandcamp, booking data and more, reconciled. The long tail with no Discogs id still resolves.

one call

The dossier, composed

No fan-out, no joining six endpoints. Ask for an entity and get everything — identity, catalogue, bookings, press, signals — assembled server-side in one round trip.

honest-gap

It tells you what it doesn't know

Every field carries provenance and a state — live, fallback, blind — and the producer + refresh cadence behind it. Unresolved lookups return 200 with nulls, never a 404 guess.

typed

Autocomplete on every response

Plain REST you can curl, plus a typed @hosaka-fm/crate client with generated types — your editor knows every field before you run it.

The typed client

REST when you want it. Types when you need them.

The SDK is a thin, typed wrapper over the same REST API — no magic, no lock-in. Generated straight from the OpenAPI spec, so the types never drift from production.

  • Full TypeScript types on every request and response.
  • Resolve helpers for names, links, and ids.
  • Drop down to raw fetch any time — it's just HTTP.
app.ts
import { Crate } from "@hosaka-fm/crate";

const crate = new Crate({ apiKey: process.env.CRATE_API_KEY });

// name -> canonical cluster (fully typed)
const { cluster_id } = await crate.resolve({ q: "Burial" });

// -> the whole dossier, source-tagged
const artist = await crate.artist.get(cluster_id);

artist.discography[0].title;  // string | autocompletes
Pricing

Pay for data that returns. Nothing else.

Every plan is metered on successful responses. Start free, no card — enough to build a real prototype, not a teaser.

Free
$0
10,000 calls/mo
Evaluate, prototype, learn the shape. No card.
Start free
Indie
$49/mo
15,000 calls/mo
Solo devs and small integrations in production.
Studio
$149/mo
100,000 calls/mo
Funded startups and production apps.
Scalemost data
$499/mo
500,000 calls/mo
High-volume product companies.
Sync
$2,000/mo
2,000,000 calls/mo
Licensing & sync agencies. SLA + named support.
Talk to us
A call counts only when it returns you data — errors and 429s are never billed. Need more? Metered overage past your plan, capped at a limit you set. Cached responses included — you're billed per result, not per cache hit.

Ship your first dossier today.

Grab a free key, paste it into a curl, and resolve your first artist before your coffee's cold.