Skip to content
159 changes: 126 additions & 33 deletions api-reference/openapi/research.json
Original file line number Diff line number Diff line change
Expand Up @@ -804,13 +804,13 @@
},
"/api/research": {
"get": {
"description": "Search for artists by name. Returns matching results with profile summaries.",
"description": "Unified Chartmetric search. This is the discovery primitive for the detail-lookup endpoints — use `type=artists` to find an `id` for [GET /api/research/albums](/api-reference/research/albums), `type=tracks` for [GET /api/research/track](/api-reference/research/track), `type=playlists` for [GET /api/research/playlist](/api-reference/research/playlist), etc. Pick the right `id` from the returned results and pass it to the appropriate detail endpoint.\n\nThin proxy over Chartmetric's `/search`. Chartmetric's default search engine is narrow — for ambiguous queries like `Hotline Bling` or `Flowers` it often returns a single low-quality match. **Pass `beta=true` for higher relevance and accuracy**, which switches Chartmetric to its improved ranking engine. Beta results include a numeric `match_strength` score and have a slightly different shape than the default engine (see the response schema).",
"parameters": [
{
"name": "q",
"in": "query",
"required": true,
"description": "Artist name to search for.",
"description": "Search query. Can be a name (e.g. `Drake`, `Flowers`) or a streaming-platform URL (e.g. `https://open.spotify.com/artist/...`).",
"schema": {
"type": "string"
}
Expand All @@ -819,7 +819,7 @@
"name": "type",
"in": "query",
"required": false,
"description": "Entity type.",
"description": "Entity type to search.",
"schema": {
"type": "string",
"enum": [
Expand All @@ -842,6 +842,39 @@
"type": "integer",
"default": 10
}
},
{
"name": "beta",
"in": "query",
"required": false,
"description": "When `true`, switches Chartmetric to its improved beta search engine — recommended for ambiguous queries. Results come back sorted by `match_strength` (higher is better) and include `target`/`platform` fields instead of the default-mode shape.",
"schema": {
"type": "string",
"enum": [
"true",
"false"
]
}
},
{
"name": "platforms",
"in": "query",
"required": false,
"description": "Comma-separated platforms to include in beta results (e.g. `cm,spotify`). Only valid with `beta=true`; ignored otherwise.",
"schema": {
"type": "string",
"example": "cm,spotify"
}
},
{
"name": "offset",
"in": "query",
"required": false,
"description": "Pagination offset. Defaults to 0 when omitted.",
"schema": {
"type": "string",
"pattern": "^(0|[1-9][0-9]*)$"
}
}
],
"responses": {
Expand Down Expand Up @@ -880,15 +913,48 @@
},
"/api/research/albums": {
"get": {
"description": "Get an artist's full discography — albums, EPs, and singles with release dates.",
"description": "Get the album discography — albums, EPs, and singles with release dates — for a Chartmetric `artist_id`.\n\nThin proxy over Chartmetric's `/artist/:id/albums`. By default `is_primary=true`, so only albums where the artist is a main artist are returned — DJ compilations, soundtracks, and pure feature appearances are excluded. Pass `is_primary=false` to include them. Discover a Chartmetric `artist_id` via [GET /api/research](/api-reference/research/search) with `type=artists&beta=true`.",
"parameters": [
{
"name": "artist",
"name": "artist_id",
"in": "query",
"required": true,
"description": "Artist name or Recoup artist ID (UUID).",
"description": "Chartmetric artist ID (positive integer). Obtain via [GET /api/research](/api-reference/research/search) with `type=artists&beta=true` — the `id` field in each result is the Chartmetric ID to pass here.",
"schema": {
"type": "string"
"type": "string",
"pattern": "^[1-9][0-9]*$",
"example": "3380"
}
},
{
"name": "is_primary",
"in": "query",
"required": false,
"description": "When `true` (default), returns only albums where the artist is a main artist. Set to `false` to include feature appearances, DJ compilations, and soundtracks.",
"schema": {
"type": "string",
"enum": ["true", "false"],
"default": "true"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Number of albums to return. Defaults to Chartmetric's default (100) when omitted.",
"schema": {
"type": "string",
"pattern": "^[1-9][0-9]*$"
}
},
{
"name": "offset",
"in": "query",
"required": false,
"description": "Pagination offset. Defaults to 0 when omitted.",
"schema": {
"type": "string",
"pattern": "^(0|[1-9][0-9]*)$"
}
}
],
Expand All @@ -904,7 +970,7 @@
}
},
"400": {
"description": "Validation error (e.g., missing `artist` parameter)",
"description": "Validation error — `artist_id` missing or not a positive integer",
"content": {
"application/json": {
"schema": {
Expand Down Expand Up @@ -1187,7 +1253,7 @@
},
"/api/research/curator": {
"get": {
"description": "Get curator profile — name, image, follower counts across platforms, tag-based genre info, and Chartmetric playlist reach statistics. Requires a numeric Chartmetric curator ID (e.g. `2` for Spotify's own account). Use `GET /api/research/playlists` to discover curators via their playlists.",
"description": "Get curator profile — name, image, follower counts across platforms, tag-based genre info, and Chartmetric playlist reach statistics. Requires a numeric Chartmetric curator ID (e.g. `2` for Spotify's own account). Discover a Chartmetric curator ID via [GET /api/research](/api-reference/research/search) with `type=curators&beta=true`. You can also find curators indirectly by looking up their playlists via [GET /api/research/playlists](/api-reference/research/playlists).",
"parameters": [
{
"name": "platform",
Expand All @@ -1207,7 +1273,7 @@
"name": "id",
"in": "query",
"required": true,
"description": "Numeric Chartmetric curator ID (e.g. `2` for Spotify's own account). Non-numeric values will be rejected.",
"description": "Numeric Chartmetric curator ID (e.g. `2` for Spotify's own account). Non-numeric values will be rejected. Obtain via [GET /api/research](/api-reference/research/search) with `type=curators&beta=true`.",
"schema": {
"type": "string",
"pattern": "^[0-9]+$",
Expand Down Expand Up @@ -1883,7 +1949,7 @@
},
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
"/api/research/playlist": {
"get": {
"description": "Get playlist metadata — name, description, follower count, track count, and curator info.",
"description": "Get playlist metadata — name, description, follower count, track count, and curator info.\n\nThin proxy over Chartmetric's `/playlist/:platform/:id` detail lookup. **`id` is Chartmetric's own numeric playlist ID, not the streaming-platform's native ID.** Discover the Chartmetric playlist ID via [GET /api/research](/api-reference/research/search) with `type=playlists&beta=true` — the `id` field in each result is the Chartmetric ID to pass here.",
"parameters": [
{
"name": "platform",
Expand All @@ -1899,15 +1965,17 @@
"youtube"
]
},
"description": "Streaming platform."
"description": "Streaming platform the Chartmetric playlist is sourced from."
},
{
"name": "id",
"in": "query",
"required": true,
"description": "Playlist ID on the platform.",
"description": "Chartmetric playlist ID (positive integer). This is **not** the streaming platform's native ID — e.g. Spotify's base62 ID `37i9dQZF1DXcBWIGoYBM5M` for RapCaviar maps to Chartmetric ID `848051`. Obtain via [GET /api/research](/api-reference/research/search) with `type=playlists&beta=true`.",
"schema": {
"type": "string"
"type": "string",
"pattern": "^[1-9][0-9]*$",
"example": "848051"
}
}
],
Expand Down Expand Up @@ -2351,24 +2419,17 @@
},
"/api/research/track": {
"get": {
"description": "Get track metadata — title, artist, album, release date, popularity, and platform IDs.\n\nResolves `q` against Chartmetric's track search and returns details for the top-ranked match. Common track names are ambiguous (e.g. \"Flowers\", \"God's Plan\") — for reliable disambiguation, either pass a Spotify track URL as `q`, or pair `q` with the `artist` query param.",
"description": "Get full Chartmetric track metadata by numeric track `id` — title, artists, albums, release date, genres, popularity, and platform IDs.\n\nThis endpoint is a thin proxy over Chartmetric's `/track/:id` detail lookup. Discover a Chartmetric track ID via [GET /api/research](/api-reference/research/search) with `type=tracks&beta=true` — pick a result's `id`, then call this endpoint. Keeping the two concerns separate means predictable credit charging and no silent wrong-match behavior for ambiguous queries.",
"parameters": [
{
"name": "q",
"name": "id",
"in": "query",
"required": true,
"description": "Track name or Spotify track URL. URLs (e.g. `https://open.spotify.com/track/<id>`) resolve directly without ambiguity. Plain names are searched via Chartmetric's track search; results may not match user intent without an `artist` filter.",
"schema": {
"type": "string"
}
},
{
"name": "artist",
"in": "query",
"required": false,
"description": "Optional artist name used to disambiguate when `q` is a plain track name. Matched case-insensitively against the candidate tracks' artist names; the top-ranked candidate whose artist names contain this value wins. Recommended whenever `q` is not a Spotify URL.",
"description": "Chartmetric track ID (positive integer). Obtain via [GET /api/research](/api-reference/research/search) with `type=tracks&beta=true` — beta-ranked search results include the `id` field directly.",
"schema": {
"type": "string"
"type": "string",
"pattern": "^[1-9][0-9]*$",
"example": "15194376"
}
}
],
Expand All @@ -2384,7 +2445,7 @@
}
},
"400": {
"description": "Validation error",
"description": "Validation error — `id` missing or not a positive integer",
"content": {
"application/json": {
"schema": {
Expand All @@ -2404,7 +2465,7 @@
}
},
"404": {
"description": "No track matched the supplied `q` (and `artist`, when present)",
"description": "No Chartmetric track exists with the supplied `id`",
"content": {
"application/json": {
"schema": {
Expand Down Expand Up @@ -2609,12 +2670,12 @@
},
"/api/research/track/playlists": {
"get": {
"description": "Returns playlists featuring a specific track. Accepts a Chartmetric track ID (`id`) or a track name + optional artist (`q`, `artist`) for a Spotify-powered lookup. When no filter flag is passed, defaults to editorial + indie + majorCurator + popularIndie = `true`. Costs 5 credits per request.",
"description": "Returns playlists featuring a specific track. Accepts a Chartmetric track ID (`id`) or a track name + optional artist (`q`, `artist`) for a Spotify-powered lookup. When no filter flag is passed, defaults to editorial + indie + majorCurator + popularIndie = `true`. Costs 5 credits per request.\n\nDiscover a Chartmetric track `id` via [GET /api/research](/api-reference/research/search) with `type=tracks&beta=true` — then pass the resulting `id` here for the most reliable match (avoids the ambiguity of name-based lookup).",
"parameters": [
{
"name": "id",
"in": "query",
"description": "Chartmetric track ID. Required if `q` is not provided.",
"description": "Chartmetric track ID. Required if `q` is not provided. Obtain via [GET /api/research](/api-reference/research/search) with `type=tracks&beta=true`.",
"schema": {
"type": "string"
}
Expand Down Expand Up @@ -4642,17 +4703,49 @@
},
"ResearchSearchResult": {
"type": "object",
"description": "Shape varies by `type` and search engine. Common fields are listed here; `additionalProperties: true` lets engine-specific fields pass through.\n\n**Default engine (`beta=false`):** entries include `name`, `id`, `image_url`, plus type-specific fields like `artist_names[]` (tracks), `isrc` (tracks), `sp_followers`/`sp_monthly_listeners`/`cm_artist_score` (artists), `owner_name` (playlists), etc.\n\n**Beta engine (`beta=true`):** entries include `name`, `id`, `imageUrl`, `target` (the entity type — e.g. `track`, `artist`, `playlist`), `platform` (e.g. `cm`, `spotify`), and `match_strength` (numeric relevance score, higher is better).",
"properties": {
"name": {
"type": "string"
},
"id": {
"type": "integer",
"description": "Internal ID for use with other research endpoints."
"description": "Chartmetric internal ID for use with the detail-lookup endpoints (`/api/research/track`, `/api/research/playlist`, `/api/research/albums`, etc.). Usually an integer; some playlist sources return a string.",
"oneOf": [
{ "type": "integer" },
{ "type": "string" }
]
},
"image_url": {
"type": "string",
"nullable": true,
"description": "Default-engine image URL. (Beta engine returns `imageUrl` instead.)"
},
"imageUrl": {
"type": "string",
"nullable": true,
"description": "Beta-engine image URL. (Default engine returns `image_url` instead.)"
},
"match_strength": {
"type": "number",
"description": "Beta-only relevance score — sort entries by this descending. Not present in default-engine results."
},
"target": {
"type": "string",
"description": "Beta-only entity type (`track`, `artist`, `playlist`, etc.). Not present in default-engine results."
},
"platform": {
"type": "string",
"description": "Beta-only source platform (e.g. `cm`, `spotify`). Not present in default-engine results."
},
"spotify_id": {
"type": "string",
"nullable": true
},
"artist_names": {
"type": "array",
"nullable": true,
"items": { "type": "string" },
"description": "Default-engine tracks only."
}
},
"additionalProperties": true
Expand Down