Tap.co Developer API

Programmatic campaign management for advertisers.

The Tap.co Developer API allows you to discover advertising platforms, create and manage campaigns, upload creative assets, and track performance programmatically.

Authentication

The Tap API uses API keys to authenticate requests. You can view and manage your API keys in your dashboard.

Your API keys carry many privileges, so be sure to keep them secure. Do not share your secret API keys in publicly accessible areas.

Authentication is performed via the Authorization header with a Bearer token.

Base URL

https://sdk.tap.co/v1

Errors

Tap uses conventional HTTP response codes to indicate the success or failure of an API request.

2xxSuccess
4xxClient errors — the request contains bad syntax or cannot be fulfilled
5xxServer errors — the server failed to fulfill a valid request

Rate Limiting

The API enforces rate limits to ensure fair usage. If you exceed these limits, the API will return a 429 Too Many Requests response.

Per minute100 requests
Per hour1,000 requests

If you need to increase your rate limit, please contact us at support@tap.co.

Authenticated Request
curl https://sdk.tap.co/v1/campaigns \
-H "Authorization: Bearer tap_live_xxx"
Error Response
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Invalid API key provided"
}
}
API Keys
# Live mode
tap_live_xxxxxxxxxxxxxxxxxxxxxxxx
# Test mode
tap_test_xxxxxxxxxxxxxxxxxxxxxxxx

AI-generate a media plan

post/plans/generate

Uses AI to generate an optimized media plan based on your campaign goals, budget, and target audience. Returns a recommended mix of platforms with scheduling and budget allocation. The AI considers: - Your total budget and how to allocate it effectively - Target audience demographics and psychographics - Geographic targeting requirements - Campaign objectives (awareness, consideration, conversion) - Optimal media mix across channels - Timing and flight scheduling

Body parameters

budget_centsintegerrequired

Total campaign budget in cents (minimum $1,000)

currencystring
target_audienceobject
market_areasstring[]required

Geographic markets to target (cities, regions, or DMAs)

objectivesobject
campaign_datesobjectrequired
preferencesobject
business_contextobject

Returns

200Generated media plan
400Invalid request
401Invalid or missing API key
POST /plans/generate
curl -X POST https://sdk.tap.co/v1/plans/generate \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"budget_cents": 5000000,
"currency": "USD",
"target_audience": {
"age_range": "25-45",
"gender": "all",
"interests": [
"technology",
"fitness",
"travel"
],
"income_level": "middle-upper"
},
"market_areas": [
"Los Angeles, CA",
"San Francisco, CA"
],
"objectives": {
"primary": "brand_awareness",
"secondary": [
"consideration"
]
},
"campaign_dates": {
"start": "2026-03-01",
"end": "2026-03-31"
},
"preferences": {
"media_types": [
"radio",
"streaming",
"podcast"
],
"exclude_platforms": []
}
}'
Response
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"status": "generating",
"name": "Q1 2026 Brand Awareness - LA & SF Markets",
"summary": "string",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "KQED Radio",
"media_type": "radio",
"market_area": "San Francisco, CA",
"allocated_budget_cents": 750000,
"budget_percentage": 15,
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 425000,
"estimated_reach": 180000,
"cpm_cents": 1765,
"rationale": "Strong match with target demographic in SF metro area",
"audience_match_score": 0.87
}
],
"totals": {
"budget_cents": 5000000,
"estimated_impressions": 3250000,
"estimated_reach": 875000,
"estimated_frequency": 3.7,
"cpm_cents": 1538
},
"media_mix": {},
"schedule": {
"start_date": "2026-01-15",
"end_date": "2026-01-15",
"weeks": 0,
"flight_pattern": "continuous"
},
"rationale": "string",
"alternatives": [
{
"type": "string",
"description": "string",
"impact": "string"
}
],
"created_at": "2026-01-15T10:30:00Z",
"expires_at": "2026-01-15T10:30:00Z"
}

Get plan generation status

get/plans/generate/{jobId}

Retrieves the status of an asynchronous plan generation job. Poll this endpoint until `status` is `completed` or `failed`. The `plan` object is included when generation completes successfully.

Parameters

jobIdstringrequired

Returns

200Plan generation status
401Invalid or missing API key
404Resource not found
GET /plans/generate/{jobId}
curl https://sdk.tap.co/v1/plans/generate/:jobId \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"job_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"status": "pending",
"progress": 0,
"plan": {
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"status": "generating",
"name": "Q1 2026 Brand Awareness - LA & SF Markets",
"summary": "string",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "KQED Radio",
"media_type": "radio",
"market_area": "San Francisco, CA",
"allocated_budget_cents": 750000,
"budget_percentage": 15,
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 425000,
"estimated_reach": 180000,
"cpm_cents": 1765,
"rationale": "Strong match with target demographic in SF metro area",
"audience_match_score": 0.87
}
],
"totals": {
"budget_cents": 5000000,
"estimated_impressions": 3250000,
"estimated_reach": 875000,
"estimated_frequency": 3.7,
"cpm_cents": 1538
},
"media_mix": {},
"schedule": {
"start_date": "2026-01-15",
"end_date": "2026-01-15",
"weeks": 0,
"flight_pattern": "continuous"
},
"rationale": "string",
"alternatives": [
{
"type": "string",
"description": "string",
"impact": "string"
}
],
"created_at": "2026-01-15T10:30:00Z",
"expires_at": "2026-01-15T10:30:00Z"
},
"error": "string",
"created_at": "2026-01-15T10:30:00Z",
"completed_at": "2026-01-15T10:30:00Z"
}

Refine a generated plan

post/plans/generate/refine

Refines an existing plan based on natural language feedback or structured adjustments. Returns a new plan version with the requested changes applied. The original plan is preserved.

Body parameters

plan_idstringrequired

ID of the plan to refine

feedbackstring

Natural language feedback for the AI

adjustmentsobject

Returns

200Refined media plan
400Invalid request
401Invalid or missing API key
POST /plans/generate/refine
curl -X POST https://sdk.tap.co/v1/plans/generate/refine \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"plan_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"feedback": "Increase radio budget and reduce streaming. Focus more on morning drive time.",
"adjustments": {
"budget_cents": 0,
"add_platforms": [
"plan_8f2a9c4b1d3e5f6a7b8c9d0e"
],
"remove_platforms": [
"plan_8f2a9c4b1d3e5f6a7b8c9d0e"
],
"platform_budgets": {},
"media_type_weights": {},
"extend_dates": {
"start": "2026-01-15",
"end": "2026-01-15"
}
}
}'
Response
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"status": "generating",
"name": "Q1 2026 Brand Awareness - LA & SF Markets",
"summary": "string",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "KQED Radio",
"media_type": "radio",
"market_area": "San Francisco, CA",
"allocated_budget_cents": 750000,
"budget_percentage": 15,
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 425000,
"estimated_reach": 180000,
"cpm_cents": 1765,
"rationale": "Strong match with target demographic in SF metro area",
"audience_match_score": 0.87
}
],
"totals": {
"budget_cents": 5000000,
"estimated_impressions": 3250000,
"estimated_reach": 875000,
"estimated_frequency": 3.7,
"cpm_cents": 1538
},
"media_mix": {},
"schedule": {
"start_date": "2026-01-15",
"end_date": "2026-01-15",
"weeks": 0,
"flight_pattern": "continuous"
},
"rationale": "string",
"alternatives": [
{
"type": "string",
"description": "string",
"impact": "string"
}
],
"created_at": "2026-01-15T10:30:00Z",
"expires_at": "2026-01-15T10:30:00Z"
}

Convert generated plan to campaign

post/plans/generate/convert

Converts a generated plan into a campaign draft. The new campaign includes all platforms, dates, and configurations from the plan. Plans expire 24 hours after generation.

Body parameters

plan_idstringrequired

ID of the generated plan to convert

campaign_namestring

Optional name for the campaign (defaults to plan name)

advertiser_namestring

Advertiser/brand name

Returns

201Campaign created from plan
400Invalid request
401Invalid or missing API key
404Resource not found
POST /plans/generate/convert
curl -X POST https://sdk.tap.co/v1/plans/generate/convert \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"plan_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"campaign_name": "string",
"advertiser_name": "string"
}'
Response
{
"id": "camp_7d4e8f2a1b3c5d6e9f0a1b2c",
"tap_id": "TAP-2026-0042",
"status": "active",
"name": "Summer Sale 2026",
"advertiser_name": "Acme Corp",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "string",
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 0,
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
}
}
],
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
},
"estimated_impressions": 0,
"billing_schedule": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"amount_cents": 0,
"due_date": "2026-01-15",
"status": "pending",
"paid_at": "2026-01-15T10:30:00Z"
}
],
"notes": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z",
"activated_at": "2026-01-15T10:30:00Z"
}

List advertising platforms

get/platforms

Returns a paginated list of advertising platforms. Filter by `media_type`, `market_area`, or budget range. For natural language queries, use `POST /platforms/search` instead.

Parameters

limitinteger

Maximum number of items to return

cursorstring

Cursor for pagination (from previous response)

media_typestring

Filter by media type

Enum: "radio", "tv", "digital", "ooh", "streaming", "podcast", "print"
market_areastring

Filter by market area (city, region, or DMA)

budget_mininteger

Minimum budget in cents

budget_maxinteger

Maximum budget in cents

Returns

200List of platforms
401Invalid or missing API key
429Rate limit exceeded
GET /platforms
curl https://sdk.tap.co/v1/platforms \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"data": [
{
"id": "plat_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "KQED Radio",
"description": "Premier public radio station serving the San Francisco Bay Area",
"media_type": "radio",
"market_areas": [
"San Francisco, CA",
"Oakland, CA",
"San Jose, CA"
],
"audience": {
"demographics": {
"age_range": "25-54",
"gender_split": {
"male": 0.48,
"female": 0.52
},
"income_level": "middle-upper"
},
"reach": 125000,
"impressions": 450000
},
"pricing": {
"base_rate_cents": 1500,
"rate_type": "cpm",
"minimum_spend_cents": 250000,
"currency": "USD"
},
"creative_specs": {
"formats": [
{
"type": "image",
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"max_file_size_bytes": 0,
"accepted_formats": [
"string"
]
}
],
"guidelines": "string"
},
"availability_status": "available",
"created_at": "2026-01-15T10:30:00Z"
}
],
"meta": {
"has_more": false,
"next_cursor": "string"
}
}

Get platform details

get/platforms/{platformId}

Retrieves a platform's details including audience demographics, pricing, market areas, and creative specifications.

Parameters

platformIdstringrequired

Platform ID

Returns

200Platform details
401Invalid or missing API key
404Resource not found
GET /platforms/{platformId}
curl https://sdk.tap.co/v1/platforms/:platformId \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"id": "plat_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "KQED Radio",
"description": "Premier public radio station serving the San Francisco Bay Area",
"media_type": "radio",
"market_areas": [
"San Francisco, CA",
"Oakland, CA",
"San Jose, CA"
],
"audience": {
"demographics": {
"age_range": "25-54",
"gender_split": {
"male": 0.48,
"female": 0.52
},
"income_level": "middle-upper"
},
"reach": 125000,
"impressions": 450000
},
"pricing": {
"base_rate_cents": 1500,
"rate_type": "cpm",
"minimum_spend_cents": 250000,
"currency": "USD"
},
"creative_specs": {
"formats": [
{
"type": "image",
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"max_file_size_bytes": 0,
"accepted_formats": [
"string"
]
}
],
"guidelines": "string"
},
"availability_status": "available",
"created_at": "2026-01-15T10:30:00Z"
}

Search platforms with natural language

post/platforms/search

Searches for platforms using natural language queries. Results include a `relevance_score` (0-1) indicating match quality. Can be combined with structured filters.

Body parameters

querystringrequired

Natural language search query

filtersPlatformFilters
limitinteger

Returns

200Search results
401Invalid or missing API key
POST /platforms/search
curl -X POST https://sdk.tap.co/v1/platforms/search \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"query": "Radio stations targeting young professionals in New York",
"filters": {
"media_types": [
"string"
],
"market_areas": [
"string"
],
"budget_min": 0,
"budget_max": 0,
"audience_demographics": {}
},
"limit": 20
}'
Response
{
"data": [
null
],
"meta": {
"has_more": false,
"next_cursor": "string"
}
}

Check platform availability

get/platforms/{platformId}/availability

Checks inventory availability for a platform during specific dates. Returns available and unavailable date ranges with cost estimates. Availability is not guaranteed until campaign activation.

Parameters

platformIdstringrequired
start_datestringrequired

Start date (YYYY-MM-DD)

end_datestringrequired

End date (YYYY-MM-DD)

Returns

200Availability information
401Invalid or missing API key
404Resource not found
GET /platforms/{platformId}/availability
curl https://sdk.tap.co/v1/platforms/:platformId/availability \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"available": false,
"available_dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"unavailable_dates": [
"2026-01-15"
],
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
}
}

Get creative specifications

get/platforms/{platformId}/creative-specs

Returns the creative specifications for a platform including accepted formats, dimensions, durations, and file size limits.

Parameters

platformIdstringrequired

Returns

200Creative specifications
401Invalid or missing API key
404Resource not found
GET /platforms/{platformId}/creative-specs
curl https://sdk.tap.co/v1/platforms/:platformId/creative-specs \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"formats": [
{
"type": "image",
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"max_file_size_bytes": 0,
"accepted_formats": [
"string"
]
}
],
"guidelines": "string"
}

List campaigns

get/campaigns

Returns a paginated list of campaigns. Filter by `status` to show only campaigns in a specific state.

Parameters

limitinteger

Maximum number of items to return

cursorstring

Cursor for pagination (from previous response)

statusstring

Filter by campaign status

Enum: "draft", "pending_payment", "active", "paused", "completed", "cancelled"

Returns

200List of campaigns
401Invalid or missing API key
GET /campaigns
curl https://sdk.tap.co/v1/campaigns \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"data": [
{
"id": "camp_7d4e8f2a1b3c5d6e9f0a1b2c",
"tap_id": "TAP-2026-0042",
"status": "active",
"name": "Summer Sale 2026",
"advertiser_name": "Acme Corp",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "string",
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 0,
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
}
}
],
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
},
"estimated_impressions": 0,
"billing_schedule": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"amount_cents": 0,
"due_date": "2026-01-15",
"status": "pending",
"paid_at": "2026-01-15T10:30:00Z"
}
],
"notes": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z",
"activated_at": "2026-01-15T10:30:00Z"
}
],
"meta": {
"has_more": false,
"next_cursor": "string"
}
}

Create a campaign

post/campaigns

Creates a new campaign in `draft` status. Draft campaigns can be modified until activated. The response includes `estimated_cost` for the configured platforms.

Body parameters

namestringrequired
advertiser_namestringrequired
platformsCampaignPlatformInput[]required
notesstring

Returns

201Campaign created
400Invalid request
401Invalid or missing API key
POST /campaigns
curl -X POST https://sdk.tap.co/v1/campaigns \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Summer Sale 2026",
"advertiser_name": "Acme Corp",
"platforms": [
{
"platform_id": "plat_abc123",
"dates": [
{
"start": "2026-02-01",
"end": "2026-02-14"
}
],
"configuration": {
"spots_per_day": 4,
"dayparts": [
"morning",
"afternoon"
]
}
}
],
"notes": "Target audience: 25-45 professionals"
}'
Response
{
"id": "camp_7d4e8f2a1b3c5d6e9f0a1b2c",
"tap_id": "TAP-2026-0042",
"status": "active",
"name": "Summer Sale 2026",
"advertiser_name": "Acme Corp",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "string",
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 0,
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
}
}
],
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
},
"estimated_impressions": 0,
"billing_schedule": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"amount_cents": 0,
"due_date": "2026-01-15",
"status": "pending",
"paid_at": "2026-01-15T10:30:00Z"
}
],
"notes": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z",
"activated_at": "2026-01-15T10:30:00Z"
}

Get campaign details

get/campaigns/{campaignId}

Retrieves a campaign including its platforms, cost estimates, billing schedule, and current status.

Parameters

campaignIdstringrequired

Returns

200Campaign details
401Invalid or missing API key
404Resource not found
GET /campaigns/{campaignId}
curl https://sdk.tap.co/v1/campaigns/:campaignId \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"id": "camp_7d4e8f2a1b3c5d6e9f0a1b2c",
"tap_id": "TAP-2026-0042",
"status": "active",
"name": "Summer Sale 2026",
"advertiser_name": "Acme Corp",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "string",
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 0,
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
}
}
],
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
},
"estimated_impressions": 0,
"billing_schedule": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"amount_cents": 0,
"due_date": "2026-01-15",
"status": "pending",
"paid_at": "2026-01-15T10:30:00Z"
}
],
"notes": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z",
"activated_at": "2026-01-15T10:30:00Z"
}

Update campaign

patch/campaigns/{campaignId}

Updates a campaign. Only `draft` campaigns can be modified. When updating `platforms`, provide the complete configuration as it fully replaces the existing platforms.

Parameters

campaignIdstringrequired

Body parameters

namestring
advertiser_namestring
platformsCampaignPlatformInput[]
notesstring

Returns

200Campaign updated
400Invalid request
401Invalid or missing API key
404Resource not found
PATCH /campaigns/{campaignId}
curl -X PATCH https://sdk.tap.co/v1/campaigns/:campaignId \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"advertiser_name": "string",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {}
}
],
"notes": "string"
}'
Response
{
"id": "camp_7d4e8f2a1b3c5d6e9f0a1b2c",
"tap_id": "TAP-2026-0042",
"status": "active",
"name": "Summer Sale 2026",
"advertiser_name": "Acme Corp",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "string",
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 0,
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
}
}
],
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
},
"estimated_impressions": 0,
"billing_schedule": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"amount_cents": 0,
"due_date": "2026-01-15",
"status": "pending",
"paid_at": "2026-01-15T10:30:00Z"
}
],
"notes": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z",
"activated_at": "2026-01-15T10:30:00Z"
}

Delete campaign

delete/campaigns/{campaignId}

Permanently deletes a draft campaign. Only `draft` and `pending_payment` campaigns can be deleted. Active or completed campaigns must be cancelled instead.

Parameters

campaignIdstringrequired

Returns

204Campaign deleted
400Invalid request
401Invalid or missing API key
404Resource not found
DELETE /campaigns/{campaignId}
curl -X DELETE https://sdk.tap.co/v1/campaigns/:campaignId \
-H "Authorization: Bearer tap_live_xxx"

Activate campaign

post/campaigns/{campaignId}/activate

Activates a draft campaign, processing payment and scheduling ad delivery. Returns `402` if payment fails. Once activated, the campaign cannot be modified.

Parameters

campaignIdstringrequired

Body parameters

payment_method_idstringrequired

ID of the payment method to use

Returns

200Campaign activated
400Invalid request
401Invalid or missing API key
402Payment required or failed
404Resource not found
POST /campaigns/{campaignId}/activate
curl -X POST https://sdk.tap.co/v1/campaigns/:campaignId/activate \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"payment_method_id": "string"
}'
Response
{
"id": "camp_7d4e8f2a1b3c5d6e9f0a1b2c",
"tap_id": "TAP-2026-0042",
"status": "active",
"name": "Summer Sale 2026",
"advertiser_name": "Acme Corp",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "string",
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 0,
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
}
}
],
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
},
"estimated_impressions": 0,
"billing_schedule": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"amount_cents": 0,
"due_date": "2026-01-15",
"status": "pending",
"paid_at": "2026-01-15T10:30:00Z"
}
],
"notes": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z",
"activated_at": "2026-01-15T10:30:00Z"
}

Cancel campaign

post/campaigns/{campaignId}/cancel

Cancels an active or pending campaign. Stops future ad delivery and processes a prorated refund. Cancellation fees may apply depending on timing.

Parameters

campaignIdstringrequired

Returns

200Campaign cancelled
400Invalid request
401Invalid or missing API key
404Resource not found
POST /campaigns/{campaignId}/cancel
curl -X POST https://sdk.tap.co/v1/campaigns/:campaignId/cancel \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"id": "camp_7d4e8f2a1b3c5d6e9f0a1b2c",
"tap_id": "TAP-2026-0042",
"status": "active",
"name": "Summer Sale 2026",
"advertiser_name": "Acme Corp",
"platforms": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "string",
"dates": [
{
"start": "2026-01-15",
"end": "2026-01-15"
}
],
"configuration": {},
"estimated_impressions": 0,
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
}
}
],
"estimated_cost": {
"subtotal_cents": 4500000,
"fees_cents": 500000,
"total_cents": 5000000,
"currency": "USD"
},
"estimated_impressions": 0,
"billing_schedule": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"amount_cents": 0,
"due_date": "2026-01-15",
"status": "pending",
"paid_at": "2026-01-15T10:30:00Z"
}
],
"notes": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z",
"activated_at": "2026-01-15T10:30:00Z"
}

Get campaign metrics

get/campaigns/{campaignId}/metrics

Returns performance metrics for a campaign including impressions, reach, frequency, and spend. Includes a `by_platform` breakdown.

Parameters

campaignIdstringrequired

Returns

200Campaign metrics
401Invalid or missing API key
404Resource not found
GET /campaigns/{campaignId}/metrics
curl https://sdk.tap.co/v1/campaigns/:campaignId/metrics \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"campaign_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"impressions": 875000,
"reach": 312000,
"frequency": 2.8,
"spend_cents": 1250000,
"cpm_cents": 1428,
"period": {
"start": "2026-01-15",
"end": "2026-01-15"
},
"by_platform": [
{
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_name": "KQED Radio",
"impressions": 350000,
"spend_cents": 500000
}
]
}

List campaign creatives

get/campaigns/{campaignId}/creatives

Returns all creatives attached to a campaign. Each creative includes its brief, assets, and approval `status`.

Parameters

campaignIdstringrequired

Returns

200List of creatives
401Invalid or missing API key
404Resource not found
GET /campaigns/{campaignId}/creatives
curl https://sdk.tap.co/v1/campaigns/:campaignId/creatives \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"data": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"campaign_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"type": "display",
"status": "pending",
"brief": {
"headline": "string",
"body_copy": "string",
"call_to_action": "string",
"tone": "string",
"target_audience": "string",
"key_messages": [
"string"
]
},
"assets": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "string",
"type": "image",
"url": "https://example.com",
"size_bytes": 0,
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"mime_type": "string",
"created_at": "2026-01-15T10:30:00Z"
}
],
"rejection_reason": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}
]
}

Add creative to campaign

post/campaigns/{campaignId}/creatives

Adds a creative to a campaign. Provide the creative type, brief, and asset IDs. The creative enters `pending` status for validation.

Parameters

campaignIdstringrequired

Body parameters

typestringrequired
Enum: "display", "video", "audio", "native"
briefCreativeBrief
asset_idsstring[]

Returns

201Creative added
400Invalid request
401Invalid or missing API key
404Resource not found
POST /campaigns/{campaignId}/creatives
curl -X POST https://sdk.tap.co/v1/campaigns/:campaignId/creatives \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"type": "display",
"brief": {
"headline": "string",
"body_copy": "string",
"call_to_action": "string",
"tone": "string",
"target_audience": "string",
"key_messages": [
"string"
]
},
"asset_ids": [
"plan_8f2a9c4b1d3e5f6a7b8c9d0e"
]
}'
Response
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"campaign_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"type": "display",
"status": "pending",
"brief": {
"headline": "string",
"body_copy": "string",
"call_to_action": "string",
"tone": "string",
"target_audience": "string",
"key_messages": [
"string"
]
},
"assets": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "string",
"type": "image",
"url": "https://example.com",
"size_bytes": 0,
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"mime_type": "string",
"created_at": "2026-01-15T10:30:00Z"
}
],
"rejection_reason": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}

Get creative details

get/campaigns/{campaignId}/creatives/{creativeId}

Retrieves a creative including its brief, assets, and approval status. If rejected, `rejection_reason` explains why.

Parameters

campaignIdstringrequired
creativeIdstringrequired

Returns

200Creative details
401Invalid or missing API key
404Resource not found
GET /campaigns/{campaignId}/creatives/{creativeId}
curl https://sdk.tap.co/v1/campaigns/:campaignId/creatives/:creativeId \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"campaign_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"type": "display",
"status": "pending",
"brief": {
"headline": "string",
"body_copy": "string",
"call_to_action": "string",
"tone": "string",
"target_audience": "string",
"key_messages": [
"string"
]
},
"assets": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "string",
"type": "image",
"url": "https://example.com",
"size_bytes": 0,
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"mime_type": "string",
"created_at": "2026-01-15T10:30:00Z"
}
],
"rejection_reason": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}

Update creative

patch/campaigns/{campaignId}/creatives/{creativeId}

Updates a creative's brief or assets. Updating an approved creative resets its status to `pending` for re-review.

Parameters

campaignIdstringrequired
creativeIdstringrequired

Body parameters

briefCreativeBrief
asset_idsstring[]

Returns

200Creative updated
400Invalid request
401Invalid or missing API key
404Resource not found
PATCH /campaigns/{campaignId}/creatives/{creativeId}
curl -X PATCH https://sdk.tap.co/v1/campaigns/:campaignId/creatives/:creativeId \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"brief": {
"headline": "string",
"body_copy": "string",
"call_to_action": "string",
"tone": "string",
"target_audience": "string",
"key_messages": [
"string"
]
},
"asset_ids": [
"plan_8f2a9c4b1d3e5f6a7b8c9d0e"
]
}'
Response
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"campaign_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"type": "display",
"status": "pending",
"brief": {
"headline": "string",
"body_copy": "string",
"call_to_action": "string",
"tone": "string",
"target_audience": "string",
"key_messages": [
"string"
]
},
"assets": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "string",
"type": "image",
"url": "https://example.com",
"size_bytes": 0,
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"mime_type": "string",
"created_at": "2026-01-15T10:30:00Z"
}
],
"rejection_reason": "string",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}

Remove creative

delete/campaigns/{campaignId}/creatives/{creativeId}

Removes a creative from a campaign. The underlying assets remain in your asset library. Cannot remove creatives from active campaigns.

Parameters

campaignIdstringrequired
creativeIdstringrequired

Returns

204Creative removed
401Invalid or missing API key
404Resource not found
DELETE /campaigns/{campaignId}/creatives/{creativeId}
curl -X DELETE https://sdk.tap.co/v1/campaigns/:campaignId/creatives/:creativeId \
-H "Authorization: Bearer tap_live_xxx"

AI-generate creative

post/creatives/generate

Generates creative assets using AI. Returns a `job_id` to poll for completion. Supports display, audio, and video formats. Pass `platform_id` to match platform specifications automatically.

Body parameters

typestringrequired
Enum: "display", "video", "audio"
briefCreativeBriefrequired
platform_idstring

Platform to generate creative for (uses platform specs)

variationsinteger

Returns

202Generation job started
400Invalid request
401Invalid or missing API key
POST /creatives/generate
curl -X POST https://sdk.tap.co/v1/creatives/generate \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"type": "display",
"brief": {
"headline": "string",
"body_copy": "string",
"call_to_action": "string",
"tone": "string",
"target_audience": "string",
"key_messages": [
"string"
]
},
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"variations": 1
}'
Response
{
"job_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"status": "pending",
"estimated_completion": "2026-01-15T10:30:00Z",
"results": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "string",
"type": "image",
"url": "https://example.com",
"size_bytes": 0,
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"mime_type": "string",
"created_at": "2026-01-15T10:30:00Z"
}
]
}

Validate creative

post/creatives/validate

Validates an asset against a platform's specifications. Returns `valid` boolean with `errors` and `warnings` arrays.

Body parameters

asset_idstringrequired
platform_idstringrequired

Returns

200Validation result
400Invalid request
401Invalid or missing API key
POST /creatives/validate
curl -X POST https://sdk.tap.co/v1/creatives/validate \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"asset_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"platform_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e"
}'
Response
{
"valid": false,
"errors": [
{
"code": "string",
"message": "string",
"field": "string"
}
],
"warnings": [
{
"code": "string",
"message": "string"
}
]
}

List assets

get/assets

Returns a paginated list of assets in your library. Filter by `type` (image, video, audio).

Parameters

limitinteger

Maximum number of items to return

cursorstring

Cursor for pagination (from previous response)

typestring
Enum: "image", "video", "audio"

Returns

200List of assets
401Invalid or missing API key
GET /assets
curl https://sdk.tap.co/v1/assets \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"data": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "string",
"type": "image",
"url": "https://example.com",
"size_bytes": 0,
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"mime_type": "string",
"created_at": "2026-01-15T10:30:00Z"
}
],
"meta": {
"has_more": false,
"next_cursor": "string"
}
}

Upload asset

post/assets

Uploads a media file to your asset library. Supports images (max 10MB), audio (max 50MB), and video (max 500MB). Returns the asset with its ID and URL.

Body parameters

filestringrequired

The file to upload

namestring

Optional display name for the asset

Returns

201Asset uploaded
400Invalid request
401Invalid or missing API key
POST /assets
curl -X POST https://sdk.tap.co/v1/assets \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "string",
"type": "image",
"url": "https://example.com",
"size_bytes": 0,
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"mime_type": "string",
"created_at": "2026-01-15T10:30:00Z"
}

Get asset details

get/assets/{assetId}

Retrieves an asset's metadata including dimensions, duration, and a signed URL valid for 24 hours.

Parameters

assetIdstringrequired

Returns

200Asset details
401Invalid or missing API key
404Resource not found
GET /assets/{assetId}
curl https://sdk.tap.co/v1/assets/:assetId \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"name": "string",
"type": "image",
"url": "https://example.com",
"size_bytes": 0,
"dimensions": {
"width": 0,
"height": 0
},
"duration_seconds": 0,
"mime_type": "string",
"created_at": "2026-01-15T10:30:00Z"
}

Delete asset

delete/assets/{assetId}

Permanently deletes an asset. Assets attached to active campaigns cannot be deleted.

Parameters

assetIdstringrequired

Returns

204Asset deleted
401Invalid or missing API key
404Resource not found
DELETE /assets/{assetId}
curl -X DELETE https://sdk.tap.co/v1/assets/:assetId \
-H "Authorization: Bearer tap_live_xxx"

List payment methods

get/payment-methods

Returns all payment methods on file. Use the `id` when activating campaigns.

Returns

200List of payment methods
401Invalid or missing API key
GET /payment-methods
curl https://sdk.tap.co/v1/payment-methods \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"data": [
{
"id": "string",
"type": "card",
"is_default": false,
"card": {
"brand": "string",
"last4": "string",
"exp_month": 0,
"exp_year": 0
},
"bank_account": {
"bank_name": "string",
"last4": "string"
},
"created_at": "2026-01-15T10:30:00Z"
}
]
}

List invoices

get/invoices

Returns a paginated list of invoices. Includes both paid and outstanding invoices.

Parameters

limitinteger

Maximum number of items to return

cursorstring

Cursor for pagination (from previous response)

Returns

200List of invoices
401Invalid or missing API key
GET /invoices
curl https://sdk.tap.co/v1/invoices \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"data": [
{
"id": "string",
"number": "string",
"status": "draft",
"amount_cents": 0,
"currency": "string",
"campaign_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"campaign_name": "string",
"due_date": "2026-01-15",
"paid_at": "2026-01-15T10:30:00Z",
"created_at": "2026-01-15T10:30:00Z"
}
],
"meta": {
"has_more": false,
"next_cursor": "string"
}
}

Get invoice details

get/invoices/{invoiceId}

Retrieves an invoice including amount, status, due date, and associated campaign.

Parameters

invoiceIdstringrequired

Returns

200Invoice details
401Invalid or missing API key
404Resource not found
GET /invoices/{invoiceId}
curl https://sdk.tap.co/v1/invoices/:invoiceId \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"id": "string",
"number": "string",
"status": "draft",
"amount_cents": 0,
"currency": "string",
"campaign_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"campaign_name": "string",
"due_date": "2026-01-15",
"paid_at": "2026-01-15T10:30:00Z",
"created_at": "2026-01-15T10:30:00Z"
}

Download invoice PDF

get/invoices/{invoiceId}/pdf

Downloads a PDF of the invoice with itemized charges. Returns `application/pdf` content.

Parameters

invoiceIdstringrequired

Returns

200PDF file
401Invalid or missing API key
404Resource not found
GET /invoices/{invoiceId}/pdf
curl https://sdk.tap.co/v1/invoices/:invoiceId/pdf \
-H "Authorization: Bearer tap_live_xxx"

Get account balance

get/balance

Returns your account balance including `available_cents` and `pending_cents`. Available balance is applied to new charges automatically.

Returns

200Account balance
401Invalid or missing API key
GET /balance
curl https://sdk.tap.co/v1/balance \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"available_cents": 0,
"pending_cents": 0,
"currency": "string"
}

List transactions

get/transactions

Returns a paginated list of transactions including charges, refunds, and credits.

Parameters

limitinteger

Maximum number of items to return

cursorstring

Cursor for pagination (from previous response)

Returns

200List of transactions
401Invalid or missing API key
GET /transactions
curl https://sdk.tap.co/v1/transactions \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"data": [
{
"id": "string",
"type": "charge",
"amount_cents": 0,
"currency": "string",
"description": "string",
"campaign_id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"created_at": "2026-01-15T10:30:00Z"
}
],
"meta": {
"has_more": false,
"next_cursor": "string"
}
}

List webhooks

get/webhooks

Returns all webhook endpoints configured for your account.

Returns

200List of webhooks
401Invalid or missing API key
GET /webhooks
curl https://sdk.tap.co/v1/webhooks \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"data": [
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"url": "https://example.com",
"events": [
"string"
],
"secret": "string",
"is_active": false,
"created_at": "2026-01-15T10:30:00Z",
"last_triggered_at": "2026-01-15T10:30:00Z"
}
]
}

Create webhook

post/webhooks

Registers a webhook endpoint. The response includes a `secret` for verifying payloads via the `X-Tap-Signature` header. The secret is only shown once.

Body parameters

urlstringrequired
eventsstring[]required

Returns

201Webhook created
400Invalid request
401Invalid or missing API key
POST /webhooks
curl -X POST https://sdk.tap.co/v1/webhooks \
-H "Authorization: Bearer tap_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"events": [
"campaign.created"
]
}'
Response
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"url": "https://example.com",
"events": [
"string"
],
"secret": "string",
"is_active": false,
"created_at": "2026-01-15T10:30:00Z",
"last_triggered_at": "2026-01-15T10:30:00Z"
}

Get webhook details

get/webhooks/{webhookId}

Retrieves a webhook's configuration, subscribed events, and `is_active` status.

Parameters

webhookIdstringrequired

Returns

200Webhook details
401Invalid or missing API key
404Resource not found
GET /webhooks/{webhookId}
curl https://sdk.tap.co/v1/webhooks/:webhookId \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"id": "plan_8f2a9c4b1d3e5f6a7b8c9d0e",
"url": "https://example.com",
"events": [
"string"
],
"secret": "string",
"is_active": false,
"created_at": "2026-01-15T10:30:00Z",
"last_triggered_at": "2026-01-15T10:30:00Z"
}

Delete webhook

delete/webhooks/{webhookId}

Permanently removes a webhook. Pending retry events are discarded.

Parameters

webhookIdstringrequired

Returns

204Webhook deleted
401Invalid or missing API key
404Resource not found
DELETE /webhooks/{webhookId}
curl -X DELETE https://sdk.tap.co/v1/webhooks/:webhookId \
-H "Authorization: Bearer tap_live_xxx"

Test webhook

post/webhooks/{webhookId}/test

Sends a test event to your webhook endpoint. Returns `success`, `response_status`, and `response_time_ms`.

Parameters

webhookIdstringrequired

Returns

200Test event sent
401Invalid or missing API key
404Resource not found
POST /webhooks/{webhookId}/test
curl -X POST https://sdk.tap.co/v1/webhooks/:webhookId/test \
-H "Authorization: Bearer tap_live_xxx"
Response
{
"success": false,
"response_status": 0,
"response_time_ms": 0
}