| name | assets |
| description | Upload, list, and manage Spotify Ads API creative assets — audio, video, and images for ad campaigns. |
| argument-hint | upload <file_path> | list [audio|video|image] | get <asset_id> | archive <asset_id> |
| allowed-tools | ["Read","Bash","AskUserQuestion"] |
Spotify Ads API — Asset Management
Upload, list, retrieve, and archive creative assets (audio, video, images) for use in ads.
Setup
- Read
access_token, ad_account_id, and auto_execute from the active platform settings file:
- Codex: prefer
.codex/spotify-ads-api.local.md, then fall back to .claude/spotify-ads-api.local.md, then .gemini/spotify-ads-api.local.md.
- Claude: prefer
.claude/spotify-ads-api.local.md, then fall back to .codex/spotify-ads-api.local.md, then .gemini/spotify-ads-api.local.md.
- Gemini: prefer
.gemini/spotify-ads-api.local.md, then fall back to .claude/spotify-ads-api.local.md, then .codex/spotify-ads-api.local.md.
- Base URL:
https://api-partner.spotify.com/ads/v3
- If no settings file exists, instruct the user to run the configure skill first (
/spotify-ads-api:configure on Claude/Codex, /configure on Gemini).
- Read the active platform manifest for the plugin
version: .codex-plugin/plugin.json on Codex, .claude-plugin/plugin.json on Claude, or gemini-extension.json (extension root) on Gemini.
- Set
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.
Parsing Arguments
The argument format is: <operation> [arg]
upload <file_path> — Upload a new asset
list [audio|video|image] — List assets, optionally filtered by type
get <asset_id> — Get details of a specific asset
archive <asset_id> — Archive an asset
unarchive <asset_id> — Unarchive an asset
- If no argument, ask which operation.
Operations
upload <file_path>
Two-step process following the API's required flow.
Step 1: Detect asset type from file extension
| Extensions | Asset Type |
|---|
.mp3, .wav, .ogg | AUDIO |
.mp4, .mov | VIDEO |
.png, .jpg, .jpeg | IMAGE |
If the extension doesn't match any of these, ask the user to specify the asset type.
Step 2: Prompt for name
Use AskUserQuestion to ask for the asset name (2-120 characters). Default to the filename without extension.
Step 3: Create asset metadata
curl -s -w "\nHTTP_STATUS:%{http_code}" -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"asset_type":"AUDIO","name":"my-creative"}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets"
Extract id from the response.
Step 4: Upload the file
First, check the file size:
stat -f%z "/path/to/file"
If file is <= 20MB — Simple upload:
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-F "media=@/path/to/file" \
-F "asset_type=AUDIO" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets/$ASSET_ID/upload"
If file is > 20MB — Chunked upload:
- Start the chunked upload session:
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets/$ASSET_ID/chunked_upload/start"
Extract upload_session_id and max_chunk_size_mb from the response.
- Split the file into chunks:
split -b ${MAX_CHUNK_SIZE_MB}m /path/to/file /tmp/chunk_
- Upload each chunk (numbered starting from 1):
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-F "media=@/tmp/chunk_aa" \
-F "upload_section=1" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets/$ASSET_ID/chunked_upload/transfer"
- Complete the chunked upload:
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"upload_session_id":"<session_id>","number_of_sections":<total_chunks>}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets/$ASSET_ID/chunked_upload/complete"
- Clean up temp chunks:
rm /tmp/chunk_*
Step 5: Poll for processing status
After upload, poll GET /assets/{id} until status changes from PROCESSING to READY or REJECTED. Poll every 3 seconds, max 60 seconds.
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets/$ASSET_ID"
Check the status field in the response. If still PROCESSING, wait 3 seconds and retry.
Step 6: Display result
Show the final asset details:
- Asset ID — the UUID
- Name — the asset name
- Type — AUDIO, VIDEO, or IMAGE
- Status — READY, PROCESSING, or REJECTED
- URL — if available (when status is READY)
- Duration — for audio/video assets
- Dimensions — for image/video assets
- Aspect ratio — for video/image assets
If the asset was REJECTED, explain that the file may not meet format requirements and suggest checking the supported formats section below.
list [audio|video|image]
List assets in the account, optionally filtered by type.
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets?asset_types=AUDIO&limit=50&sort_direction=DESC"
If no type filter is provided, omit the asset_types parameter to list all assets.
Format as table:
| ID | Name | Type | Status | Duration/Dimensions | Created |
|---|
- For audio assets: show duration
- For video assets: show duration and dimensions
- For image assets: show dimensions
- Filter out archived assets unless the user specifically asks for them
If continuation_token is present in the response, note that more assets exist.
get <asset_id>
Get full details of a specific asset.
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets/$ASSET_ID"
Display all fields in readable format:
- For audio: show name, type, status, duration, URL
- For video: show name, type, status, duration, aspect ratio, dimensions, has_audio, URL
- For image: show name, type, status, dimensions, aspect ratio, URL
archive <asset_id> / unarchive <asset_id>
Archive or unarchive an asset using the bulk action endpoint.
curl -s -w "\nHTTP_STATUS:%{http_code}" -X PATCH -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"action":"ARCHIVE","ids":["<asset_id>"]}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets"
For unarchive, use "action":"UNARCHIVE".
Confirm the action completed by displaying the updated asset status.
Supported Formats
| Type | Formats | Recommendations |
|---|
| Audio | MP3, WAV, OGG | 128kbps+, 44.1kHz+ sample rate |
| Video | MP4, MOV | Aspect ratios: 16:9, 1.91:1, 1:1, 9:16 |
| Image | PNG, JPEG | — |
- Max file size (simple upload): 20MB
- Asset naming: 2-120 characters
Execution Behavior
- If
auto_execute is true, execute each API call directly.
- If
auto_execute is false, present the curl command and ask for confirmation before executing.
- Display responses in readable format.
- On error, show the error message from the response body.