diff --git a/api-reference/openapi/research.json b/api-reference/openapi/research.json index c1a327d..7b2b730 100644 --- a/api-reference/openapi/research.json +++ b/api-reference/openapi/research.json @@ -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" } @@ -819,7 +819,7 @@ "name": "type", "in": "query", "required": false, - "description": "Entity type.", + "description": "Entity type to search.", "schema": { "type": "string", "enum": [ @@ -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": { @@ -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]*)$" } } ], @@ -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": { @@ -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", @@ -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]+$", @@ -1883,7 +1949,7 @@ }, "/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", @@ -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" } } ], @@ -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/`) 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" } } ], @@ -2384,7 +2445,7 @@ } }, "400": { - "description": "Validation error", + "description": "Validation error — `id` missing or not a positive integer", "content": { "application/json": { "schema": { @@ -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": { @@ -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" } @@ -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