Skip to main content
POST /v1/soundlinks creates a soundlink that is not tied to a Soundlink-funded campaign. Requires the soundlinks:write scope and a Self-Serve plan.
This does not create a campaign and does not appear on GET /v1/campaigns. Ads run in your own Meta account. On create, the Idempotency-Key header is required.

Prerequisites

  • An API key with the soundlinks:write scope — see Authentication
  • A Self-Serve plan on your organization
  • A Spotify track or playlist URL that exists on Spotify
Expected (201). data is the same shape as soundlink detail:
The soundlink is active immediately. Use data.url as the public landing page.

Request fields

Spotify URLs

spotifyUrl must be https://open.spotify.com/track/{id} or https://open.spotify.com/playlist/{id}. Locale prefixes (/intl-pt/...) and query strings (?si=...) are accepted. Album, artist, spotify: URIs, and a track or playlist that does not exist on Spotify return 422 invalid_spotify_url.

Apple Music URLs

Optional appleMusicUrl adds an Apple Music button on the landing page. Songs and catalog playlists are checked in that storefront. Missing content returns 400 invalid_request. If Apple is unavailable, create still succeeds. Library playlists (pl.u-) are format-checked only. Send an https://music.apple.com URL with a two-letter storefront:
  • Song: /song/{slug}/{id}
  • Catalog playlist: playlist id starts with pl.
  • Library playlist: playlist id starts with pl.u-
  • Album share sheet that includes ?i={songId}. This is stored and returned as the canonical song URL (/song/{slug}/{songId})
The 201 body and later GETs return appleMusicUrl as https://music.apple.com/us/song/take-on-me/1035048414. Omit the field and detail returns appleMusicUrl: null. A plain album link (no ?i=), an artist link, http, or any other host returns 400 invalid_request.

YouTube Music URLs

Optional youtubeMusicUrl adds a YouTube Music button on the landing page. A song or playlist that does not exist on YouTube returns 400 invalid_request. If YouTube is unavailable, create still succeeds. Send a song or playlist URL:
  • Song: music.youtube.com/watch?v={id}, youtube.com/watch?v={id}, or youtu.be/{id}
  • Playlist: music.youtube.com/playlist?list={id}
The 201 body and later GETs return youtubeMusicUrl as https://music.youtube.com/watch?v=dQw4w9WgXcQ. Omit the field and detail returns youtubeMusicUrl: null. Shorts, live, channel, and browse links, http, or any other host return 400 invalid_request.

Meta pixel

Attach a Meta pixel in one of two ways:
  • Save or rotate — send metaPixelId and metaConversionAccessToken together.
  • Reuse a saved pixel — send metaPixelId alone for a pixel your organization already stored via Managing pixels.
Token without ID, or an ID your organization does not own, returns 400 invalid_request. Omit both to skip Meta tracking. Create never applies an organization default.
Reuse only:
GET returns metaPixelId when set. The CAPI token is never returned. Send streamValueEventEnabled: true to turn on Soundlink Stream Value for that soundlink. Your organization must already be enabled for it. Otherwise the request returns 403 stream_value_not_enabled. true cannot be combined with attributionEnabled: false. That returns 400 invalid_request. You can set this only when you create the soundlink. Omit the field or send false to leave it off. Events are sent only when the soundlink has a Meta pixel and conversion access token. Detail returns streamValueEventEnabled. List items do not.

Idempotency

The Idempotency-Key header is required on POST /v1/soundlinks.
  • Any unique string up to 255 characters — a UUID or <action>-<date>-<ref> pattern works well
  • Keys are honored for 24 hours
  • Retrying with the same key and same body replays the original 201 — it does not create a second soundlink
  • Reusing a key with a different body returns 409 idempotency_key_conflict
  • If a concurrent request with the same key is still processing, you also get 409 — retry shortly
When a request times out or you never saw the response, retry with the same key. When a request failed with a definitive error (for example 422 invalid_spotify_url) and you have fixed the cause, send the retry as a new request with a new key.

Errors

See Errors for the full list. DELETE /v1/soundlinks/{soundlinkId} — same as Archive in the app. Requires soundlinks:write. No Idempotency-Key.
Expected (200). data.status is archived. The public landing page returns 404 after cache expires. List and detail still return the row. A second delete, unknown id, other org, campaign-linked id, or a soundlink that is not active returns 404 not_found. This cannot be undone via the API.

Send a test event

POST /v1/soundlinks/{soundlinkId}/test-events sends the same test conversion as Send test event in the app. Requires soundlinks:write. No request body and no Idempotency-Key. Pixels and tokens already stored on the soundlink are used. A Meta pixel sends a live Soundlink Stream event. A TikTok pixel sends a live ViewContent event. These are not sandbox events.
Expected (200). data.status is sent. A soundlink with neither pixel, or a pixel missing its conversion token, returns 400 invalid_request. Unknown ids, another organization, and campaign-linked soundlinks return 404. Archived self-serve soundlinks are allowed.

Next

Syncing soundlinks — list and detail · Soundlink metrics · API Reference