From spotify-ads-api
Apply batch operations to Spotify Ads API entities: pause/resume ad sets, update budgets, toggle delivery, swap creatives, archive campaigns/ad sets/ads.
How this skill is triggered — by the user, by Claude, or both
Slash command
/spotify-ads-api:bulk pause | resume | budget | delivery | archive | creativepause | resume | budget | delivery | archive | creativeThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Apply batch changes to multiple entities in a single workflow. All operations follow the same pattern: list entities, select targets, confirm changes, apply sequentially.
Apply batch changes to multiple entities in a single workflow. All operations follow the same pattern: list entities, select targets, confirm changes, apply sequentially.
access_token, ad_account_id, and auto_execute from the active platform settings file:
.codex/spotify-ads-api.local.md, then fall back to .claude/spotify-ads-api.local.md, then .gemini/spotify-ads-api.local.md..claude/spotify-ads-api.local.md, then fall back to .codex/spotify-ads-api.local.md, then .gemini/spotify-ads-api.local.md..gemini/spotify-ads-api.local.md, then fall back to .claude/spotify-ads-api.local.md, then .codex/spotify-ads-api.local.md.https://api-partner.spotify.com/ads/v3/spotify-ads-api:configure on Claude/Codex, /configure on Gemini).version: .codex-plugin/plugin.json on Codex, .claude-plugin/plugin.json on Claude, or gemini-extension.json (extension root) on Gemini.SDK_PRODUCT to codex-plugin on Codex, claude-code-plugin on Claude, or gemini-cli-extension on Gemini. Set SDK_HEADER="X-Spotify-Ads-Sdk: $SDK_PRODUCT/$PLUGIN_VERSION" and include -H "$SDK_HEADER" on all API requests.Parse the user's argument to determine the operation:
pause — Pause multiple active ad sets or campaignsresume — Resume paused ad sets or campaignsbudget — Update budgets across selected ad setsdelivery — Toggle ad delivery ON/OFFarchive — Archive multiple entitiescreative — Swap creative assets across adsAll operations optionally accept a campaign filter: pause --campaign <campaign_id> narrows the entity list to a specific campaign.
All operations follow this pattern:
Fetch entities matching the operation's criteria. Present as a numbered table:
Active Ad Sets (5 found):
| # | ID | Name | Campaign | Budget | Format |
|---|----|------|----------|--------|--------|
| 1 | abc... | US 18-34 Audio | Summer Promo | $75/day | AUDIO |
| 2 | def... | US 25-54 Video | Summer Promo | $50/day | VIDEO |
| 3 | ghi... | UK All Audio | Q2 Brand | $100/day | AUDIO |
| 4 | jkl... | CA 18-44 Audio | Q2 Brand | $60/day | AUDIO |
| 5 | mno... | US All Display | Podcast Launch | $40/day | IMAGE |
Ask the user to select entities. Support these selection formats:
1, 3, 51-3all1-3, 5Show a summary of what will change. For budget operations, show before/after values. For status changes, show entity names and the target state.
Execute PATCH requests one at a time. Report success or failure for each entity. Continue on partial failure — do not stop the batch if one entity fails.
Display a final summary table:
Bulk Pause Results:
| Ad Set | Status | Result |
|--------|--------|--------|
| US 18-34 Audio | PAUSED | Success |
| UK All Audio | PAUSED | Success |
| US All Display | — | Failed: 403 Forbidden |
2/3 operations succeeded.
pausePause multiple active ad sets or campaigns.
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets?statuses=ACTIVE&limit=50&sort_direction=DESC"
To filter by campaign: add &campaign_ids=$CAMPAIGN_ID.
To pause campaigns instead of ad sets, ask the user first, then:
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/campaigns?statuses=ACTIVE&limit=50&sort_direction=DESC"
For each selected ad set:
curl -s -w "\nHTTP_STATUS:%{http_code}" -X PATCH -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"status":"PAUSED"}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets/$AD_SET_ID"
For campaigns, use the campaigns endpoint instead.
Skip entities that are already PAUSED — note them as "Already paused, skipped" in the results.
resumeResume paused ad sets or campaigns.
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets?statuses=PAUSED&limit=50&sort_direction=DESC"
For each selected ad set:
curl -s -w "\nHTTP_STATUS:%{http_code}" -X PATCH -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"status":"ACTIVE"}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets/$AD_SET_ID"
budgetUpdate budgets across multiple ad sets.
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets?limit=50&sort_direction=DESC"
Present the table with current budget amounts (convert micro_amount ÷ 1,000,000 to dollars) and budget type (DAILY/LIFETIME).
After selection, ask how to change the budget:
Budget changes (+20%):
| Ad Set | Budget Type | Current | New |
|--------|-------------|---------|-----|
| US 18-34 Audio | DAILY | $75.00 | $90.00 |
| UK All Audio | DAILY | $100.00 | $120.00 |
Proceed with these changes?
For each selected ad set:
curl -s -w "\nHTTP_STATUS:%{http_code}" -X PATCH -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"budget":{"micro_amount":<NEW_MICRO_AMOUNT>,"type":"<DAILY|LIFETIME>"}}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets/$AD_SET_ID"
Always convert dollar amounts to micro-amounts by multiplying by 1,000,000.
deliveryToggle ad delivery ON or OFF across multiple ads.
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ads?limit=50&sort_direction=DESC"
To filter by campaign or ad set: add &campaign_ids=$CAMPAIGN_ID or &ad_set_ids=$AD_SET_ID.
Present the table showing current delivery status (ON/OFF), ad name, ad set name, and status.
Ask the user: toggle all selected to ON, or toggle all to OFF?
For each selected ad:
curl -s -w "\nHTTP_STATUS:%{http_code}" -X PATCH -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"delivery":"ON"}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ads/$AD_ID"
Skip ads already in the target delivery state.
archiveArchive multiple entities. This is effectively permanent — there is no unarchive for campaigns, ad sets, or ads.
Ask the user: "What do you want to archive — campaigns, ad sets, or ads?"
Fetch non-archived entities of the selected type:
# For ad sets:
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets?statuses=ACTIVE&statuses=PAUSED&limit=50&sort_direction=DESC"
Before applying, warn: "Archiving is effectively permanent. Archived entities cannot be reactivated. Are you sure?"
For each selected entity:
curl -s -w "\nHTTP_STATUS:%{http_code}" -X PATCH -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"status":"ARCHIVED"}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets/$AD_SET_ID"
creativeSwap creative assets across multiple ads.
Important: The PATCH /ads/{id} endpoint does not support updating asset fields. To swap creative, this operation must:
This means creative swaps produce new ad IDs, new approval cycles, and reset delivery metrics. Warn the user about this before proceeding. Also preserve third-party tracking exactly from the original ad unless the user explicitly asks to remove or change tracking.
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ads?limit=50&sort_direction=DESC"
Present table showing ad name, current asset, ad set, delivery status.
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets?statuses=READY&limit=50&sort_direction=DESC"
Present table of available assets filtered to READY status.
Ask the user to select which ads to update and which new asset to use. The new asset must match the ad set's asset_format (AUDIO, VIDEO, or IMAGE).
Read the existing ad:
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ads/$AD_ID"
Create the replacement ad with the same fields but new asset_id:
curl -s -w "\nHTTP_STATUS:%{http_code}" -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{
"name": "<same_name>",
"ad_set_id": "<same_ad_set_id>",
"tagline": "<same_tagline>",
"advertiser_name": "<same_advertiser_name>",
"assets": {
"asset_id": "<NEW_ASSET_ID>",
"logo_asset_id": "<same_logo>",
"companion_asset_id": "<same_companion>"
},
"call_to_action": {
"key": "<same_key>",
"clickthrough_url": "<same_url>"
},
"third_party_tracking": <same_third_party_tracking_if_present>,
"delivery": "<same_delivery>"
}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ads"
Only include third_party_tracking when it exists on the source ad. If tracking cannot be copied, ask the user before archiving the original ad.
Archive the old ad:
curl -s -w "\nHTTP_STATUS:%{http_code}" -X PATCH -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"status":"ARCHIVED"}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ads/$OLD_AD_ID"
Creative Swap Results:
| Original Ad | New Ad ID | Asset | Result |
|-------------|-----------|-------|--------|
| 30s Spot A (abc...) | def... | new-audio.mp3 | Success |
| 30s Spot B (ghi...) | jkl... | new-audio.mp3 | Success |
2/2 swaps completed. Old ads archived. New ads are in PENDING approval status.
auto_execute is true, execute after the user confirms the change summary. The listing and selection steps always require user interaction regardless of auto_execute.auto_execute is false, present each curl command and ask for confirmation before executing.HTTP_STATUS: line from curl output to determine success or failure before interpreting the response body.--campaign <id>) to narrow results./spotify-ads-api:dashboard./spotify-ads-api:campaigns update or /spotify-ads-api:ads ad-sets update./spotify-ads-api:assets list.npx claudepluginhub spotify/ads-agentic-tools --plugin spotify-ads-apiManages Spotify Ads API ad sets and ads — list, create, get, or update. Useful for programmatic ad campaign management via curl.
Executes AdCP Media Buy Protocol operations: discover ad products, create/manage campaigns, sync creatives, and track delivery. Use when buying advertising or testing ad APIs.
Manages ad campaigns across Google Ads, Meta Ads, LinkedIn Ads, and TikTok Ads via Adspirer MCP server. Analyzes performance, researches keywords, creates campaigns, optimizes budgets.