soundlinks:read. Use a soundlinkId from Syncing soundlinks.
Soundlink metrics omit spend, fees, and efficiency fields (cpl, cpf) — ads run in your Meta account.
startDate and endDate are inclusive (YYYY-MM-DD).
- Overview and paginated breakdown: default to the soundlink creation date → today (no 90-day cap).
- Retention: filters by cohort date. If you omit both dates, a recent window ending today is used. A range that is too wide returns
400 invalid_query_parameter. - Weekly retention: filters by cohort week, with the same default window and the same
400when the range is too wide. - Engagement (paginated + export) and breakdown export: default to the last 90 days ending today; responses are capped at 90 days per request. Page longer histories in 90-day slices. See JSONL exports.
Overview
GET /v1/soundlinks/{soundlinkId}/metrics/overview
Soundlink-level totals for a date range: views, link_clicks (nullable), streams, listeners, followers, streams_per_listener, and ctr_lp. One payload per request window — not broken down by country or track.
link_clicks counts CTA clicks across all DSPs on the landing page. It is null when this soundlink type does not track them.
listeners is the sum of daily per-country new_listeners (not period-unique across days or countries). It is not equal to summing breakdown listeners (new + returning).
New and returning splits are not on overview. Use breakdown or engagement rows for new_listeners, returning_listeners, and the stream splits.
Breakdown (by country)
GET /v1/soundlinks/{soundlinkId}/metrics/breakdown (paginated)
GET /v1/soundlinks/{soundlinkId}/metrics/breakdown/export (JSONL)
Per-day, per-country rows (soundlink_country_daily v1.0). Primary key:
(provider, account_id, report_date, soundlink_id, country_code)
On track soundlinks (soundlink_target_type = track), each row also includes soundlink_target_isrc and soundlink_target_spotify_track_id.
Each row includes spotify_link_clicks, apple_music_link_clicks, and youtube_music_link_clicks. link_clicks is the all-DSP total and is always greater than or equal to their sum — do not derive a DSP count by subtraction. Apple Music and YouTube Music are outbound clicks only (no playback attribution). YouTube Music is often 0 on standalone soundlinks.
Maps to the Countries tab in Soundlink Insights. Use for geo reporting and daily warehouse loads by territory. Summing country rows for a given report_date reconstructs the day total across territories.
Engagement (by track)
GET /v1/soundlinks/{soundlinkId}/metrics/engagement (paginated)
GET /v1/soundlinks/{soundlinkId}/metrics/engagement/export (JSONL)
Per-day, per-track rows (soundlink_engagement_daily v1.0). Primary key:
(provider, account_id, report_date, soundlink_id, engagement_context, country_code, engaged_spotify_track_id)
Key difference from breakdown: breakdown aggregates views, streams, and listeners by country; engagement breaks down which tracks listeners played, including catalog spillover and playlist slot performance (engagement_context, engaged_spotify_track_id).
engagement_context values:
catalog— same-artist spillover and direct plays on track soundlinksplaylist— per-track performance inside the promoted playlist
?engagementContext=catalog or playlist when you only need one slice.
Playlist engagement rows include playlist_position when available — the track’s 1-based slot on the soundlink playlist for that report_date.
Retention (by cohort)
GET /v1/soundlinks/{soundlinkId}/metrics/retention
One row per cohort date (soundlink_cohort_retention_daily v1.0). Primary key:
(provider, account_id, cohort_date, soundlink_id)
The cohort date is the UTC date a listener first played through the soundlink. Each listener belongs to one cohort: their earliest first play across all countries. Dates with no first plays have no row. All rows come back in one response, with no pagination.
A day-N value is
null until day N has passed for that cohort date. It is final after that.
retention_by_day_N never decreases within a row, because each listener counts once. It can’t tell you whether day-3 returners also played on day 2. Use returned_on_day_N for day-by-day behavior.
soundlink_target_isrc is currently always null.
Weekly retention (by cohort week)
GET /v1/soundlinks/{soundlinkId}/metrics/retention-weekly
One item per cohort week. The week is anchored on the soundlink creation date in UTC, not on a calendar Monday. Each listener has one acquisition country: the country of their earliest first play.
The response uses granularity week and scope attributed. All items come back in one response, with no pagination. Items do not repeat soundlink target fields. Use the soundlink detail for that.
startDate and endDate filter cohort_week (inclusive). If you omit both, a recent window ending today is used. A range that is too wide returns 400 invalid_query_parameter.
Omit groupBy for one item per cohort week. country_code is null. Counts are summed across countries, and pct is active_users / cohort_size after that sum. groupBy=country returns one item per cohort week and country (XX when the country is unknown). There is no filter for a single country.
A day or week is included only after every listener in that cohort week has aged past it, so a young cohort has a shorter array. Cells stop at week 26.
Data mutability
Rows for a givenreport_date can change for up to 7 days after the date closes (delayed Spotify events). Re-fetch and re-ingest on the primary key — it is idempotent.
Listeners vs streams
On breakdown and engagement rows, do not sumlisteners across days — the same listener can appear on multiple report_date rows. Summing streams within a day is safe; across days it counts repeat listens.
Typical sync flow
- Daily: list soundlinks — upsert catalog
- Daily: overview and/or breakdown (paginated or export)
- Optional: engagement (paginated or export) for track-level spillover
- Optional: retention, or weekly retention
account_id for the same organization UUID that catalog JSON calls organizationId. Join on soundlink_id.
FAQ
Where are new / returning listeners? Onbreakdown and engagement rows (new_listeners, returning_listeners, and the stream splits). Overview only exposes aggregated listeners (sum of daily per-country new_listeners).
How do I get one row per day without country? Sum that day’s breakdown rows across country_code, or store the country rows and aggregate in your warehouse.
Listening insights
GET /v1/soundlinks/{soundlinkId}/listening-insights/{insight}
Same three questions as campaign listening insights, for a soundlink the organization owns. A soundlink created for a campaign is allowed here even when it is absent from GET /v1/soundlinks/{soundlinkId}. Requires soundlinks:read. Use a client timeout of at least 120 seconds.
See Listening insights.