{"openapi":"3.1.0","info":{"title":"Pushnami Ads Advertiser API","version":"1.0.0","description":"Manage campaigns, creatives and source targeting for your Pushnami Ads account. Every endpoint is also an MCP tool at POST /mcp. Reporting lives in the Spend Report API. Every authenticated response carries Pushnami-Api-Key-Expires-At (ISO 8601); within 14 days of expiry it also carries Pushnami-Api-Key-Expiry-Warning. Renew the key on the API Access page; the key string stays the same."},"servers":[{"url":"https://ads-api.pushnami.com"}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key: pnk_..."}},"responses":{"Error":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{},"request_id":{"type":"string"}}}}}}}}}},"paths":{"/v1/me":{"get":{"operationId":"get_api_key_info","summary":"Who am I","description":"Returns the advertiser account this API key acts on and whether it can make changes.","x-required-scope":"read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/limits":{"get":{"operationId":"get_limits","summary":"Daily limits","description":"How much of today's API change budget this account has used, per kind of change, and when it resets (00:00 UTC). Check before large jobs. Pausing campaigns and creatives is never limited.","x-required-scope":"read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/balance":{"get":{"operationId":"get_balance","summary":"Account balance","description":"Your available balance, how you pay (card or prepaid wire), auto-funding settings for card accounts, average daily spend over the last 7 days, and how many days the balance will last at that pace. status is \"low\" or \"depleted\" when the account needs funds; message says what to do. Read-only: funds are added in the dashboard (card) or by wire (prepay), never through the API. Refreshed at most every 10 minutes; fresh=true forces a new read.","x-required-scope":"read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"fresh","in":"query","required":false,"schema":{"type":"boolean","description":"Skip the 10-minute cache."}}]}},"/v1/campaigns":{"get":{"operationId":"list_campaigns","summary":"List campaigns","description":"Lists campaigns in your account, newest first. Defaults to active and paused campaigns. Use get_campaign for the default bid and live delivery status of one campaign.","x-required-scope":"read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["active","paused","archived","rejected"]},"uniqueItems":true,"description":"Filter by status. Default: active and paused."},"style":"form","explode":false},{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":100,"description":"Matches campaign name or ID."}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":10000,"default":0}}]},"post":{"operationId":"create_campaign","summary":"Create campaign","description":"Creates a campaign. It starts delivering once it has an approved creative and the account has funds; pass status \"paused\" to create it paused. Add creatives with create_creatives.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"201":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"pattern":"\\S"},"audience":{"type":"object","description":"Who the campaign targets. Replaces the whole audience when sent; omit a field to not target on it. An empty object targets everyone. Targeting subscribers newer than 7 days (10080 minutes) or any age/gender rule raises the minimum bid to $0.30.","additionalProperties":false,"properties":{"country":{"type":"string","enum":["US","CA","DE","AU","GB","SG","AE","FR","IT","JP","IL","IE","HK","NL"],"description":"ISO country code."},"states":{"type":"array","items":{"type":"string","enum":["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]},"uniqueItems":true,"maxItems":50,"description":"US state codes. Only meaningful with country \"US\"."},"platforms":{"type":"array","items":{"type":"string","enum":["DESKTOP","MOBILE","TABLET","OTHER"]},"uniqueItems":true,"minItems":1,"maxItems":4},"subscribed_more_than_minutes_ago":{"type":"integer","minimum":1,"maximum":5256000,"description":"Only subscribers who subscribed more than this many minutes ago."},"subscribed_less_than_minutes_ago":{"type":"integer","minimum":1,"maximum":5256000,"description":"Only subscribers who subscribed less than this many minutes ago (10080 = 7 days)."},"min_age":{"type":"integer","minimum":13,"maximum":120},"max_age":{"type":"integer","minimum":13,"maximum":120},"gender":{"type":"string","enum":["M","F"],"description":"M or F. Omit to target both."}}},"default_bid":{"type":"number","minimum":0.1,"maximum":25,"description":"USD per click. Minimum $0.10, or $0.30 when the audience targets subscribers newer than 7 days or uses age/gender."},"daily_spend_limit":{"type":"number","minimum":100,"maximum":1000000,"description":"Daily spend cap in USD, at least 100. Campaigns managed through the API always have one; removing it is only possible in the dashboard. One change can at most double it."},"target_cpa":{"anyOf":[{"type":"number","minimum":1,"maximum":10000},{"type":"null"}],"description":"Target cost per acquisition in USD (at least 1). Setting it turns on source optimization; null turns it off. One change can at most double it."},"start_date":{"type":"string","format":"date-time","description":"When delivery may start. Default: now."},"end_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When delivery stops. Omit for no end date."},"status":{"type":"string","enum":["active","paused"],"default":"active"}},"required":["name","audience","default_bid","daily_spend_limit"],"additionalProperties":false}}}}}},"/v1/campaigns/{campaign_id}":{"get":{"operationId":"get_campaign","summary":"Get campaign","description":"One campaign with its settings, default bid, source targeting mode and delivery_status (why it is or is not delivering right now: waiting_for_funds, waiting_for_creatives, daily_limit_reached, ...).","x-required-scope":"read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]},"patch":{"operationId":"update_campaign","summary":"Update campaign","description":"Changes any of: name, audience (replaced whole), default_bid, daily_spend_limit, target_cpa (null turns source optimization off), start_date, end_date. Only the fields you send change. Day-parting (active hours) is kept as set in the dashboard.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"pattern":"\\S"},"audience":{"type":"object","description":"Who the campaign targets. Replaces the whole audience when sent; omit a field to not target on it. An empty object targets everyone. Targeting subscribers newer than 7 days (10080 minutes) or any age/gender rule raises the minimum bid to $0.30.","additionalProperties":false,"properties":{"country":{"type":"string","enum":["US","CA","DE","AU","GB","SG","AE","FR","IT","JP","IL","IE","HK","NL"],"description":"ISO country code."},"states":{"type":"array","items":{"type":"string","enum":["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]},"uniqueItems":true,"maxItems":50,"description":"US state codes. Only meaningful with country \"US\"."},"platforms":{"type":"array","items":{"type":"string","enum":["DESKTOP","MOBILE","TABLET","OTHER"]},"uniqueItems":true,"minItems":1,"maxItems":4},"subscribed_more_than_minutes_ago":{"type":"integer","minimum":1,"maximum":5256000,"description":"Only subscribers who subscribed more than this many minutes ago."},"subscribed_less_than_minutes_ago":{"type":"integer","minimum":1,"maximum":5256000,"description":"Only subscribers who subscribed less than this many minutes ago (10080 = 7 days)."},"min_age":{"type":"integer","minimum":13,"maximum":120},"max_age":{"type":"integer","minimum":13,"maximum":120},"gender":{"type":"string","enum":["M","F"],"description":"M or F. Omit to target both."}}},"default_bid":{"type":"number","minimum":0.1,"maximum":25,"description":"USD per click. Minimum $0.10, or $0.30 when the audience targets subscribers newer than 7 days or uses age/gender."},"daily_spend_limit":{"type":"number","minimum":100,"maximum":1000000,"description":"Daily spend cap in USD, at least 100. Campaigns managed through the API always have one; removing it is only possible in the dashboard. One change can at most double it."},"target_cpa":{"anyOf":[{"type":"number","minimum":1,"maximum":10000},{"type":"null"}],"description":"Target cost per acquisition in USD (at least 1). Setting it turns on source optimization; null turns it off. One change can at most double it."},"start_date":{"type":"string","format":"date-time"},"end_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"null removes the end date."}},"required":[],"additionalProperties":false,"minProperties":1}}}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}},"/v1/campaigns/{campaign_id}/status":{"post":{"operationId":"set_campaign_status","summary":"Pause, activate or archive a campaign","description":"Sets a campaign to active, paused or archived. Pausing stops delivery within seconds. Archiving is permanent: an archived campaign cannot be reactivated or edited.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","paused","archived"]}},"required":["status"],"additionalProperties":false}}}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}},"/v1/campaigns/{campaign_id}/clone":{"post":{"operationId":"clone_campaign","summary":"Clone campaign","description":"Copies a campaign: audience, schedule, bid, daily limit, target CPA and source targeting. With include_creatives (default true) its active, paused and pending creatives are copied too and go to review.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"201":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"pattern":"\\S"},"include_creatives":{"type":"boolean","default":true,"description":"Copy up to 20 of its newest active, paused and pending creatives."},"status":{"type":"string","enum":["active","paused"],"default":"paused"},"daily_spend_limit":{"type":"number","minimum":100,"maximum":1000000,"description":"Daily spend cap for the copy. Default: the original's. Required if it has none."}},"required":["name"],"additionalProperties":false}}}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}},"/v1/campaigns/{campaign_id}/creatives":{"get":{"operationId":"list_creatives","summary":"List creatives","description":"Lists a campaign's creatives, newest first. Rejected creatives include rejection_reasons and rejection_comment.","x-required-scope":"read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}},{"name":"status","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","enum":["active","paused","pending_review","rejected","draft","archived"]},"uniqueItems":true,"description":"Default: everything except archived."},"style":"form","explode":false},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":10000,"default":0}}]},"post":{"operationId":"create_creatives","summary":"Create creatives","description":"Adds up to 20 push creatives to a campaign. Each is submitted for review (usually within 24 hours) unless draft is true. To submit, title, message, link and icon_id are required. Upload images first with upload_image.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"201":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"creatives":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":100,"description":"Notification title (34 characters or fewer recommended). May use dynamic values such as {{=data.dcity||'Your City'}} or {{#def.date('MMMM')}}."},"message":{"type":"string","minLength":1,"maxLength":200,"description":"Notification body (65 characters or fewer recommended). May use dynamic values such as {{=data.dcity||'Your City'}} or {{#def.date('MMMM')}}."},"link":{"type":"string","maxLength":2000,"pattern":"^https?://\\S+$","description":"Destination URL. Supports tracking macros such as <<conversion_id>> and {{=data.adsourceid}}."},"image_id":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{24}$","description":"Large image (2:1), from upload_image with kind \"image\". Optional."},{"type":"null"}],"description":"Large image (2:1), from upload_image with kind \"image\". Optional. null clears it."},"icon_id":{"type":"string","pattern":"^[0-9a-f]{24}$","description":"Icon (1:1), from upload_image with kind \"icon\". Required to submit."},"button1":{"anyOf":[{"type":"string","minLength":1,"maxLength":25,"pattern":"\\S","description":"Primary button text. Defaults to \"Click Here\"."},{"type":"null"}],"description":"Primary button text. Defaults to \"Click Here\". null clears it."},"button2":{"anyOf":[{"type":"string","minLength":1,"maxLength":25,"pattern":"\\S","description":"Second button."},{"type":"null"}],"description":"Second button. null clears it."}},"required":[],"additionalProperties":false}},"draft":{"type":"boolean","default":false,"description":"Save as drafts instead of submitting."}},"required":["creatives"],"additionalProperties":false}}}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}},"/v1/creatives/{creative_id}":{"get":{"operationId":"get_creative","summary":"Get creative","description":"One creative with its content, status and any rejection feedback.","x-required-scope":"read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}-\\d{3,6}$","description":"Creative ID, e.g. C0001234-001."}}]},"patch":{"operationId":"update_creative","summary":"Edit creative","description":"Edits a creative. Only the fields you send change. Editing a pending, rejected or draft creative updates it in place and (re)submits it for review. Editing an active or paused creative creates a new version that goes to review while the original keeps running; the new version replaces it once approved.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":100,"description":"Notification title (34 characters or fewer recommended). May use dynamic values such as {{=data.dcity||'Your City'}} or {{#def.date('MMMM')}}."},"message":{"type":"string","minLength":1,"maxLength":200,"description":"Notification body (65 characters or fewer recommended). May use dynamic values such as {{=data.dcity||'Your City'}} or {{#def.date('MMMM')}}."},"link":{"type":"string","maxLength":2000,"pattern":"^https?://\\S+$","description":"Destination URL. Supports tracking macros such as <<conversion_id>> and {{=data.adsourceid}}."},"image_id":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{24}$","description":"Large image (2:1), from upload_image with kind \"image\". Optional."},{"type":"null"}],"description":"Large image (2:1), from upload_image with kind \"image\". Optional. null clears it."},"icon_id":{"type":"string","pattern":"^[0-9a-f]{24}$","description":"Icon (1:1), from upload_image with kind \"icon\". Required to submit."},"button1":{"anyOf":[{"type":"string","minLength":1,"maxLength":25,"pattern":"\\S","description":"Primary button text. Defaults to \"Click Here\"."},{"type":"null"}],"description":"Primary button text. Defaults to \"Click Here\". null clears it."},"button2":{"anyOf":[{"type":"string","minLength":1,"maxLength":25,"pattern":"\\S","description":"Second button."},{"type":"null"}],"description":"Second button. null clears it."},"submit_for_review":{"type":"boolean","description":"For a draft: submit it for review."}},"required":[],"additionalProperties":false,"minProperties":1}}}},"parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}-\\d{3,6}$","description":"Creative ID, e.g. C0001234-001."}}]}},"/v1/creatives/{creative_id}/status":{"post":{"operationId":"set_creative_status","summary":"Pause, activate or archive a creative","description":"Pauses an active creative, re-activates a paused one, or archives a creative (permanent). Pending and rejected creatives cannot be activated — approval activates them.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","paused","archived"]}},"required":["status"],"additionalProperties":false}}}},"parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}-\\d{3,6}$","description":"Creative ID, e.g. C0001234-001."}}]}},"/v1/creatives/{creative_id}/clone":{"post":{"operationId":"clone_creative","summary":"Clone creative","description":"Copies a creative into the same or another of your campaigns, optionally changing fields, and submits the copy for review. Good for A/B variants: clone and change only the title or image.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"201":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"campaign_id":{"type":"string","pattern":"^C\\d{7,10}$","description":"Target campaign. Default: the original's campaign."},"title":{"type":"string","minLength":1,"maxLength":100,"description":"Notification title (34 characters or fewer recommended). May use dynamic values such as {{=data.dcity||'Your City'}} or {{#def.date('MMMM')}}."},"message":{"type":"string","minLength":1,"maxLength":200,"description":"Notification body (65 characters or fewer recommended). May use dynamic values such as {{=data.dcity||'Your City'}} or {{#def.date('MMMM')}}."},"link":{"type":"string","maxLength":2000,"pattern":"^https?://\\S+$","description":"Destination URL. Supports tracking macros such as <<conversion_id>> and {{=data.adsourceid}}."},"image_id":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{24}$","description":"Large image (2:1), from upload_image with kind \"image\". Optional."},{"type":"null"}],"description":"Large image (2:1), from upload_image with kind \"image\". Optional. null clears it."},"icon_id":{"type":"string","pattern":"^[0-9a-f]{24}$","description":"Icon (1:1), from upload_image with kind \"icon\". Required to submit."},"button1":{"anyOf":[{"type":"string","minLength":1,"maxLength":25,"pattern":"\\S","description":"Primary button text. Defaults to \"Click Here\"."},{"type":"null"}],"description":"Primary button text. Defaults to \"Click Here\". null clears it."},"button2":{"anyOf":[{"type":"string","minLength":1,"maxLength":25,"pattern":"\\S","description":"Second button."},{"type":"null"}],"description":"Second button. null clears it."},"draft":{"type":"boolean","default":false}},"required":[],"additionalProperties":false}}}},"parameters":[{"name":"creative_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}-\\d{3,6}$","description":"Creative ID, e.g. C0001234-001."}}]}},"/v1/images":{"post":{"operationId":"upload_image","summary":"Upload creative image or icon","description":"Uploads a PNG, JPEG or GIF (max 700 KB) and returns its id for create_creatives / update_creative. Send image_url (a public https link; we download it) or data_base64 with content_type, not both. Prefer image_url: it avoids sending the file through the conversation. kind \"icon\": square (1:1), 300x300 recommended. kind \"image\": 2:1, 400x200 recommended.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"201":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["image","icon"]},"content_type":{"type":"string","enum":["image/png","image/jpeg","image/gif"]},"data_base64":{"type":"string","minLength":8,"maxLength":960000,"pattern":"^[A-Za-z0-9+/]+={0,2}$","description":"The file bytes, base64-encoded (no data: prefix). Requires content_type."},"image_url":{"type":"string","maxLength":2000,"pattern":"^https://\\S+$","description":"A public https URL of the file. Downloaded once, within 10 seconds; the type is read from the file."}},"required":["kind"],"additionalProperties":false}}}}}},"/v1/campaigns/{campaign_id}/sources":{"get":{"operationId":"get_source_settings","summary":"Get source targeting and bids","description":"A campaign's source (website) targeting: whether it runs a block-list or an allow-list, the sources you blocked or allowed by hand, and per-source bid overrides. For per-source performance use the Spend Report API.","x-required-scope":"read","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}},"/v1/campaigns/{campaign_id}/sources/bids":{"post":{"operationId":"set_source_bids","summary":"Set per-source bids","description":"Sets the bid for up to 50 sources on a campaign in one call. Send bid (USD) to override, bid: null to go back to the campaign default, or optimize: true to hand the sources to source optimization (requires a target_cpa on the campaign).","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source_ids":{"type":"array","description":"Source (website) IDs, as they appear in the Spend Report API source_id column. Up to 50 per call, the same as one page in the dashboard.","items":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,40}$"},"minItems":1,"maxItems":50,"uniqueItems":true},"bid":{"anyOf":[{"type":"number","minimum":0.1,"maximum":25,"description":"USD per click. Minimum $0.10, or $0.30 when the audience targets subscribers newer than 7 days or uses age/gender."},{"type":"null"}],"description":"USD per click, at most 3x the campaign's default bid. null resets to the default."},"optimize":{"type":"boolean"},"dry_run":{"type":"boolean","default":false,"description":"Check the request and report what would change, without changing anything."}},"required":["source_ids"],"additionalProperties":false}}}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}},"/v1/campaigns/{campaign_id}/sources/block":{"post":{"operationId":"block_sources","summary":"Block sources","description":"Blocks up to 50 sources on a block-list campaign so it stops buying their traffic.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source_ids":{"type":"array","description":"Source (website) IDs, as they appear in the Spend Report API source_id column. Up to 50 per call, the same as one page in the dashboard.","items":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,40}$"},"minItems":1,"maxItems":50,"uniqueItems":true},"dry_run":{"type":"boolean","default":false,"description":"Check the request and report what would change, without changing anything."}},"required":["source_ids"],"additionalProperties":false}}}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}},"/v1/campaigns/{campaign_id}/sources/unblock":{"post":{"operationId":"unblock_sources","summary":"Unblock sources","description":"Removes sources from a block-list campaign's blocked list.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source_ids":{"type":"array","description":"Source (website) IDs, as they appear in the Spend Report API source_id column. Up to 50 per call, the same as one page in the dashboard.","items":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,40}$"},"minItems":1,"maxItems":50,"uniqueItems":true},"dry_run":{"type":"boolean","default":false,"description":"Check the request and report what would change, without changing anything."}},"required":["source_ids"],"additionalProperties":false}}}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}},"/v1/campaigns/{campaign_id}/sources/allow":{"post":{"operationId":"allow_sources","summary":"Allow sources","description":"Adds up to 50 sources to an allow-list campaign, which only buys traffic from allowed sources.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source_ids":{"type":"array","description":"Source (website) IDs, as they appear in the Spend Report API source_id column. Up to 50 per call, the same as one page in the dashboard.","items":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,40}$"},"minItems":1,"maxItems":50,"uniqueItems":true},"dry_run":{"type":"boolean","default":false,"description":"Check the request and report what would change, without changing anything."}},"required":["source_ids"],"additionalProperties":false}}}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}},"/v1/campaigns/{campaign_id}/sources/disallow":{"post":{"operationId":"disallow_sources","summary":"Disallow sources","description":"Removes sources from an allow-list campaign. Refused if it would remove the last allowed source, because that would make the campaign serve everywhere.","x-required-scope":"write","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source_ids":{"type":"array","description":"Source (website) IDs, as they appear in the Spend Report API source_id column. Up to 50 per call, the same as one page in the dashboard.","items":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,40}$"},"minItems":1,"maxItems":50,"uniqueItems":true},"dry_run":{"type":"boolean","default":false,"description":"Check the request and report what would change, without changing anything."}},"required":["source_ids"],"additionalProperties":false}}}},"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","pattern":"^C\\d{7,10}$","description":"Campaign ID, e.g. C0001234 (the ID shown in the dashboard and the Spend Report API)."}}]}}}}