RecommendationsResponse
Spotify-shaped recommendations: blend up to 5 seed tracks and return the nearest catalogue tracks by audio-feature similarity. Drop-in for the removed Spotify GET /v1/recommendations — FreqBlog catalog ids, open-data ranking.
Properties
| Name | Type | Description |
|---|---|---|
| seeds | array | Echo of the supplied seeds with a found/unfound flag. |
| seed_query | object | When seeded by name (`track`/`artist`) instead of an id, the catalogue track that name resolved to — so you can confirm the right track was picked. Null when seeding by `seed_tracks`. |
| count | integer | Number of recommended tracks returned (≤ `limit`). |
| tracks | array | Recommended tracks ordered by genre-aware relevance to the seed blend (each `track` carries its catalogue `genre`). `score` is the raw audio-feature cosine similarity (genre affinity influences orderi |
| filters | object | Present only when you supplied `min_`/`max_`/`target_` tunables. Confirms which ones took effect and what they cost — check it before concluding the catalogue is thin. |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/freqblog-com/json-schema/freqblog-com-recommendations-response-schema.json",
"title": "RecommendationsResponse",
"description": "Spotify-shaped recommendations: blend up to 5 seed tracks and return the\nnearest catalogue tracks by audio-feature similarity. Drop-in for the removed\nSpotify GET /v1/recommendations — FreqBlog catalog ids, open-data ranking.",
"x-generated": "2026-10-30",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/freqblog-com-openapi.json#/components/schemas/RecommendationsResponse",
"properties": {
"seeds": {
"items": {
"$ref": "#/$defs/RecommendationSeed"
},
"type": "array",
"title": "Seeds",
"description": "Echo of the supplied seeds with a found/unfound flag."
},
"seed_query": {
"anyOf": [
{
"$ref": "#/$defs/TrackStub"
},
{
"type": "null"
}
],
"description": "When seeded by name (`track`/`artist`) instead of an id, the catalogue track that name resolved to — so you can confirm the right track was picked. Null when seeding by `seed_tracks`."
},
"count": {
"type": "integer",
"title": "Count",
"description": "Number of recommended tracks returned (≤ `limit`)."
},
"tracks": {
"items": {
"$ref": "#/$defs/SimilarTrackResult"
},
"type": "array",
"title": "Tracks",
"description": "Recommended tracks ordered by genre-aware relevance to the seed blend (each `track` carries its catalogue `genre`). `score` is the raw audio-feature cosine similarity (genre affinity influences ordering, not the score), so it may not be strictly descending. With `cross_genre=strict` only same-genre-family tracks are returned."
},
"filters": {
"anyOf": [
{
"$ref": "#/$defs/RecommendationFiltersApplied"
},
{
"type": "null"
}
],
"description": "Present only when you supplied `min_`/`max_`/`target_` tunables. Confirms which ones took effect and what they cost — check it before concluding the catalogue is thin."
}
},
"type": "object",
"required": [
"seeds",
"count",
"tracks"
],
"$defs": {
"RecommendationFiltersApplied": {
"properties": {
"applied": {
"additionalProperties": {
"additionalProperties": {
"type": "number"
},
"type": "object"
},
"type": "object",
"title": "Applied",
"description": "The tunables we honoured, keyed by attribute — e.g. `{\"tempo\": {\"min\": 100, \"max\": 130}, \"energy\": {\"target\": 0.8}}`. An attribute you sent but don't see here was NOT applied."
},
"dropped_by": {
"additionalProperties": {
"type": "integer"
},
"type": "object",
"title": "Dropped By",
"description": "Per attribute, how many otherwise-rankable catalogue tracks its `min_`/`max_` bound removed. The largest entry is the bound to loosen first. Empty when only `target_` preferences were supplied (a target re-ranks, it never removes)."
},
"limit_reached": {
"type": "boolean",
"title": "Limit Reached",
"description": "False when the bounds exhausted the catalogue before `limit` tracks were found — i.e. a short `tracks` list is the FILTER's doing, not a lack of similar music. Loosen the bound with the biggest `dropped_by`.",
"default": true
}
},
"type": "object",
"required": [
"applied"
],
"title": "RecommendationFiltersApplied",
"description": "What the `min_`/`max_`/`target_` tunables actually did — so an over-tight filter\nis visible in the response instead of looking like a thin catalogue."
},
"RecommendationSeed": {
"properties": {
"id": {
"type": "string",
"title": "Id",
"description": "Seed track id as supplied."
},
"found": {
"type": "boolean",
"title": "Found",
"description": "True if the seed was usable (in catalog with enough audio features)."
}
},
"type": "object",
"required": [
"id",
"found"
],
"title": "RecommendationSeed"
},
"SimilarTrackResult": {
"properties": {
"track": {
"$ref": "#/$defs/TrackStub"
},
"genre_relation": {
"type": "string",
"title": "Genre Relation",
"description": "How this track's genre family relates to the seed's: `same`, `compatible` (a different but mixable family), `cross` (unrelated), or `unknown` (either side has no mapped genre, so no genre adjustment was applied). **Read this alongside `score`.** Under the default `cross_genre=auto` the ordering is by cosine PLUS a genre adjustment, so `score` alone does not explain the order — a `cross` pick is pushed down and appears only when too few same-family neighbours exist, which is why a lower-scoring `same` track can sit above a higher-scoring `cross` one. Filter on this to keep only the in-lane picks, or use `cross_genre=strict` to have the server do it.",
"default": "unknown"
},
"score": {
"type": "number",
"title": "Score",
"description": "Similarity in [-1, 1]; typically [0, 1] in practice, higher = closer. On `/similar` (since 2026-10-11) it is 0.8 × the PANNs audio-embedding cosine + 0.2 × the 18-feature cosine, so top results run lower than a raw cosine (about 0.7-0.97); on `/recommendations` it is the raw 18-feature cosine. Either way it is not the value results are ordered by unless `cross_genre=allow`; see `genre_relation`."
}
},
"type": "object",
"required": [
"track",
"score"
],
"title": "SimilarTrackResult"
},
"TrackStub": {
"properties": {
"itunes_track_id": {
"type": "string",
"title": "Itunes Track Id",
"description": "Track id (catalog `itunes_track_id` or synthetic prefix). Pass to `/track/{id}/embedding` or use the name+artist with `/lookup`."
},
"track_name": {
"type": "string",
"title": "Track Name"
},
"artist_name": {
"type": "string",
"title": "Artist Name"
},
"album_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Album Name"
},
"popularity": {
"type": "integer",
"title": "Popularity",
"description": "Internal catalogue ordering key — **not an audience or popularity metric**. It reflects how a track entered our catalogue, not how widely it is listened to, and is not comparable between tracks. Being redefined as a chart-position score; don't build on it.",
"default": 0
},
"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*. ⚠ This is NOT an audience-size measure and does not tell you monthly listeners; it is a chart placement and nothing more. 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. Distinct from `popularity`, which is an internal ordering key and not a metric."
},
"mbid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Mbid",
"description": "MusicBrainz Recording ID, when known."
},
"isrc": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Isrc",
"description": "ISRC, when known."
},
"genre": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Genre",
"description": "Broad genre classification, when known."
},
"release_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Release Date",
"description": "ISO 8601 release date, when known."
},
"duration_ms": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Duration Ms"
},
"explicit": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Explicit"
}
},
"type": "object",
"required": [
"itunes_track_id",
"track_name",
"artist_name"
],
"title": "TrackStub",
"description": "Minimal track shape for search and browse endpoints. No audio features.\nUse `/lookup` for full audio features once you have a track id."
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
curl "https://apis.io/api/v1/json-schemas/freqblog-com-recommendations-response"
curl "https://apis.io/api/v1/json-schemas?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.