Skip to content
Listener.comDevelopers

Campaigns

Sponsorship campaigns, slots, cluster links, brand profiles and air checks.

List campaigns

GET/v1/campaigns

The workspace's campaigns as the Campaigns page lists them: status, flight, goal progress, pacing, slots, reach by category and format, expected and delivered CPM, EMV, budget, unlinked slots, brand and public URL.

status filters after meta.status_counts are taken; brand matches name or slug; show_ids keeps campaigns with a slot or cluster on those shows; search matches title, brand and show names; sort_by is <key>:<asc|desc> (keys: startDate, endDate, status, createdAt, updatedAt, title, brand, reach, goal, pacing, cpm, budget, show). precision=summary (default) reads stored cluster summaries, fast but EMV, first-30-days and delivered CPM skip summary-only clusters; precision=nodes loads every linked cluster (slow on large networks).

SDKlistener.campaigns.list()client.campaigns.list()

Query parameters

  • statusstring
    Status filter or value.
    One ofallupcomingactivecompleted

    Default "all"

  • brandstringnullable
    Brand name or slug filter.
  • show_idsarray of stringsnullable
    Limit to these show ids (default: every show in the workspace). Repeat the parameter or comma-separate values.
  • searchstringnullable
    Case-insensitive text filter.
  • unlinked_onlyboolean

    Default false

  • sort_bystring
    Sort field.

    Default "startDate:desc"

  • precisionstring
    summary (fast, stored totals) or a more precise, slower computation.
    One ofsummarynodes

    Default "summary"

  • limitinteger1 to 100
    Page size, 1–100 (default 25).

    Default 25

  • cursorstring
    Opaque cursor from the previous page's next_cursor.

Returns

200

OK

  • objectstringrequired
  • urlstringrequired
  • dataarray of objectsrequired
    Show child attributesHide child attributes
  • has_morebooleanrequired
  • next_cursorstringrequirednullable
    Pass as cursor to get the next page; null on the last page.
  • metaobjectrequired
    The result's non-list fields (window, coverage, freshness, totals, note …).
    Show child attributesHide child attributes

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Create a campaign

POST/v1/campaigns

Create a campaign. At least one show must be referenced through show_goals, show_budgets or planned_episodes. Dates are YYYY-MM-DD and end_date must not precede start_date. When brand.name is set the brand profile is created or updated first and campaigns already sharing that brand get its details re-stamped (listed in warnings). A duplicate title + brand is a warning, not an error. No emails or notifications are sent.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

SDKlistener.campaigns.create()client.campaigns.create()

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • titlestringrequired
    Title.
  • descriptionstring
    Free-text description.

    Default ""

  • start_datestringnullable
    First day, YYYY-MM-DD (inclusive). With end_date, overrides time_range.
  • end_datestringnullable
    Last day, YYYY-MM-DD (inclusive). With start_date, overrides time_range.
  • brandobjectnullable
    Brand name or slug filter.
    Show child attributesHide child attributes
  • show_goalsmap of integernullable
    Per-show view goals: {show_id: views}.
  • show_budgetsmap of numbernullable
    Per-show budgets in dollars: {show_id: amount}.
  • total_budgetnumbernullable
    Total campaign budget in dollars.
  • platform_goalsmap of integernullable
    Per-platform goals: {platform: views}.
  • planned_episodesarray of objectsnullable
    Campaign slots: [{show_id, title?, expected_impressions?, budget?}].
    Show child attributesHide child attributes
  • show_idsarray of stringsnullable
    Limit to these show ids (default: every show in the workspace).
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Retrieve a campaign

GET/v1/campaigns/{campaign_id}

One campaign in full: headline KPIs (reach by category and format, engagement, expected vs delivered CPM, EMV with resolved settings, first-30-days estimate), fulfilment against goal and pacing, every slot with its linked cluster's reach, per-show breakdown, air-check summary, share settings, brand, activity log and URLs. Node-precise: every linked cluster is loaded.

SDKlistener.campaigns.retrieve()client.campaigns.retrieve()

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).

Query parameters

  • activity_limitinteger0 to 200

    Default 30

Returns

200

OK

  • idstringrequired
  • titlestringrequired
  • statusstringrequired
    One ofupcomingactivecompleted
  • status_labelstringrequired
  • brandobjectrequired
    Show child attributesHide child attributes
  • goalsobjectrequired
    Show child attributesHide child attributes
  • pacingobjectrequired
    Show child attributesHide child attributes
  • reachobjectrequired
    Show child attributesHide child attributes
  • activity_logobjectrequired
    Show child attributesHide child attributes
  • app_urlstringrequired
  • precisionstringrequired
    One ofsummarynodesnone
  • computed_atstringrequired
  • cache_age_secondsnumberrequired
  • objectstringrequired
  • descriptionstring

    Default ""

  • status_is_manualboolean

    Default false

  • status_updated_atstringnullable
  • start_datestringnullable
  • end_datestringnullable
  • start_is_fallbackboolean

    Default false

  • days_remainingintegernullable
  • days_until_startintegernullable
  • timingstringnullable
  • has_goalboolean

    Default false

  • goal_progress_pctnumbernullable
  • goal_progress_clamped_pctnumbernullable
  • budgetnumber

    Default 0

  • slot_budget_totalnumber

    Default 0

  • expected_impressionsnumber

    Default 0

  • expected_cpmnumber

    Default 0

  • delivered_cpmnumber

    Default 0

  • delivered_cpm_statusstring

    Default "pending"

  • delivered_cpm_detailobject
  • format_cpmobject
  • emvobject
    EMV block incl. resolved settings + settings_source.
  • engagementnumber

    Default 0

  • engagement_ratenumber

    Default 0

  • first_30_daysobject
  • linked_show_idsarray of strings
  • linked_show_namesarray of strings
  • show_countinteger

    Default 0

  • cluster_idsarray of strings
  • clusters_loadedinteger

    Default 0

  • clusters_missingarray of strings
  • total_slotsinteger

    Default 0

  • linked_slotsinteger

    Default 0

  • unlinked_slot_countinteger

    Default 0

  • live_slotsinteger

    Default 0

  • slotsarray of objects
    Show child attributesHide child attributes
  • show_breakdownarray of objects
    Show child attributesHide child attributes
  • air_checksobject
  • excluded_node_countinteger

    Default 0

  • excluded_node_ids_countinteger

    Default 0

  • featured_content_node_idstringnullable
  • merged_fromarray of objectsnullable
  • copied_fromobjectnullable
  • created_viastringnullable
  • duplicateobjectnullable
  • shareobject
  • public_urlstringnullable
  • created_atstringnullable
  • updated_atstringnullable
  • warningsarray of strings
  • notestringnullable

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Update a campaign

PATCH/v1/campaigns/{campaign_id}

Update a campaign's title, description, dates, brand, goals, budgets, EMV settings or featured content. Only the fields you send change. brand fields merge into the campaign's brand; show_goals replaces the per-show goals and recomputes the total; emv_settings merges and is normalised. Renaming the brand re-stamps other campaigns of that brand (listed in warnings). clear_featured_content_node / clear_platform_goals remove those fields. Slots, cluster links and status have their own endpoints.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

SDKlistener.campaigns.update()client.campaigns.update()

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • titlestringnullable
    Title.
  • descriptionstringnullable
    Free-text description.
  • start_datestringnullable
    First day, YYYY-MM-DD (inclusive). With end_date, overrides time_range.
  • end_datestringnullable
    Last day, YYYY-MM-DD (inclusive). With start_date, overrides time_range.
  • brandobjectnullable
    Brand name or slug filter.
    Show child attributesHide child attributes
  • show_goalsmap of integernullable
    Per-show view goals: {show_id: views}.
  • show_budgetsmap of numbernullable
    Per-show budgets in dollars: {show_id: amount}.
  • total_budgetnumbernullable
    Total campaign budget in dollars.
  • platform_goalsmap of integernullable
    Per-platform goals: {platform: views}.
  • emv_settingsobjectnullable
    Campaign `emvSettings (port of normalizeCampaignEmvSettings`).
    Show child attributesHide child attributes
  • featured_content_node_idstringnullable
  • clear_featured_content_nodeboolean

    Default false

  • clear_platform_goalsboolean

    Default false

  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Delete a campaign

DELETE/v1/campaigns/{campaign_id}

Permanently delete a campaign (no undo, no cascade) and report what it leaves behind: pending brand invites and shared reports that embed it. Send ?dry_run=true first to see them.

  • Send ?dry_run=true to get {"object": "dry_run", "would_write": …} without writing anything.
  • Requires ?confirm=true; without it the API answers 409 confirmation_required with the exact preview.

SDKlistener.campaigns.delete()client.campaigns.delete()

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).

Query parameters

  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

  • confirmboolean
    Must be true to apply destructive or metered changes; without it the API answers 409 with a preview.

    Default false

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Campaign timeline

GET/v1/campaigns/{campaign_id}/timeline

A campaign's reach series (total, audio, YouTube, social; daily buckets as the campaign chart draws them) and its EMV accrual over a window. window is 7d, 30d, 90d or all, or send start_date + end_date; chart_type is daily or cumulative. EMV points are thinned to at most 180 by summing whole weeks.

SDKlistener.campaigns.timeline()client.campaigns.timeline()

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).

Query parameters

  • windowstring
    Reporting window.
    One of7d30d90dall

    Default "30d"

  • start_datestringnullable
    First day, YYYY-MM-DD (inclusive). With end_date, overrides time_range.
  • end_datestringnullable
    Last day, YYYY-MM-DD (inclusive). With start_date, overrides time_range.
  • chart_typestring
    daily values or a cumulative running total.
    One ofdailycumulative

    Default "cumulative"

Returns

200

OK

  • campaign_idstringrequired
  • titlestringrequired
  • windowobjectrequired
    {time_range, chart_type, start, end, previous_start, previous_end} as the chart resolves it.
  • chart_typestringrequired
    One ofdailycumulative
  • totalsmap of numberrequired
  • growthmap of numberrequired
    vs the equal-length previous window; None for all-time.
  • reach_seriesarray of objectsrequired
    Show child attributesHide child attributes
  • audio_seriesarray of objectsrequired
    Show child attributesHide child attributes
  • youtube_seriesarray of objectsrequired
    Show child attributesHide child attributes
  • social_seriesarray of objectsrequired
    Show child attributesHide child attributes
  • events_countedintegerrequired
  • emv_seriesarray of objectsrequired
    Show child attributesHide child attributes
  • emv_totalnumberrequired
  • precisionstringrequired
    One ofsummarynodesnone
  • computed_atstringrequired
  • cache_age_secondsnumberrequired
  • objectstringrequired
  • emv_by_platformmap of number
  • emv_enabledboolean

    Default false

  • emv_nodes_countedinteger

    Default 0

  • emv_points_thinnedboolean
    True when the EMV series was thinned to ≤ 180 points by summing whole weeks.

    Default false

  • warningsarray of strings
  • public_urlstringnullable
  • notestringnullable

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Campaign CPM insights

GET/v1/campaigns/{campaign_id}/cpm-insights

A campaign's expected vs delivered CPM per format and where it sits against the workspace's recent campaigns (median of the 12 most recent peers with a delivered CPM; within ±3 % counts as in line). Peers are the peer_limit most recently updated other campaigns, loaded at node precision. Delivered CPM is null until a campaign has delivered at least 25 % of its expected impressions.

SDKlistener.campaigns.cpmInsights()client.campaigns.cpm_insights()

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).

Query parameters

  • peer_limitinteger1 to 60

    Default 24

Returns

200

OK

  • campaign_idstringrequired
  • titlestringrequired
  • precisionstringrequired
    One ofsummarynodesnone
  • computed_atstringrequired
  • cache_age_secondsnumberrequired
  • objectstringrequired
  • expected_cpmnumber

    Default 0

  • delivered_cpmnumber

    Default 0

  • delivered_cpm_statusstring

    Default "pending"

  • delivered_cpm_detailobject
  • format_cpmobject
  • benchmarksmap of object
    long_form / short_form delivered CPM vs the median of the 12 most recent peers with a CPM.
    Show child attributesHide child attributes
  • peersarray of objects
    Show child attributesHide child attributes
  • peers_consideredinteger

    Default 0

  • peers_with_cpmmap of integer
  • workspace_campaign_countinteger

    Default 0

  • warningsarray of strings
  • public_urlstringnullable
  • notestringnullable

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Set a campaign's status

POST/v1/campaigns/{campaign_id}/status

Set a campaign's manual status (upcoming, active, completed), or send "status": null to clear the override so the status follows the dates again. No other side effects.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

SDKlistener.campaigns.setStatus()client.campaigns.set_status()

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • statusstringnullable
    Status filter or value.
    One ofupcomingactivecompleted
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Add campaign slots

POST/v1/campaigns/{campaign_id}/slots

Append slots (planned episodes) to a campaign: a show plus optional title, expected_impressions, budget and linked_cluster_id each. Returns the new slot ids and the full slot list. A cluster already linked to another slot is refused (single-slot rule); up to 2,000 slots per campaign.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

SDKlistener.campaigns.slots.create()client.campaigns.slots.create()

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • planned_episodesarray of objectsrequired
    Campaign slots: [{show_id, title?, expected_impressions?, budget?}].
    Show child attributesHide child attributes
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Update a campaign slot

PATCH/v1/campaigns/{campaign_id}/slots/{slot_id}

Edit one slot's title, expected_impressions, budget or show_id. Setting impressions or budget pins the value so the app stops auto-distributing it. To change the linked cluster use PUT / DELETE /v1/campaigns/{campaign_id}/slots/{slot_id}/cluster.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

SDKlistener.campaigns.slots.update()client.campaigns.slots.update()

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).
  • slot_idstringrequired
    Campaign slot (planned episode) id from the campaign's slots.

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • titlestringnullable
    Title.
  • expected_impressionsintegernullable
  • budgetnumbernullable
  • show_idstringnullable
    A show id in this workspace (see GET /v1/shows).
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

List brands

GET/v1/brands

The workspace's advertisers (brand profiles plus every brand named on a campaign) with campaign counts, status mix, shows reached, aggregated reach, budget and CPM, EMV and the public brand page URL. search matches name, slug or domain; precision=summary (default) reads stored cluster summaries, nodes loads every linked cluster.

SDKlistener.brands.list()client.brands.list()

Query parameters

  • searchstringnullable
    Case-insensitive text filter.
  • precisionstring
    summary (fast, stored totals) or a more precise, slower computation.
    One ofsummarynodes

    Default "summary"

  • limitinteger1 to 100
    Page size, 1–100 (default 25).

    Default 25

  • cursorstring
    Opaque cursor from the previous page's next_cursor.

Returns

200

OK

  • objectstringrequired
  • urlstringrequired
  • dataarray of objectsrequired
    Show child attributesHide child attributes
  • has_morebooleanrequired
  • next_cursorstringrequirednullable
    Pass as cursor to get the next page; null on the last page.
  • metaobjectrequired
    The result's non-list fields (window, coverage, freshness, totals, note …).
    Show child attributesHide child attributes

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Retrieve a brand

GET/v1/brands/{brand_slug}

One brand's report as its public page computes it: totals (reach by category, budget, planned impressions, expected and delivered CPM), per-campaign rows, per-show performance, EMV, invites and a reach trend. The path also accepts the brand name. time_range (7d, 30d, 90d, all) and chart_type shape the trend; precision=nodes (default) loads every linked cluster, summary is faster but skips EMV.

SDKlistener.brands.retrieve()client.brands.retrieve()

Path parameters

  • brand_slugstringrequired
    Brand slug (see GET /v1/brands).

Query parameters

  • time_rangestring
    7d | 14d | 30d | 90d | 180d | 365d | all, or a quarter like 2026-Q2. Windows are UTC days anchored to today.
    One of7d30d90dall

    Default "all"

  • chart_typestring
    daily values or a cumulative running total.
    One ofdailycumulative

    Default "cumulative"

  • precisionstring
    summary (fast, stored totals) or a more precise, slower computation.
    One ofsummarynodes

    Default "nodes"

Returns

200

OK

  • slugstringrequired
  • namestringrequired
  • totalsobjectrequired
  • campaign_rowsarray of objectsrequired
  • show_performancearray of objectsrequired
  • showsarray of objectsrequired
  • trendobjectrequired
    {time_range, chart_type, points: [...]} from brand_trend_series.
  • precisionstringrequired
    One ofsummarynodesnone
  • app_urlstringrequired
  • computed_atstringrequired
  • cache_age_secondsnumberrequired
  • objectstringrequired
  • domainstringnullable
  • logostringnullable
  • notesstringnullable
  • has_contactboolean

    Default false

  • has_brand_docboolean

    Default false

  • brand_docobjectnullable
    The canonical campaignBrands doc (contact fields removed).
  • invitesarray of objects
    brandInvites for this brand (emails masked).
  • campaign_idsarray of strings
  • campaign_countinteger

    Default 0

  • emv_totalnumber

    Default 0

  • emv_by_campaignmap of number
  • public_urlstringnullable
  • notestringnullable

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Create or update a brand

PUT/v1/brands/{brand_slug}

Create or update a brand profile once for every campaign: name, logo, domain, contact, invite email, notes. Every campaign of the brand gets its brand details re-stamped in the same write; when more than one campaign is affected the request needs "confirm": true (the 409 preview and a dry run both list affected_campaign_ids).

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

SDKlistener.brands.upsert()client.brands.upsert()

Path parameters

  • brand_slugstringrequirednullable

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • namestringrequired
    Name.
  • logostringnullable
  • domainstringnullable
  • contactstringnullable
  • invite_emailstringnullable
  • notesstringnullable
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

  • confirmboolean
    Must be true to apply destructive or metered changes; without it the API answers 409 with a preview.

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

List air checks

GET/v1/air-checks

Ad-read verification rows, one per campaign placement, with status (detected, missing, pending, blocked, excluded), the transcript-capable targets (Spotify episode, long-form YouTube video), every brand mention found (collapsed into ad reads with YouTube timestamp links) and pre / mid / post placement. group_by (advertiser, publisher, campaign, show) adds groups in meta. Narrow with campaign_id, brand or show_id on large networks.

SDKlistener.airChecks.list()client.air_checks.list()

Query parameters

  • campaign_idstringnullable
    Campaign id (see GET /v1/campaigns).
  • show_idstringnullable
    A show id in this workspace (see GET /v1/shows).
  • brandstringnullable
    Brand name or slug filter.
  • statusstring
    Status filter or value.
    One ofalldetectedmissingpendingblockedexcluded

    Default "all"

  • platformstringnullable
    A platform name (e.g. youtube, spotify, applePodcasts, instagram).
    One ofspotifyyoutube
  • group_bystringnullable
    Group the results by this field.
    One ofadvertiserpublishercampaignshow
  • limitinteger1 to 100
    Page size, 1–100 (default 25).

    Default 25

  • cursorstring
    Opaque cursor from the previous page's next_cursor.

Returns

200

OK

  • objectstringrequired
  • urlstringrequired
  • dataarray of objectsrequired
    Show child attributesHide child attributes
  • has_morebooleanrequired
  • next_cursorstringrequirednullable
    Pass as cursor to get the next page; null on the last page.
  • metaobjectrequired
    The result's non-list fields (window, coverage, freshness, totals, note …).
    Show child attributesHide child attributes

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error