{"openapi":"3.1.0","info":{"title":"Koast API","version":"1.0.0","description":"The Koast REST API. Every brand-scoped resource lives under `/v1/brands/{brandId}`. Lists are cursor-paginated, errors share one envelope, and every response carries a `Koast-Request-Id` header."},"servers":[{"url":"https://api.koast.ai"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Activity"},{"name":"Ad Accounts"},{"name":"Automations"},{"name":"Brands"},{"name":"Copies"},{"name":"Creatives"},{"name":"Integrations"},{"name":"Launches"},{"name":"Pipeline"},{"name":"Snapshot Templates"},{"name":"Structure Templates"},{"name":"Webhooks"},{"name":"Workflows"}],"paths":{"/v1/brands":{"get":{"operationId":"list-my-ad-accounts","summary":"List my ad accounts","description":"Lists the brands the caller can access, one row per brand with its `brandId` and ad account. `connected: false` means the brand has no ad account attached.","tags":["Brands"],"x-koast-required-scope":"read","parameters":[{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"List my ad accounts","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"brandId":{"type":"number"},"brandName":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountName":{"anyOf":[{"type":"string"},{"type":"null"}]},"connected":{"type":"boolean"},"active":{"type":"boolean"},"organizationId":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["brandId","brandName","accountId","accountName","connected","active","organizationId"],"additionalProperties":false}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["accounts","nextCursor"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/activity":{"get":{"operationId":"get-team-activity-log","summary":"Get team activity log","description":"Returns the team activity log for the brand, who changed what and when, over the last `days` days. Filter by `userId` or `entityId`. `activities` is the cursor-paginated collection (`limit`, `cursor`, `nextCursor`); `summary` counts the activities of the returned page.","tags":["Activity"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"accountId","in":"query","required":false,"description":"Ad account id (e.g. act_1234 on Meta). Required when no single brand is locked in context — get it from listMyAdAccounts.","schema":{"type":"string","minLength":1}},{"name":"days","in":"query","required":false,"schema":{"default":7,"type":"number","minimum":1,"maximum":90}},{"name":"userId","in":"query","required":false,"schema":{"type":"number"}},{"name":"entityId","in":"query","required":false,"schema":{"type":"string"}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"Get team activity log","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"description":"Totals over the activities of this page.","type":"object","properties":{"days":{"type":"number"},"totalEvents":{"type":"number"},"groupedActions":{"type":"number"},"perUser":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}},"perEntity":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}}},"required":["days","totalEvents","groupedActions","perUser","perEntity"],"additionalProperties":{}},"activities":{"description":"The paged collection: one entry per change, newest first. Follow `nextCursor` for the next page.","type":"array","items":{"type":"object","properties":{"userId":{"type":"number"},"userName":{"description":"Who made the change. An API key shows as \"API key: <name>\".","type":"string"},"entityType":{"type":"string","enum":["campaign","adset","ad","unknown"]},"entityId":{"type":"string"},"entityName":{"anyOf":[{"type":"string"},{"type":"null"}]},"action":{"type":"string"},"when":{"description":"ISO time of the change.","type":"string"}},"required":["userId","userName","entityType","entityId","entityName","action","when"],"additionalProperties":{}}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["summary","activities","nextCursor"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/ad-accounts/{accountId}/campaigns":{"get":{"operationId":"list-account-campaigns","summary":"List ad account campaigns","description":"Lists every campaign in the ad account on the ad platform, including those not imported into Koast. Filter by `statusFilter` or by a case-insensitive name substring with `nameQuery`. Values are live reads from the ad platform.","tags":["Ad Accounts"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"accountId","in":"path","required":true,"description":"The ad account id (act_… on Meta, biz_… on Whop).","schema":{"type":"string"}},{"name":"statusFilter","in":"query","required":false,"description":"Filter by status: ACTIVE, PAUSED, ARCHIVED","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},{"name":"nameQuery","in":"query","required":false,"description":"Case-insensitive substring to match campaign names. ALWAYS pass this when the user named a specific campaign (e.g. \"meta test campaign\") — the account can hold hundreds of campaigns and this returns only the matches with their ids.","schema":{"type":"string","minLength":1}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"List ad account campaigns","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"asOf":{"description":"ISO time of the live provider read behind this response. Set on MCP and API responses, which may be served from the short metrics cache.","type":"string"},"campaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"effective_status":{"type":"string"},"objective":{"type":"string"},"brandId":{"anyOf":[{"type":"string"},{"type":"number"}]},"budget":{"anyOf":[{"type":"object","properties":{"period":{"type":"string"},"amountMinorUnits":{"type":"number"}},"additionalProperties":false},{"type":"null"}]},"budgetLevel":{"type":"string"}},"additionalProperties":{}}},"totalInAccount":{"type":"number"},"matched":{"type":"number"},"nameQuery":{"anyOf":[{"type":"string"},{"type":"null"}]},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["campaigns","totalInAccount","matched","nameQuery","nextCursor"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/ad-accounts/{accountId}/lead-forms":{"get":{"operationId":"list-lead-forms","summary":"List lead forms","description":"Lists the instant lead forms that exist on the Page `pageId`, as `{ id, name }`. Values are live reads from the ad platform.","tags":["Ad Accounts"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"accountId","in":"path","required":true,"description":"The ad account id (act_… on Meta, biz_… on Whop).","schema":{"type":"string"}},{"name":"pageId","in":"query","required":true,"description":"Page id that owns the lead forms (from assets.facebookPage.id or getAvailableOptions).","schema":{"type":"string","minLength":1}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"List lead forms","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"leadForms":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","name"],"additionalProperties":false}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["leadForms","nextCursor"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/ad-accounts/{accountId}/naming-convention":{"get":{"operationId":"get-account-naming-convention","summary":"Get account naming convention","description":"Returns the naming convention templates configured for the ad account at the campaign, ad set and ad levels, with examples.","tags":["Ad Accounts"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"accountId","in":"path","required":true,"description":"The ad account id (act_… on Meta, biz_… on Whop).","schema":{"type":"string"}}],"responses":{"200":{"description":"Get account naming convention","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/ad-accounts/{accountId}/options":{"get":{"operationId":"get-available-options","summary":"Get asset and targeting options","description":"Lists the selectable assets and targeting values on the ad account for `optionType` (`pixels`, `facebookPages`, `instagramAccounts`, `audiences`, `interests`, `locations` or `conversionEvents`), optionally filtered by `query`.","tags":["Ad Accounts"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"accountId","in":"path","required":true,"description":"The ad account id (act_… on Meta, biz_… on Whop).","schema":{"type":"string"}},{"name":"optionType","in":"query","required":true,"description":"Type of option: pixels, facebookPages, instagramAccounts, audiences, interests, locations, conversionEvents","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"description":"Search query to filter results","schema":{"type":"string"}}],"responses":{"200":{"description":"Get asset and targeting options","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{},"additionalProperties":{}},{"type":"array","items":{}}]}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/ad-accounts/{accountId}/overview":{"get":{"operationId":"get-account-overview","summary":"Get account overview","description":"Rolls up spend and results across the Koast launches on the ad account for `datePreset` (default `today`). Campaigns not launched through Koast are not counted, and at most 10 launches are sampled. Values are live reads from the ad platform.","tags":["Ad Accounts"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"accountId","in":"path","required":true,"description":"The ad account id (act_… on Meta, biz_… on Whop).","schema":{"type":"string"}},{"name":"datePreset","in":"query","required":false,"description":"Reporting date preset. If omitted, defaults to today. Use last_7d / last_28d / last_30d / last_90d / this_month / last_month as needed. Every last_Nd preset ENDS YESTERDAY and does not include today, so a campaign that only started yesterday reads as zero under last_7d — use today or yesterday to see it, and say which window a number came from. For \"lifetime\" / \"all time\" / \"since launch\", use maximum — NOT \"lifetime\" (it is not an accepted value). Arbitrary start/end date ranges are not supported by the backend.","schema":{"type":"string","enum":["today","yesterday","this_week_sun_today","last_7d","last_14d","last_28d","last_30d","last_90d","this_month","last_month","maximum"]}}],"responses":{"200":{"description":"Get account overview","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"asOf":{"description":"ISO time of the live provider read behind this response. Set on MCP and API responses, which may be served from the short metrics cache.","type":"string"}},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/automations":{"get":{"operationId":"list-automations","summary":"List automations","description":"Lists the brand's monitoring automations, rule-based watchers that run actions such as pause or notify on live campaigns. Filter with `status`; results are cursor-paginated.","tags":["Automations"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"List automations","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"automations":{"type":"array","items":{"type":"object","properties":{"automationId":{"type":"number"},"automationName":{"type":"string"},"status":{"type":"string"},"action":{"type":"string"},"actionLevel":{"type":"string"},"frequency":{"type":"string"}},"required":["automationId","automationName","status","action","actionLevel","frequency"],"additionalProperties":{}}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["automations","nextCursor"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"save-automation","summary":"Save automation","description":"Creates a monitoring automation from the spec in `automation`, or updates an existing one when `automationId` is given. On create the spec must be complete (name, actionLevel, actions, frequency, apiOutageAction, rules); on update only the fields you pass are changed.","tags":["Automations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"automationId":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"},"automation":{"description":"Whole monitoring automation spec: { name, actionLevel, actions[], frequency, apiOutageAction, rules[], campaignIds?, status?, applyToNewCampaigns? }","type":"object","properties":{},"additionalProperties":{}}},"required":["automation"],"additionalProperties":false}}}},"responses":{"200":{"description":"Save automation","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/automations/{automationId}":{"delete":{"operationId":"delete-automation","summary":"Delete automation","description":"Permanently deletes the monitoring automation.","tags":["Automations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"automationId","in":"path","required":true,"schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}}],"responses":{"200":{"description":"Delete automation","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"automationId":{"type":"string"}},"required":["automationId"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"get":{"operationId":"get-automation","summary":"Get automation","description":"Returns one monitoring automation: its rules, actions, frequency, scope and status.","tags":["Automations"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"automationId","in":"path","required":true,"schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}}],"responses":{"200":{"description":"Get automation","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/automations/{automationId}/status":{"patch":{"operationId":"set-automation-status","summary":"Set automation status","description":"Sets the automation's `status` to `ACTIVE` (armed) or `PAUSED`.","tags":["Automations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"automationId","in":"path","required":true,"schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ACTIVE","PAUSED"]}},"required":["status"],"additionalProperties":false}}}},"responses":{"200":{"description":"Set automation status","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/copies":{"post":{"operationId":"generate-copy","summary":"Generate ad copy","description":"Generates ad copy (headlines, primary text, descriptions) for `platform` using the brand's stored context, and stores it under a copy generation id. Pass `creativeIds` to match the copy to those creatives. No ad changes until the id is attached to an ad.","tags":["Copies"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"platform":{"description":"Target platform. Only facebook and instagram are supported — the value is stored as the copy's platform label.","type":"string","enum":["facebook","instagram"]},"tone":{"description":"Tone: professional, casual, urgent, friendly. Optional — defaults to brand voice.","type":"string"},"angle":{"description":"Marketing angle. Optional — only pass if the user requested a specific framing.","type":"string"},"productDescription":{"description":"Optional override. Backend auto-fills product context from brand (name, URL, business type, voice). Only pass this if the user gave specifics that should take precedence over brand defaults.","type":"string"},"creativeIds":{"description":"IDs of creatives attached to this chat. When present, the backend pulls each creative's name + stored visual analysis and feeds it to the copy LLM so the copy matches what the ad actually shows. Pass whenever creatives are listed in the ## Attachments block. Never call readDocument on image MIME types — use this param instead.","type":"array","items":{"type":"number"}}},"required":["platform"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate ad copy","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/copies/{copyId}":{"get":{"operationId":"get-copy","summary":"Get generated ad copy","description":"Returns a previously generated copy by its id: headlines, primary text, descriptions and variations.","tags":["Copies"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"copyId","in":"path","required":true,"description":"ID of the copy generation","schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}}],"responses":{"200":{"description":"Get generated ad copy","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/creatives":{"get":{"operationId":"list-creatives","summary":"List creatives","description":"Lists the images and videos in the brand's creative library, newest first, with the `creativeId` used when attaching a creative to an ad. Filter with `search` and `kind`, or pass `creativeIds` to fetch a specific set. A creative with `ready: false` is a video still processing and cannot be attached yet.","tags":["Creatives"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"search","in":"query","required":false,"description":"Filter by creative or file name. Omit to list everything, newest first.","schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"kind","in":"query","required":false,"description":"Narrow to images or to videos. Defaults to ALL.","schema":{"type":"string","enum":["ALL","IMAGES","VIDEOS"]}},{"name":"creativeIds","in":"query","required":false,"description":"Look up an explicit set of creative ids instead of browsing. This is also what the gallery sends when a user picks creatives in it, so the ids reach you.","schema":{"maxItems":60,"type":"array","items":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"style":"form","explode":true},{"name":"page","in":"query","required":false,"description":"1-based page. Defaults to 1.","schema":{"type":"integer","minimum":1,"maximum":9007199254740991}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"List creatives","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"creatives":{"type":"array","items":{"type":"object","properties":{"creativeId":{"description":"Pass this as `creativeId` to addAds, distributeCreative or swapCreatives.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"name":{"type":"string"},"kind":{"type":"string","enum":["image","video"]},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"previewUrl":{"description":"The url the gallery may render. Null when the asset is not on Koast storage — the creative still exists and still works in an ad.","anyOf":[{"type":"string"},{"type":"null"}]},"previewable":{"type":"boolean"},"width":{"anyOf":[{"type":"number"},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"aspectRatio":{"anyOf":[{"type":"string"},{"type":"null"}]},"durationSeconds":{"anyOf":[{"type":"number"},{"type":"null"}]},"sizeBytes":{"anyOf":[{"type":"number"},{"type":"null"}]},"isImported":{"type":"boolean"},"ready":{"description":"False while a video is still being processed. A creative that is not ready cannot be attached to an ad yet.","type":"boolean"},"createdAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["creativeId","name","kind","url","previewUrl","previewable","width","height","aspectRatio","durationSeconds","sizeBytes","isImported","ready","createdAt"],"additionalProperties":{}}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"selection":{"description":"True when the call named explicit creativeIds, i.e. it is a selection rather than a browse.","type":"boolean"},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["creatives","total","page","pages","selection","nextCursor"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"upload-creative","summary":"Upload creative","description":"Stores an image in the brand's creative library and returns its `creativeId`. Pass exactly one of `imageUrl` (a public https URL that Koast downloads and re-hosts) or `fileData` (base64 bytes, with `contentType` and `fileName`). Uploading bytes the brand already holds returns the existing creative with `reused: true`. Images only; no ad is created or changed.","tags":["Creatives"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"imageUrl":{"description":"Public https url of the image to store. Koast downloads it and re-hosts it, so a link that later expires does not rot the ad. Use this whenever the user gives you a link.","type":"string","minLength":1},"fileData":{"description":"Standard base64 of the image bytes, with NO data-url prefix. Intended for the Koast creative gallery, which reads a dropped file and sends it here. Do not attempt to write this yourself — if the user attached an image to the chat, say you cannot read its bytes and ask for a link or for them to drop it in the gallery.","type":"string","minLength":1,"maxLength":13333338},"contentType":{"description":"Media type of `fileData`. Required with fileData, ignored with imageUrl.","type":"string","enum":["image/jpeg","image/png","image/webp","image/gif"]},"fileName":{"description":"File name to store it under. Required with fileData; defaults to the url's own name otherwise.","type":"string","minLength":1,"maxLength":200},"name":{"description":"Display name for the creative. Defaults to the file name.","type":"string","minLength":1,"maxLength":200}},"additionalProperties":false}}}},"responses":{"200":{"description":"Upload creative","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"creativeId":{"description":"Pass this as `creativeId` to addAds, distributeCreative or swapCreatives.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"name":{"type":"string"},"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"previewUrl":{"description":"The url a Koast view may render, filtered through the same host list that writes the view CSP. Null means the asset is stored somewhere the iframe may not load — the creative still works in an ad.","anyOf":[{"type":"string"},{"type":"null"}]},"width":{"anyOf":[{"type":"number"},{"type":"null"}]},"height":{"anyOf":[{"type":"number"},{"type":"null"}]},"reused":{"description":"True when the brand already held these exact bytes, so the existing creative was returned instead of a duplicate being made.","type":"boolean"}},"required":["creativeId","name","url","previewUrl","width","height","reused"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/integrations/clickflare":{"delete":{"operationId":"disconnect-clickflare","summary":"Disconnect ClickFlare","description":"Disconnects ClickFlare from the brand: removes the API key, the campaign mappings and the spend push setting. Conversion and revenue data already pulled from ClickFlare is kept. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Disconnect ClickFlare","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"disconnected":{"type":"boolean","const":true}},"required":["disconnected"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"connect-clickflare","summary":"Connect ClickFlare","description":"Connects ClickFlare to the brand. Koast checks the key against ClickFlare, reads the account timezone and currency, and detects which tracking fields carry the ad platform campaign, ad set and ad ids. Sending a new key to a connected brand replaces the key and keeps the settings. Answers 422 when ClickFlare rejects the key. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"description":"A ClickFlare API key (ClickFlare → Settings → API keys).","type":"string","minLength":1,"maxLength":512},"workspaceIds":{"description":"ClickFlare workspace ids to read. An empty list reads every workspace of the account.","maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}}},"required":["apiKey"],"additionalProperties":false}}}},"responses":{"200":{"description":"Connect ClickFlare","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"connected":{"description":"Whether a ClickFlare API key is connected to the brand.","type":"boolean"},"maskedApiKey":{"anyOf":[{"type":"string"},{"type":"null"}]},"timezone":{"description":"The ClickFlare account timezone used for reports. Null means UTC is used.","anyOf":[{"type":"string"},{"type":"null"}]},"currency":{"anyOf":[{"type":"string"},{"type":"null"}]},"workspaceIds":{"type":"array","items":{"type":"string"}},"trackingFields":{"type":"object","properties":{"campaign":{"anyOf":[{"type":"string"},{"type":"null"}]},"adset":{"anyOf":[{"type":"string"},{"type":"null"}]},"ad":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["campaign","adset","ad"],"additionalProperties":false},"trackingFieldsSource":{"description":"How each tracking field was chosen: `data` (matched Koast ids in ClickFlare traffic), `traffic_source` (the traffic source template), or `manual`.","type":"object","properties":{"campaign":{"anyOf":[{"type":"string","enum":["data","traffic_source","manual"]},{"type":"null"}]},"adset":{"anyOf":[{"type":"string","enum":["data","traffic_source","manual"]},{"type":"null"}]},"ad":{"anyOf":[{"type":"string","enum":["data","traffic_source","manual"]},{"type":"null"}]}},"required":["campaign","adset","ad"],"additionalProperties":false},"lastPullAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPullError":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPullRows":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["brandId","connected","maskedApiKey","timezone","currency","workspaceIds","trackingFields","trackingFieldsSource","lastPullAt","lastPullError","lastPullRows"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/integrations/clickflare/mappings":{"get":{"operationId":"list-clickflare-campaign-mappings","summary":"List ClickFlare campaign mappings","description":"Returns the campaign mappings used by the ClickFlare spend push: automatic ones derived from the ClickFlare traffic of the last days (the campaign tracking field), manual ones, the Koast campaigns with spend that have no mapping (with the reason), and the ClickFlare campaigns to pick from. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}}],"responses":{"200":{"description":"List ClickFlare campaign mappings","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"mappings":{"type":"array","items":{"type":"object","properties":{"providerCampaignId":{"type":"string"},"koastCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the campaign runs on, e.g. `meta` or `whop`.","type":"string"},{"type":"null"}]},"cfCampaignId":{"type":"string"},"cfCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"source":{"type":"string","enum":["auto","manual"]},"pushable":{"type":"boolean"},"skipReason":{"anyOf":[{"type":"string","enum":["clickflare_campaign_missing","mixed_account_timezones","currency_not_usd","spend_unavailable","no_visits"]},{"type":"null"}]},"updatedAt":{"type":"string"},"updatedByUserId":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["providerCampaignId","koastCampaignName","provider","cfCampaignId","cfCampaignName","source","pushable","skipReason","updatedAt","updatedByUserId"],"additionalProperties":false}},"unmatched":{"type":"array","items":{"type":"object","properties":{"providerCampaignId":{"type":"string"},"koastCampaignName":{"type":"string"},"provider":{"description":"The ad platform the campaign runs on, e.g. `meta` or `whop`.","type":"string"},"reason":{"type":"string","enum":["ambiguous","provider_ids_not_in_clickflare","not_seen_in_clickflare"]},"candidates":{"type":"array","items":{"type":"object","properties":{"cfCampaignId":{"type":"string"},"cfCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"visits":{"type":"number"}},"required":["cfCampaignId","cfCampaignName","visits"],"additionalProperties":false}}},"required":["providerCampaignId","koastCampaignName","provider","reason","candidates"],"additionalProperties":false}},"clickflareCampaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}}},"required":["brandId","mappings","unmatched","clickflareCampaigns"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/integrations/clickflare/mappings/{providerCampaignId}":{"put":{"operationId":"update-clickflare-campaign-mapping","summary":"Update ClickFlare campaign mapping","description":"Sets the ClickFlare campaign that receives the spend of an ad platform campaign. A manual mapping wins over the automatic one. Send `cfCampaignId: null` to remove the manual mapping. Returns the full mapping list. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"providerCampaignId","in":"path","required":true,"description":"The ad platform campaign id (a Meta campaign id, or a Whop `adcamp_…` id).","schema":{"type":"string","minLength":1,"maxLength":191}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cfCampaignId":{"description":"The ClickFlare campaign id to push this campaign's spend into. Null removes the manual mapping and falls back to the automatic one, if any.","anyOf":[{"type":"string","minLength":1,"maxLength":64},{"type":"null"}]}},"required":["cfCampaignId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Update ClickFlare campaign mapping","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"mappings":{"type":"array","items":{"type":"object","properties":{"providerCampaignId":{"type":"string"},"koastCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the campaign runs on, e.g. `meta` or `whop`.","type":"string"},{"type":"null"}]},"cfCampaignId":{"type":"string"},"cfCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"source":{"type":"string","enum":["auto","manual"]},"pushable":{"type":"boolean"},"skipReason":{"anyOf":[{"type":"string","enum":["clickflare_campaign_missing","mixed_account_timezones","currency_not_usd","spend_unavailable","no_visits"]},{"type":"null"}]},"updatedAt":{"type":"string"},"updatedByUserId":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["providerCampaignId","koastCampaignName","provider","cfCampaignId","cfCampaignName","source","pushable","skipReason","updatedAt","updatedByUserId"],"additionalProperties":false}},"unmatched":{"type":"array","items":{"type":"object","properties":{"providerCampaignId":{"type":"string"},"koastCampaignName":{"type":"string"},"provider":{"description":"The ad platform the campaign runs on, e.g. `meta` or `whop`.","type":"string"},"reason":{"type":"string","enum":["ambiguous","provider_ids_not_in_clickflare","not_seen_in_clickflare"]},"candidates":{"type":"array","items":{"type":"object","properties":{"cfCampaignId":{"type":"string"},"cfCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"visits":{"type":"number"}},"required":["cfCampaignId","cfCampaignName","visits"],"additionalProperties":false}}},"required":["providerCampaignId","koastCampaignName","provider","reason","candidates"],"additionalProperties":false}},"clickflareCampaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}}},"required":["brandId","mappings","unmatched","clickflareCampaigns"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/integrations/clickflare/push":{"get":{"operationId":"get-clickflare-cost-push","summary":"Get ClickFlare spend push","description":"Returns the ClickFlare spend push setting of the brand and the outcome of the last push: when it ran, how many ClickFlare campaigns it updated, the last error and how many Koast campaigns with spend have no ClickFlare campaign mapped. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Get ClickFlare spend push","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"connected":{"description":"Whether a ClickFlare API key is connected to the brand.","type":"boolean"},"enabled":{"type":"boolean"},"disabledReason":{"description":"Why Koast turned the push off itself: `unauthorized` (ClickFlare rejected the key) or `refused` (ClickFlare refused the cost upload).","anyOf":[{"type":"string"},{"type":"null"}]},"lastPushAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastCampaignsPushed":{"description":"ClickFlare campaigns whose spend for today the last cycle uploaded.","type":"number"},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastErrorAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"unmatchedCount":{"description":"Koast campaigns with spend and no ClickFlare campaign mapped.","type":"number"},"schedule":{"type":"object","properties":{"cron":{"type":"string"},"finalLocalHour":{"description":"Local hour of the ad account at or after which yesterday's final push is sent.","type":"number"},"requestIntervalSeconds":{"description":"Spacing between two cost uploads on one ClickFlare API key.","type":"number"}},"required":["cron","finalLocalHour","requestIntervalSeconds"],"additionalProperties":false}},"required":["brandId","connected","enabled","disabledReason","lastPushAt","lastCampaignsPushed","lastError","lastErrorAt","unmatchedCount","schedule"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"put":{"operationId":"update-clickflare-cost-push","summary":"Update ClickFlare spend push","description":"Turns the spend push into ClickFlare on or off. When on, Koast uploads the spend of every mapped ClickFlare campaign for today every hour, and yesterday's final spend once after midnight in the ad account timezone. Each upload replaces the cost ClickFlare holds for that window. ClickFlare accepts USD only. ClickFlare must be connected and a campaign tracking field set first. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"description":"Turn the hourly spend push into ClickFlare on or off for this brand.","type":"boolean"}},"required":["enabled"],"additionalProperties":false}}}},"responses":{"200":{"description":"Update ClickFlare spend push","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"connected":{"description":"Whether a ClickFlare API key is connected to the brand.","type":"boolean"},"enabled":{"type":"boolean"},"disabledReason":{"description":"Why Koast turned the push off itself: `unauthorized` (ClickFlare rejected the key) or `refused` (ClickFlare refused the cost upload).","anyOf":[{"type":"string"},{"type":"null"}]},"lastPushAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastCampaignsPushed":{"description":"ClickFlare campaigns whose spend for today the last cycle uploaded.","type":"number"},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastErrorAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"unmatchedCount":{"description":"Koast campaigns with spend and no ClickFlare campaign mapped.","type":"number"},"schedule":{"type":"object","properties":{"cron":{"type":"string"},"finalLocalHour":{"description":"Local hour of the ad account at or after which yesterday's final push is sent.","type":"number"},"requestIntervalSeconds":{"description":"Spacing between two cost uploads on one ClickFlare API key.","type":"number"}},"required":["cron","finalLocalHour","requestIntervalSeconds"],"additionalProperties":false}},"required":["brandId","connected","enabled","disabledReason","lastPushAt","lastCampaignsPushed","lastError","lastErrorAt","unmatchedCount","schedule"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/integrations/clickflare/settings":{"get":{"operationId":"get-clickflare-settings","summary":"Get ClickFlare settings","description":"Returns the ClickFlare connection of the brand: the masked API key, the ClickFlare account timezone and currency, the workspaces Koast reads, which `trackingField1..20` carries the campaign, ad set and ad ids (and how each was chosen), and the outcome of the last report pull. Answers 404 when ClickFlare is not connected. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Get ClickFlare settings","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"connected":{"description":"Whether a ClickFlare API key is connected to the brand.","type":"boolean"},"maskedApiKey":{"anyOf":[{"type":"string"},{"type":"null"}]},"timezone":{"description":"The ClickFlare account timezone used for reports. Null means UTC is used.","anyOf":[{"type":"string"},{"type":"null"}]},"currency":{"anyOf":[{"type":"string"},{"type":"null"}]},"workspaceIds":{"type":"array","items":{"type":"string"}},"trackingFields":{"type":"object","properties":{"campaign":{"anyOf":[{"type":"string"},{"type":"null"}]},"adset":{"anyOf":[{"type":"string"},{"type":"null"}]},"ad":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["campaign","adset","ad"],"additionalProperties":false},"trackingFieldsSource":{"description":"How each tracking field was chosen: `data` (matched Koast ids in ClickFlare traffic), `traffic_source` (the traffic source template), or `manual`.","type":"object","properties":{"campaign":{"anyOf":[{"type":"string","enum":["data","traffic_source","manual"]},{"type":"null"}]},"adset":{"anyOf":[{"type":"string","enum":["data","traffic_source","manual"]},{"type":"null"}]},"ad":{"anyOf":[{"type":"string","enum":["data","traffic_source","manual"]},{"type":"null"}]}},"required":["campaign","adset","ad"],"additionalProperties":false},"lastPullAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPullError":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPullRows":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["brandId","connected","maskedApiKey","timezone","currency","workspaceIds","trackingFields","trackingFieldsSource","lastPullAt","lastPullError","lastPullRows"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"patch":{"operationId":"update-clickflare-settings","summary":"Update ClickFlare settings","description":"Changes the ClickFlare workspaces Koast reads and overrides the tracking fields that carry the ad platform campaign, ad set and ad ids. Only the fields sent change. A tracking field set here is marked `manual` and is never replaced by detection; null clears it. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"workspaceIds":{"description":"ClickFlare workspace ids to read. An empty list reads every workspace of the account.","maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"trackingFields":{"description":"Overrides the detected tracking fields. A role set here is marked `manual`; null clears it.","type":"object","properties":{"campaign":{"description":"The ClickFlare tracking field that carries the ad platform campaign id.","anyOf":[{"type":"string","enum":["trackingField1","trackingField2","trackingField3","trackingField4","trackingField5","trackingField6","trackingField7","trackingField8","trackingField9","trackingField10","trackingField11","trackingField12","trackingField13","trackingField14","trackingField15","trackingField16","trackingField17","trackingField18","trackingField19","trackingField20"]},{"type":"null"}]},"adset":{"description":"The ClickFlare tracking field that carries the ad platform ad set id.","anyOf":[{"type":"string","enum":["trackingField1","trackingField2","trackingField3","trackingField4","trackingField5","trackingField6","trackingField7","trackingField8","trackingField9","trackingField10","trackingField11","trackingField12","trackingField13","trackingField14","trackingField15","trackingField16","trackingField17","trackingField18","trackingField19","trackingField20"]},{"type":"null"}]},"ad":{"description":"The ClickFlare tracking field that carries the ad platform ad id.","anyOf":[{"type":"string","enum":["trackingField1","trackingField2","trackingField3","trackingField4","trackingField5","trackingField6","trackingField7","trackingField8","trackingField9","trackingField10","trackingField11","trackingField12","trackingField13","trackingField14","trackingField15","trackingField16","trackingField17","trackingField18","trackingField19","trackingField20"]},{"type":"null"}]}},"additionalProperties":false}},"additionalProperties":false}}}},"responses":{"200":{"description":"Update ClickFlare settings","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"connected":{"description":"Whether a ClickFlare API key is connected to the brand.","type":"boolean"},"maskedApiKey":{"anyOf":[{"type":"string"},{"type":"null"}]},"timezone":{"description":"The ClickFlare account timezone used for reports. Null means UTC is used.","anyOf":[{"type":"string"},{"type":"null"}]},"currency":{"anyOf":[{"type":"string"},{"type":"null"}]},"workspaceIds":{"type":"array","items":{"type":"string"}},"trackingFields":{"type":"object","properties":{"campaign":{"anyOf":[{"type":"string"},{"type":"null"}]},"adset":{"anyOf":[{"type":"string"},{"type":"null"}]},"ad":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["campaign","adset","ad"],"additionalProperties":false},"trackingFieldsSource":{"description":"How each tracking field was chosen: `data` (matched Koast ids in ClickFlare traffic), `traffic_source` (the traffic source template), or `manual`.","type":"object","properties":{"campaign":{"anyOf":[{"type":"string","enum":["data","traffic_source","manual"]},{"type":"null"}]},"adset":{"anyOf":[{"type":"string","enum":["data","traffic_source","manual"]},{"type":"null"}]},"ad":{"anyOf":[{"type":"string","enum":["data","traffic_source","manual"]},{"type":"null"}]}},"required":["campaign","adset","ad"],"additionalProperties":false},"lastPullAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPullError":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastPullRows":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["brandId","connected","maskedApiKey","timezone","currency","workspaceIds","trackingFields","trackingFieldsSource","lastPullAt","lastPullError","lastPullRows"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/integrations/redtrack/mappings":{"get":{"operationId":"list-redtrack-campaign-mappings","summary":"List RedTrack campaign mappings","description":"Returns the campaign mappings used by the RedTrack spend push: automatic ones derived from the RedTrack clicks of the last days (`sub3`, falling back to `rt_campaign_id`), manual ones, the Koast campaigns with spend that have no mapping (with the reason), and the RedTrack campaigns to pick from. Any member who can access the brand can read it; changes require an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}}],"responses":{"200":{"description":"List RedTrack campaign mappings","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"mappings":{"type":"array","items":{"type":"object","properties":{"providerCampaignId":{"type":"string"},"koastCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the campaign runs on, e.g. `meta` or `whop`.","type":"string"},{"type":"null"}]},"rtCampaignId":{"type":"string"},"rtCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"source":{"type":"string","enum":["auto","manual"]},"matchedOn":{"anyOf":[{"type":"string","enum":["sub3","rt_campaign_id"]},{"type":"null"}]},"pushable":{"type":"boolean"},"skipReason":{"anyOf":[{"type":"string","enum":["shared_campaign_without_sub3","redtrack_auto_cost","redtrack_campaign_missing"]},{"type":"null"}]},"updatedAt":{"type":"string"},"updatedByUserId":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["providerCampaignId","koastCampaignName","provider","rtCampaignId","rtCampaignName","source","matchedOn","pushable","skipReason","updatedAt","updatedByUserId"],"additionalProperties":false}},"unmatched":{"type":"array","items":{"type":"object","properties":{"providerCampaignId":{"type":"string"},"koastCampaignName":{"type":"string"},"provider":{"description":"The ad platform the campaign runs on, e.g. `meta` or `whop`.","type":"string"},"reason":{"type":"string","enum":["ambiguous","provider_ids_not_in_redtrack","not_seen_in_redtrack"]},"candidates":{"type":"array","items":{"type":"object","properties":{"rtCampaignId":{"type":"string"},"rtCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"clicks":{"type":"number"}},"required":["rtCampaignId","rtCampaignName","clicks"],"additionalProperties":false}}},"required":["providerCampaignId","koastCampaignName","provider","reason","candidates"],"additionalProperties":false}},"redtrackCampaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"autoCostUpdate":{"type":"boolean"}},"required":["id","title","autoCostUpdate"],"additionalProperties":false}}},"required":["brandId","mappings","unmatched","redtrackCampaigns"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/integrations/redtrack/mappings/{providerCampaignId}":{"put":{"operationId":"update-redtrack-campaign-mapping","summary":"Update RedTrack campaign mapping","description":"Sets the RedTrack campaign that receives the spend of an ad platform campaign. A manual mapping wins over the automatic one. Send `rtCampaignId: null` to remove the manual mapping. Returns the full mapping list. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"providerCampaignId","in":"path","required":true,"description":"The ad platform campaign id (a Meta campaign id, or a Whop `adcamp_…` id).","schema":{"type":"string","minLength":1,"maxLength":191}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"rtCampaignId":{"description":"The RedTrack campaign id to push this campaign's spend into. Null removes the manual mapping and falls back to the automatic one, if any.","anyOf":[{"type":"string","minLength":1,"maxLength":64},{"type":"null"}]}},"required":["rtCampaignId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Update RedTrack campaign mapping","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"mappings":{"type":"array","items":{"type":"object","properties":{"providerCampaignId":{"type":"string"},"koastCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the campaign runs on, e.g. `meta` or `whop`.","type":"string"},{"type":"null"}]},"rtCampaignId":{"type":"string"},"rtCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"source":{"type":"string","enum":["auto","manual"]},"matchedOn":{"anyOf":[{"type":"string","enum":["sub3","rt_campaign_id"]},{"type":"null"}]},"pushable":{"type":"boolean"},"skipReason":{"anyOf":[{"type":"string","enum":["shared_campaign_without_sub3","redtrack_auto_cost","redtrack_campaign_missing"]},{"type":"null"}]},"updatedAt":{"type":"string"},"updatedByUserId":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["providerCampaignId","koastCampaignName","provider","rtCampaignId","rtCampaignName","source","matchedOn","pushable","skipReason","updatedAt","updatedByUserId"],"additionalProperties":false}},"unmatched":{"type":"array","items":{"type":"object","properties":{"providerCampaignId":{"type":"string"},"koastCampaignName":{"type":"string"},"provider":{"description":"The ad platform the campaign runs on, e.g. `meta` or `whop`.","type":"string"},"reason":{"type":"string","enum":["ambiguous","provider_ids_not_in_redtrack","not_seen_in_redtrack"]},"candidates":{"type":"array","items":{"type":"object","properties":{"rtCampaignId":{"type":"string"},"rtCampaignName":{"anyOf":[{"type":"string"},{"type":"null"}]},"clicks":{"type":"number"}},"required":["rtCampaignId","rtCampaignName","clicks"],"additionalProperties":false}}},"required":["providerCampaignId","koastCampaignName","provider","reason","candidates"],"additionalProperties":false}},"redtrackCampaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"autoCostUpdate":{"type":"boolean"}},"required":["id","title","autoCostUpdate"],"additionalProperties":false}}},"required":["brandId","mappings","unmatched","redtrackCampaigns"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/integrations/redtrack/push":{"get":{"operationId":"get-redtrack-cost-push","summary":"Get RedTrack spend push","description":"Returns the RedTrack spend push setting of the brand and the outcome of the last push: when it ran, how many campaigns it placed, the last error and how many Koast campaigns with spend have no RedTrack campaign mapped. Any member who can access the brand can read it; changes require an organization owner or admin. `disabledReason` is `unauthorized` or `refused` when RedTrack refused the key, and `key_changed` when the brand's RedTrack key was changed (an owner or admin turns it back on).","tags":["Integrations"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Get RedTrack spend push","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"connected":{"description":"Whether a RedTrack API key is connected to the brand.","type":"boolean"},"enabled":{"type":"boolean"},"disabledReason":{"description":"Why Koast turned the push off itself: `unauthorized` (RedTrack rejected the key) or `refused` (the RedTrack plan does not allow cost updates).","anyOf":[{"type":"string"},{"type":"null"}]},"lastPushAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastCampaignsPushed":{"description":"Campaigns whose spend for today the last cycle placed in RedTrack.","type":"number"},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastErrorAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"unmatchedCount":{"description":"Koast campaigns with spend and no RedTrack campaign mapped.","type":"number"},"schedule":{"type":"object","properties":{"cron":{"type":"string"},"finalLocalHour":{"description":"Local hour of the ad account at or after which yesterday's final push is sent.","type":"number"},"requestIntervalSeconds":{"description":"Spacing between two cost updates on one RedTrack API key.","type":"number"}},"required":["cron","finalLocalHour","requestIntervalSeconds"],"additionalProperties":false}},"required":["brandId","connected","enabled","disabledReason","lastPushAt","lastCampaignsPushed","lastError","lastErrorAt","unmatchedCount","schedule"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"put":{"operationId":"update-redtrack-cost-push","summary":"Update RedTrack spend push","description":"Turns the spend push into RedTrack on or off. When on, Koast places each mapped campaign's spend for today into its RedTrack campaign every hour, and yesterday's final spend once after midnight in the ad account timezone. RedTrack must be connected first. Changing the brand's RedTrack key turns the push off. Requires an organization owner or admin.","tags":["Integrations"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"description":"Turn the hourly spend push into RedTrack on or off for this brand.","type":"boolean"}},"required":["enabled"],"additionalProperties":false}}}},"responses":{"200":{"description":"Update RedTrack spend push","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"brandId":{"type":"number"},"connected":{"description":"Whether a RedTrack API key is connected to the brand.","type":"boolean"},"enabled":{"type":"boolean"},"disabledReason":{"description":"Why Koast turned the push off itself: `unauthorized` (RedTrack rejected the key) or `refused` (the RedTrack plan does not allow cost updates).","anyOf":[{"type":"string"},{"type":"null"}]},"lastPushAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastCampaignsPushed":{"description":"Campaigns whose spend for today the last cycle placed in RedTrack.","type":"number"},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastErrorAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"unmatchedCount":{"description":"Koast campaigns with spend and no RedTrack campaign mapped.","type":"number"},"schedule":{"type":"object","properties":{"cron":{"type":"string"},"finalLocalHour":{"description":"Local hour of the ad account at or after which yesterday's final push is sent.","type":"number"},"requestIntervalSeconds":{"description":"Spacing between two cost updates on one RedTrack API key.","type":"number"}},"required":["cron","finalLocalHour","requestIntervalSeconds"],"additionalProperties":false}},"required":["brandId","connected","enabled","disabledReason","lastPushAt","lastCampaignsPushed","lastError","lastErrorAt","unmatchedCount","schedule"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches":{"get":{"operationId":"list-koast-batches","summary":"List Koast batches","description":"Lists the brand's Koast launches (batches), drafts and published, with their status and campaign, ad set and ad counts. Filter by `status` or by a title substring with `search`.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"accountId","in":"query","required":false,"description":"Ad account id (act_xxx on Meta). Optional — defaults to current page context.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Filter by lifecycle status.","schema":{"type":"string","enum":["DRAFT","IMPORTED","PENDING","RUNNING","COMPLETED","COMPLETED_WITH_ISSUES","ACTION_REQUIRED","FAILED","CANCELLED"]}},{"name":"search","in":"query","required":false,"description":"Substring match on batch title.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"List Koast batches","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"batches":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"updatedAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"campaignsCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"adsetsCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"adsCount":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["id","title","description","status","createdAt","updatedAt","campaignsCount","adsetsCount","adsCount"],"additionalProperties":false}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]},"asOf":{"description":"ISO time of the live provider read behind this response. Set on MCP and API responses, which may be served from the short metrics cache.","type":"string"}},"required":["accountId","total","page","limit","batches","nextCursor"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"create-campaign-launch","summary":"Create campaign launch","description":"Creates an empty launch (batch) under the brand and returns its id. The launch holds no campaigns until you add one. `title` defaults to \"Untitled Batch\".","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"description":"Optional human title; defaults to \"Untitled Batch\" server-side.","type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000}},"additionalProperties":false}}}},"responses":{"200":{"description":"Create campaign launch","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"brandId":{"type":"number"},"brandName":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","title","brandId","brandName","accountId"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/clone":{"post":{"operationId":"clone-live-campaign","summary":"Clone live campaign","description":"Deep-copies the ad platform campaign `providerCampaignId` (ad sets, ads, copy and creatives) into `count` new launches as editable drafts with all platform ids stripped. Each clone gets its own launch, since a launch holds one campaign. Returns the new `campaignLaunchId` of each clone.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"providerCampaignId":{"description":"Campaign id to clone on the ad platform (the raw `id` from listAccountCampaigns rows).","type":"string","minLength":1},"count":{"description":"How many cloned batches to create (1 batch per clone, max 20).","default":1,"type":"integer","minimum":1,"maximum":20},"titlePrefix":{"description":"Optional title prefix for the cloned batches; a copy index is appended when count > 1.","type":"string","minLength":1,"maxLength":180}},"required":["providerCampaignId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Clone live campaign","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"clones":{"type":"array","items":{"type":"object","properties":{"campaignLaunchId":{"type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["campaignLaunchId","title"],"additionalProperties":false}},"requested":{"type":"number"}},"required":["clones","requested"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/import":{"post":{"operationId":"import-live-campaign","summary":"Import live campaign","description":"Wraps a campaign that exists on the ad platform but not in Koast (`providerCampaignId`) in a new launch, so it can be reported on and extended with new ad sets and ads that publish into the same campaign. Idempotent: if a launch already wraps that campaign, its `campaignLaunchId` is returned with `alreadyExisted: true`.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"providerCampaignId":{"description":"Campaign id on the ad platform (the raw `id` from listAccountCampaigns rows).","type":"string","minLength":1},"title":{"description":"Optional batch title; defaults to the campaign name server-side.","type":"string","minLength":1,"maxLength":200}},"required":["providerCampaignId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Import live campaign","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"campaignLaunchId":{"type":"string"},"alreadyExisted":{"type":"boolean"},"title":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["campaignLaunchId","alreadyExisted","title"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}":{"delete":{"operationId":"delete-batch","summary":"Delete batch or pipeline card","description":"Permanently deletes the launch (or pipeline card) and every campaign, ad set and ad it holds in Koast. Anything already published to the ad platform is untouched and keeps running and spending; pause it first if that is the intent.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Delete batch or pipeline card","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"description":"The id that was deleted.","type":"string"}},"required":["deleted"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/ad-sets":{"post":{"operationId":"add-adset","summary":"Add ad set","description":"Adds a draft ad set under the campaign `campaignNodeId`, optionally applying `settings` (dot-notation paths, budget amounts in cents) at creation. The response lists the paths that were stored in `appliedSettings` and those that were not in `notApplied`. On an imported live campaign, the new ad set is published into that same campaign on the next publish.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignNodeId":{"description":"ID of the campaign node to add the ad set to","type":"string","minLength":1},"name":{"description":"Name for the new ad set","type":"string"},"settings":{"description":"Optional settings to apply at create time. Dot-notation paths, same shape as updateSettings (e.g. `targeting.ageRange`, `budget.dailyAmount`, `schedule.startTime`, `optimization.bidStrategy`). budget.dailyAmount / budget.lifetimeAmount are CENTS. Array-typed paths must be native arrays. The response reports `appliedSettings` and `notApplied` — do NOT claim any value the response did not echo back.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["campaignNodeId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Add ad set","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/ad-sets/{adsetId}":{"get":{"operationId":"get-adset-details","summary":"Get ad set details","description":"Returns the full details of one ad set in the launch: settings, targeting, budget, schedule, placements, optimization, assets and links, plus its ads.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"adsetId","in":"path","required":true,"description":"ID of the ad set to get details for","schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Get ad set details","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/ad-sets/{adsetNodeId}/creatives/swap":{"post":{"operationId":"swap-creatives","summary":"Swap creatives","description":"Replaces the creatives on the ad set's ads with `creativeIds`, in order, keeping each ad's copy. Existing ads are edited in place; extra creatives clone an existing ad, and surplus ads are removed from the Koast tree and listed in `removedAdIds`.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"adsetNodeId","in":"path","required":true,"description":"Koast adset node id whose ads should carry the new creatives.","schema":{"type":"string","minLength":1}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"creativeIds":{"description":"Numeric creative IDs to place on the ad set, in order. Copy on existing ads is preserved.","minItems":1,"maxItems":100,"type":"array","items":{"type":"number"}}},"required":["creativeIds"],"additionalProperties":false}}}},"responses":{"200":{"description":"Swap creatives","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"adsetId":{"description":"Koast adset node id the creatives were placed on.","type":"string"},"ads":{"description":"The ads the ad set carries after the swap, each with the creative it now runs.","type":"array","items":{"type":"object","properties":{"adId":{"type":"string"},"creativeId":{"type":"number"}},"required":["adId","creativeId"],"additionalProperties":{}}},"removedAdIds":{"description":"Ids of surplus ads deleted from the Koast tree because fewer creatives were supplied than the ad set had ads. Empty when none were deleted.","type":"array","items":{"type":"string"}},"validation":{"type":"object","properties":{"valid":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"issueCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"issues":{"type":"array","items":{"type":"string"}}},"required":["valid","issueCount","issues"],"additionalProperties":{}}},"required":["adsetId","ads","removedAdIds"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/ad-sets/{adsetNodeId}/lead-form":{"post":{"operationId":"attach-lead-form","summary":"Attach lead form","description":"Turns on instant forms for the lead-generation ad set `adsetNodeId` and sets `leadFormId` as its form. Draft ad sets only; a live ad set returns 409.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"adsetNodeId","in":"path","required":true,"description":"Koast adset node id to attach the lead form to.","schema":{"type":"string","minLength":1}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"leadFormId":{"description":"Meta lead form id from listLeadForms.","type":"string","minLength":1},"leadFormName":{"description":"Optional human name of the lead form (from listLeadForms).","type":"string"}},"required":["leadFormId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Attach lead form","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/ads":{"post":{"operationId":"add-ads","summary":"Add ads","description":"Creates 1-100 ads, each under its own `adsetNodeId`, optionally attaching a `creativeId` and a `copyGenerationId` in the same request. Partial success is possible: unknown ad sets are returned in `notFound` and per-ad errors in `failed`, while the rest are created.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ads":{"description":"Ads to create (1-100). Each entry targets a specific adsetNodeId with optional creativeId and copyGenerationId.","minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"adsetNodeId":{"description":"Target ad set ID for this ad","type":"string","minLength":1},"name":{"description":"Name for the new ad","type":"string"},"creativeId":{"description":"Numeric creative ID to attach on create","type":"number"},"copyGenerationId":{"description":"Numeric copy generation ID (from generateCopy) to attach on create","type":"number"}},"required":["adsetNodeId"]}}},"required":["ads"],"additionalProperties":false}}}},"responses":{"200":{"description":"Add ads","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/ads/{adId}":{"get":{"operationId":"get-ad-details","summary":"Get ad details","description":"Returns the full details of one ad in the launch: creative, copy, links, call to action and tracking.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"adId","in":"path","required":true,"description":"ID of the ad to get details for","schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Get ad details","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/campaigns":{"post":{"operationId":"add-campaign","summary":"Add campaign","description":"Adds the campaign to the launch. A launch holds at most one campaign, so this fails if one already exists. `objective` is one of `website-conversions`, `lead-form` or `traffic`; platform-native objective names are rejected.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Name for the new campaign","type":"string","minLength":1,"maxLength":500},"objective":{"description":"Campaign objective. Must be one of: 'website-conversions', 'lead-form', 'traffic'. These are Koast-side canonical values — DO NOT pass Meta-native objective enum names like OUTCOME_SALES or OUTCOME_LEADS.","type":"string","enum":["website-conversions","lead-form","traffic"]}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Add campaign","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"objective":{"anyOf":[{"type":"string"},{"type":"null"}]},"validation":{"type":"object","properties":{"valid":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"issueCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"issues":{"type":"array","items":{"type":"string"}}},"required":["valid","issueCount","issues"],"additionalProperties":{}}},"required":["id","name"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/campaigns/import":{"post":{"operationId":"import-campaigns","summary":"Import campaigns","description":"Imports a campaign from the ad platform (`campaignIds`) into the launch, with its ad sets and ads. `sourceType: existing` attaches to the live campaign and keeps its platform ids; `duplicate` copies it as an editable draft. Pass `sourceAdAccountId` to import from another ad account the brand is connected to. The import runs in the background, so a large campaign may report `still-running` when the response returns.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignIds":{"description":"Ad-platform campaign IDs to import (non-empty)","minItems":1,"maxItems":1,"type":"array","items":{"type":"string","minLength":1}},"sourceType":{"description":"'existing' attaches to the live campaign (keeps its ad-platform IDs). 'duplicate' copies it as an editable draft with ad-platform IDs stripped — prefer cloneLiveCampaign for that. Anything else is rejected by the API.","default":"existing","type":"string","enum":["existing","duplicate"]},"sourceAdAccountId":{"description":"Ad account id to import FROM (e.g. act_1234 on Meta), when it differs from the batch's own ad account. Get it from listMyAdAccounts — never invent it. Omit for a same-account import. The brand must already have a connected credential for this account; if it does not, the API refuses and this tool reports the refusal instead of importing.","type":"string","minLength":1}},"required":["campaignIds"],"additionalProperties":false}}}},"responses":{"200":{"description":"Import campaigns","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/creative-fatigue":{"get":{"operationId":"compute-creative-fatigue","summary":"Compute creative fatigue","description":"Returns a deterministic creative fatigue score with its components (hook rate and CTR trajectories, frequency trend, CPM in context) and a `status`. Pass `adId` to score one ad, or omit it to score the launch aggregated at `level`, over the last `days` days. Values are computed from live daily insights on the ad platform.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"adId","in":"query","required":false,"description":"Optional ad-platform ad id to score a single ad. When omitted, scores the aggregated series at the chosen level.","schema":{"type":"string","minLength":1}},{"name":"level","in":"query","required":false,"description":"Insight level; defaults to 'ad' since fatigue is a per-creative concept.","schema":{"default":"ad","type":"string","enum":["campaign","adset","ad"]}},{"name":"days","in":"query","required":false,"description":"Lookback window in days. Defaults to 30.","schema":{"default":30,"type":"integer","minimum":3,"maximum":90}}],"responses":{"200":{"description":"Compute creative fatigue","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"score":{"anyOf":[{"type":"number"},{"type":"null"}]},"components":{"type":"object","properties":{"hookRateTrajectory":{"anyOf":[{"type":"number"},{"type":"null"}]},"ctrTrajectory":{"anyOf":[{"type":"number"},{"type":"null"}]},"frequencyTrend":{"anyOf":[{"type":"number"},{"type":"null"}]},"cpmInContext":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["hookRateTrajectory","ctrTrajectory","frequencyTrend","cpmInContext"],"additionalProperties":{}},"status":{"type":"string","enum":["insufficient data","no fatigue","early","active","exhausted"]},"daysAnalyzed":{"type":"number"},"source":{"type":"string","const":"insights-daily"},"asOf":{"description":"ISO time of the live provider read behind this response. Set on MCP and API responses, which may be served from the short metrics cache.","type":"string"}},"required":["score","components","status","daysAnalyzed","source"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/creatives/distribute":{"post":{"operationId":"distribute-creative","summary":"Distribute creative","description":"Places one creative (`creativeId`) on many ad sets at once: those in `targets.adsetIds` and every ad set under the campaigns in `targets.campaignIds`. With `strategy: newAdPerTarget` a new ad is created in each ad set; with `replaceFirstAd` the creative replaces the one on each ad set's first ad, or a new ad is created when the ad set has none.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"creativeId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"targets":{"type":"object","properties":{"adsetIds":{"type":"array","items":{"type":"string","minLength":1}},"campaignIds":{"type":"array","items":{"type":"string","minLength":1}}}},"strategy":{"type":"string","enum":["newAdPerTarget","replaceFirstAd"]}},"required":["creativeId","targets","strategy"],"additionalProperties":false}}}},"responses":{"200":{"description":"Distribute creative","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/delivery-status":{"get":{"operationId":"get-ad-delivery-status","summary":"Get ad delivery status","description":"Returns review and delivery status from the ad platform for every live entity in the launch: `issues` lists each ad that is disapproved, in review or has limited delivery, and `adsetStatuses` and `campaignStatuses` give the status of every live ad set and campaign. Values are live reads from the ad platform.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get ad delivery status","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"issues":{"type":"array","items":{"type":"object","properties":{"adId":{"type":"string"},"effectiveStatus":{"type":"string"},"reasons":{"type":"array","items":{"type":"string"}},"internalId":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["adId","effectiveStatus","reasons"],"additionalProperties":{}}},"coverage":{"type":"string","enum":["CHECKED","NO_LIVE_ENTITIES"]},"adsChecked":{"type":"number"},"adsetStatuses":{"type":"array","items":{"type":"object","properties":{"adsetId":{"type":"string"},"metaAdsetId":{"type":"string"},"effectiveStatus":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["adsetId","metaAdsetId","effectiveStatus"],"additionalProperties":{}}},"campaignStatuses":{"type":"array","items":{"type":"object","properties":{"campaignId":{"type":"string"},"metaCampaignId":{"type":"string"},"effectiveStatus":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["campaignId","metaCampaignId","effectiveStatus"],"additionalProperties":{}}}},"required":["issues","coverage","adsetStatuses","campaignStatuses"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/insights/daily":{"get":{"operationId":"get-insights-daily","summary":"Get daily insights","description":"Returns daily insights for the launch, one row per day summed across every entity at `level`: spend, impressions, clicks, reach, frequency, hook and hold rate, results, CPA, CTR (all clicks) and CPM. The window is the last `days` days, or `startDate` to `endDate` when both are given. `reach` is null when more than one entity is summed. Values are live reads from the ad platform.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"level","in":"query","required":false,"schema":{"default":"campaign","type":"string","enum":["campaign","adset","ad"]}},{"name":"days","in":"query","required":false,"schema":{"default":30,"type":"number","minimum":1,"maximum":90}},{"name":"startDate","in":"query","required":false,"description":"Explicit window start (YYYY-MM-DD). Pass BOTH startDate and endDate to fetch an exact date range instead of the relative `days` window — use this when the user names specific dates so the year is never guessed.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"endDate","in":"query","required":false,"description":"Explicit window end (YYYY-MM-DD). Pass together with startDate; overrides `days`.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"Get daily insights","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"days":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"spend":{"type":"number"},"impressions":{"type":"number"},"clicks":{"type":"number"},"reach":{"anyOf":[{"type":"number"},{"type":"null"}]},"entities":{"type":"number"},"frequency":{"anyOf":[{"type":"number"},{"type":"null"}]},"hook_rate":{"anyOf":[{"type":"number"},{"type":"null"}]},"hold_rate":{"anyOf":[{"type":"number"},{"type":"null"}]},"cpa":{"description":"Cost per RESULT for the day: spend divided by `results`. Null when the day produced no results, or when the provider named no result action — never 0, which would claim the results were free.","anyOf":[{"type":"number"},{"type":"null"}]},"ctr":{"description":"ALL-click CTR: every click divided by impressions. Reads higher than getMetrics.ctr, which is link-click CTR — do not compare the two field-for-field.","anyOf":[{"type":"number"},{"type":"null"}]},"cpm":{"anyOf":[{"type":"number"},{"type":"null"}]},"purchases":{"anyOf":[{"type":"number"},{"type":"null"}]},"results":{"description":"Conversions for whatever event the campaign optimises for on this date. Null means the ad platform named no result action for these entities — that is \"unknown\", NOT zero.","anyOf":[{"type":"number"},{"type":"null"}]},"resultActionType":{"description":"The action `results` was counted on (e.g. complete_registration, omni_purchase, lead). Null when the entities on this date optimise for different events, so no single name describes the total.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["date","spend","impressions","clicks","reach","entities","frequency","hook_rate","hold_rate","cpa","ctr","cpm"],"additionalProperties":{}}},"dateRange":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"}},"required":["start","end"],"additionalProperties":{}},"dataAvailability":{"type":"string","enum":["NO_LIVE_ENTITIES","OUT_OF_WINDOW","AVAILABLE"]},"campaignLaunchId":{"description":"The launch these days belong to, echoed back so a second read can be scoped to the same launch without guessing.","type":"string"},"level":{"description":"Which level the days were summed across, echoed back from the request.","type":"string","enum":["campaign","adset","ad"]},"asOf":{"description":"ISO time of the live provider read behind this response. Set on MCP and API responses, which may be served from the short metrics cache.","type":"string"}},"required":["days","dateRange","dataAvailability"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/metrics":{"get":{"operationId":"get-metrics","summary":"Get metrics","description":"Returns performance totals for the launch at `level` (campaign, ad set or ad) for `datePreset` (default `today`): spend, impressions, reach, clicks, link CTR, CPM, frequency, CPC, results, cost per result, hook rate and ROAS. Pass `id` to scope to one entity. Values are live reads from the ad platform; a null metric means it is unknown, not zero.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"level","in":"query","required":true,"description":"Which level to pull metrics at.","schema":{"type":"string","enum":["campaign","adset","ad"]}},{"name":"datePreset","in":"query","required":false,"description":"Reporting date preset. If omitted, defaults to today. Use last_7d / last_28d / last_30d / last_90d / this_month / last_month as needed. Every last_Nd preset ENDS YESTERDAY and does not include today, so a campaign that only started yesterday reads as zero under last_7d — use today or yesterday to see it, and say which window a number came from. For \"lifetime\" / \"all time\" / \"since launch\", use maximum — NOT \"lifetime\" (it is not an accepted value). Arbitrary start/end date ranges are not supported by the backend.","schema":{"type":"string","enum":["today","yesterday","this_week_sun_today","last_7d","last_14d","last_28d","last_30d","last_90d","this_month","last_month","maximum"]}},{"name":"id","in":"query","required":false,"description":"Optional entity id to scope to. Omit for all entities at this level.","schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Get metrics","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"level":{"type":"string","const":"campaign"},"campaigns":{"type":"array","items":{"type":"object","properties":{"internalId":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"isMock":{"type":"boolean"},"metaCampaignId":{"description":"The provider's own campaign id. The `meta` prefix is legacy field naming, not a claim about the provider — on Whop this holds a Whop adcamp_ id.","anyOf":[{"type":"string"},{"type":"null"}]},"metaAdsetId":{"description":"The provider's own ad set id. The `meta` prefix is legacy field naming — on Whop this holds a Whop ad-group id.","anyOf":[{"type":"string"},{"type":"null"}]},"metaAdId":{"description":"The provider's own ad id. The `meta` prefix is legacy field naming — on Whop this holds a Whop ad id.","anyOf":[{"type":"string"},{"type":"null"}]},"campaignId":{"anyOf":[{"type":"string"},{"type":"null"}]},"adsetId":{"anyOf":[{"type":"string"},{"type":"null"}]},"adId":{"anyOf":[{"type":"string"},{"type":"null"}]},"entityId":{"type":"string"},"actionType":{"type":"string"},"displayStatus":{"description":"Delivery status as Koast displays it, from the last state the provider reported. ABSENT means the provider has reported nothing for this entity yet — that is \"not reported\", NOT \"off\", so do not say an ad is paused on the strength of a missing status.","type":"string","enum":["LIVE","OFF","UNDER_REVIEW","REJECTED","SCHEDULED","PROCESSING","NOT_DELIVERING","DRAFT"]},"providerStatus":{"description":"The provider's own status string, unmapped.","type":"string"},"spend":{"anyOf":[{"type":"number"},{"type":"null"}]},"impressions":{"anyOf":[{"type":"number"},{"type":"null"}]},"reach":{"anyOf":[{"type":"number"},{"type":"null"}]},"clicks":{"anyOf":[{"type":"number"},{"type":"null"}]},"ctr":{"description":"LINK-click CTR: link clicks / impressions, as the ad platform reports it. NOT the same as getInsightsDaily.ctr, which is all-click CTR and reads higher, and not equal to clicks/impressions from this same row.","anyOf":[{"type":"number"},{"type":"null"}]},"cpm":{"anyOf":[{"type":"number"},{"type":"null"}]},"frequency":{"anyOf":[{"type":"number"},{"type":"null"}]},"costPerClick":{"anyOf":[{"type":"number"},{"type":"null"}]},"results":{"anyOf":[{"type":"number"},{"type":"null"}]},"costPerResult":{"anyOf":[{"type":"number"},{"type":"null"}]},"hookRate":{"anyOf":[{"type":"number"},{"type":"null"}]},"purchaseRoas":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["internalId","name","isMock"],"additionalProperties":{}}},"campaignLaunchId":{"description":"The launch these rows belong to, echoed back so a second read can be scoped to the same launch without guessing.","type":"string"},"isExample":{"type":"boolean"},"datePreset":{"type":"string"},"dataAvailability":{"type":"string","enum":["NO_LIVE_ENTITIES","OUT_OF_WINDOW","AVAILABLE"]},"dateRange":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"}},"required":["start","end"],"additionalProperties":{}},"windowCap":{"type":"object","properties":{"requested":{"type":"string"},"maxDays":{"type":"number"}},"required":["requested","maxDays"],"additionalProperties":{}},"asOf":{"description":"ISO time of the live provider read behind this response. Set on MCP and API responses, which may be served from the short metrics cache.","type":"string"}},"required":["level","campaigns","isExample","datePreset"],"additionalProperties":{}},{"type":"object","properties":{"level":{"type":"string","const":"adset"},"adsets":{"type":"array","items":{"type":"object","properties":{"internalId":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"isMock":{"type":"boolean"},"metaCampaignId":{"description":"The provider's own campaign id. The `meta` prefix is legacy field naming, not a claim about the provider — on Whop this holds a Whop adcamp_ id.","anyOf":[{"type":"string"},{"type":"null"}]},"metaAdsetId":{"description":"The provider's own ad set id. The `meta` prefix is legacy field naming — on Whop this holds a Whop ad-group id.","anyOf":[{"type":"string"},{"type":"null"}]},"metaAdId":{"description":"The provider's own ad id. The `meta` prefix is legacy field naming — on Whop this holds a Whop ad id.","anyOf":[{"type":"string"},{"type":"null"}]},"campaignId":{"anyOf":[{"type":"string"},{"type":"null"}]},"adsetId":{"anyOf":[{"type":"string"},{"type":"null"}]},"adId":{"anyOf":[{"type":"string"},{"type":"null"}]},"entityId":{"type":"string"},"actionType":{"type":"string"},"displayStatus":{"description":"Delivery status as Koast displays it, from the last state the provider reported. ABSENT means the provider has reported nothing for this entity yet — that is \"not reported\", NOT \"off\", so do not say an ad is paused on the strength of a missing status.","type":"string","enum":["LIVE","OFF","UNDER_REVIEW","REJECTED","SCHEDULED","PROCESSING","NOT_DELIVERING","DRAFT"]},"providerStatus":{"description":"The provider's own status string, unmapped.","type":"string"},"spend":{"anyOf":[{"type":"number"},{"type":"null"}]},"impressions":{"anyOf":[{"type":"number"},{"type":"null"}]},"reach":{"anyOf":[{"type":"number"},{"type":"null"}]},"clicks":{"anyOf":[{"type":"number"},{"type":"null"}]},"ctr":{"description":"LINK-click CTR: link clicks / impressions, as the ad platform reports it. NOT the same as getInsightsDaily.ctr, which is all-click CTR and reads higher, and not equal to clicks/impressions from this same row.","anyOf":[{"type":"number"},{"type":"null"}]},"cpm":{"anyOf":[{"type":"number"},{"type":"null"}]},"frequency":{"anyOf":[{"type":"number"},{"type":"null"}]},"costPerClick":{"anyOf":[{"type":"number"},{"type":"null"}]},"results":{"anyOf":[{"type":"number"},{"type":"null"}]},"costPerResult":{"anyOf":[{"type":"number"},{"type":"null"}]},"hookRate":{"anyOf":[{"type":"number"},{"type":"null"}]},"purchaseRoas":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["internalId","name","isMock"],"additionalProperties":{}}},"campaignLaunchId":{"description":"The launch these rows belong to, echoed back so a second read can be scoped to the same launch without guessing.","type":"string"},"isExample":{"type":"boolean"},"datePreset":{"type":"string"},"dataAvailability":{"type":"string","enum":["NO_LIVE_ENTITIES","OUT_OF_WINDOW","AVAILABLE"]},"dateRange":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"}},"required":["start","end"],"additionalProperties":{}},"windowCap":{"type":"object","properties":{"requested":{"type":"string"},"maxDays":{"type":"number"}},"required":["requested","maxDays"],"additionalProperties":{}},"asOf":{"description":"ISO time of the live provider read behind this response. Set on MCP and API responses, which may be served from the short metrics cache.","type":"string"}},"required":["level","adsets","isExample","datePreset"],"additionalProperties":{}},{"type":"object","properties":{"level":{"type":"string","const":"ad"},"ads":{"type":"array","items":{"type":"object","properties":{"internalId":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"isMock":{"type":"boolean"},"metaCampaignId":{"description":"The provider's own campaign id. The `meta` prefix is legacy field naming, not a claim about the provider — on Whop this holds a Whop adcamp_ id.","anyOf":[{"type":"string"},{"type":"null"}]},"metaAdsetId":{"description":"The provider's own ad set id. The `meta` prefix is legacy field naming — on Whop this holds a Whop ad-group id.","anyOf":[{"type":"string"},{"type":"null"}]},"metaAdId":{"description":"The provider's own ad id. The `meta` prefix is legacy field naming — on Whop this holds a Whop ad id.","anyOf":[{"type":"string"},{"type":"null"}]},"campaignId":{"anyOf":[{"type":"string"},{"type":"null"}]},"adsetId":{"anyOf":[{"type":"string"},{"type":"null"}]},"adId":{"anyOf":[{"type":"string"},{"type":"null"}]},"entityId":{"type":"string"},"actionType":{"type":"string"},"displayStatus":{"description":"Delivery status as Koast displays it, from the last state the provider reported. ABSENT means the provider has reported nothing for this entity yet — that is \"not reported\", NOT \"off\", so do not say an ad is paused on the strength of a missing status.","type":"string","enum":["LIVE","OFF","UNDER_REVIEW","REJECTED","SCHEDULED","PROCESSING","NOT_DELIVERING","DRAFT"]},"providerStatus":{"description":"The provider's own status string, unmapped.","type":"string"},"spend":{"anyOf":[{"type":"number"},{"type":"null"}]},"impressions":{"anyOf":[{"type":"number"},{"type":"null"}]},"reach":{"anyOf":[{"type":"number"},{"type":"null"}]},"clicks":{"anyOf":[{"type":"number"},{"type":"null"}]},"ctr":{"description":"LINK-click CTR: link clicks / impressions, as the ad platform reports it. NOT the same as getInsightsDaily.ctr, which is all-click CTR and reads higher, and not equal to clicks/impressions from this same row.","anyOf":[{"type":"number"},{"type":"null"}]},"cpm":{"anyOf":[{"type":"number"},{"type":"null"}]},"frequency":{"anyOf":[{"type":"number"},{"type":"null"}]},"costPerClick":{"anyOf":[{"type":"number"},{"type":"null"}]},"results":{"anyOf":[{"type":"number"},{"type":"null"}]},"costPerResult":{"anyOf":[{"type":"number"},{"type":"null"}]},"hookRate":{"anyOf":[{"type":"number"},{"type":"null"}]},"purchaseRoas":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["internalId","name","isMock"],"additionalProperties":{}}},"campaignLaunchId":{"description":"The launch these rows belong to, echoed back so a second read can be scoped to the same launch without guessing.","type":"string"},"isExample":{"type":"boolean"},"datePreset":{"type":"string"},"dataAvailability":{"type":"string","enum":["NO_LIVE_ENTITIES","OUT_OF_WINDOW","AVAILABLE"]},"dateRange":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"}},"required":["start","end"],"additionalProperties":{}},"windowCap":{"type":"object","properties":{"requested":{"type":"string"},"maxDays":{"type":"number"}},"required":["requested","maxDays"],"additionalProperties":{}},"asOf":{"description":"ISO time of the live provider read behind this response. Set on MCP and API responses, which may be served from the short metrics cache.","type":"string"}},"required":["level","ads","isExample","datePreset"],"additionalProperties":{}}]}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/nodes/remove":{"post":{"operationId":"remove-nodes","summary":"Remove items from campaign tree","description":"Removes 1-200 campaign, ad set or ad nodes from the launch, together with their children. Only the Koast tree changes: anything already published keeps running on the ad platform. Ids not found in the launch are returned in `notFound`. Cannot be undone.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"nodes":{"description":"Nodes to delete (1-200). Each entry names its nodeId and nodeType.","minItems":1,"maxItems":200,"type":"array","items":{"type":"object","properties":{"nodeId":{"description":"ID of the node to delete","type":"string","minLength":1},"nodeType":{"description":"Type of the node","type":"string","enum":["campaign","adset","ad"]}},"required":["nodeId","nodeType"]}}},"required":["nodes"],"additionalProperties":false}}}},"responses":{"200":{"description":"Remove items from campaign tree","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"removedIds":{"description":"Ids named in the request that existed and were removed. Cascaded children are not listed here.","type":"array","items":{"type":"string"}},"deleted":{"description":"The same ids as removedIds.","type":"array","items":{"type":"string"}},"notFound":{"description":"Ids named in the request that did not exist in this launch. Nothing was removed for them.","type":"array","items":{"type":"string"}},"count":{"description":"How many of the requested nodes were removed — the length of removedIds. Does not include cascaded children.","type":"number"},"cascadedIds":{"description":"Ids of child nodes removed together with a removed parent. They were not named in the request.","type":"array","items":{"type":"string"}},"totalRemoved":{"description":"Total nodes removed, parents plus cascaded children — count plus the length of cascadedIds.","type":"number"},"validation":{"type":"object","properties":{"valid":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"issueCount":{"anyOf":[{"type":"number"},{"type":"null"}]},"issues":{"type":"array","items":{"type":"string"}}},"required":["valid","issueCount","issues"],"additionalProperties":{}}},"required":["removedIds","deleted","notFound","count","cascadedIds","totalRemoved"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/nodes/{nodeId}":{"patch":{"operationId":"update-node","summary":"Update campaign, ad set or ad","description":"Updates a campaign, ad set or ad node. Attach a creative, a generated copy or an existing post to an ad with `creativeId`, `copyGenerationId` or `postId`; set other fields, such as `status` (`PAUSED` or `ACTIVE`), through `properties`. At least one of these must be provided.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"nodeId","in":"path","required":true,"description":"ID of the node to update","schema":{"type":"string","minLength":1}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"creativeId":{"description":"Numeric creative ID to attach to an ad node. Use this when the user says \"use this creative\" or selects a creative from the attachments panel.","type":"number"},"copyGenerationId":{"description":"Numeric copy generation ID to attach to an ad node. Use this AFTER calling generateCopy — take the returned id and pass it here on the target ad.","type":"number"},"postId":{"description":"Existing Meta post ID to attach to an ad node.","type":"string"},"properties":{"description":"Other key-value pairs to update (e.g., { name: \"New name\" }). Do NOT put creativeId / copyGenerationId / postId here — use the dedicated fields above.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"additionalProperties":false}}}},"responses":{"200":{"description":"Update campaign, ad set or ad","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/nodes/{nodeId}/duplicate":{"post":{"operationId":"duplicate-node","summary":"Duplicate ad set or ad","description":"Duplicates an ad set or ad, including all its settings and children, `count` times (1-50).","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"nodeId","in":"path","required":true,"description":"ID of the node to duplicate","schema":{"type":"string","minLength":1}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"nodeType":{"description":"Type of the node to duplicate","type":"string","enum":["adset","ad"]},"count":{"description":"Number of copies to create (default 1, max 50)","default":1,"type":"number","minimum":1,"maximum":50}},"required":["nodeType"],"additionalProperties":false}}}},"responses":{"200":{"description":"Duplicate ad set or ad","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"count":{"type":"number"},"nodeType":{"type":"string","enum":["adset","ad"]}},"required":["success","count","nodeType"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/nodes/{nodeId}/live-budget":{"post":{"operationId":"edit-live-campaign","summary":"Edit live campaign budget","description":"Changes the daily or lifetime budget of a campaign or ad set that is already live, and pushes the change straight to the ad platform. `amount` is in cents (minimum 100). Returns 409 for a node that is still a draft; draft budgets are changed through the settings endpoint.","tags":["Launches"],"x-koast-required-scope":"publish","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"nodeId","in":"path","required":true,"description":"ID of the live campaign or ad set node to edit","schema":{"type":"string","minLength":1}},{"$ref":"#/components/parameters/IdempotencyKeyRequired"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"level":{"description":"Level of the node. Budget cannot be edited on an ad.","type":"string","enum":["CAMPAIGN","ADSET"]},"budgetType":{"description":"Whether to set the daily or lifetime budget.","type":"string","enum":["daily","lifetime"]},"amount":{"description":"New budget in CENTS (5000 = $50.00). Minimum 100 ($1.00). If the user said \"$50\", pass 5000.","type":"integer","minimum":100,"maximum":10000000}},"required":["level","budgetType","amount"],"additionalProperties":false}}}},"responses":{"200":{"description":"Edit live campaign budget","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"updated":{"type":"string"},"level":{"type":"string","enum":["CAMPAIGN","ADSET"]},"budgetType":{"type":"string","enum":["daily","lifetime"]},"amount":{"type":"number"},"metaId":{"type":"string"},"nodeName":{"anyOf":[{"type":"string"},{"type":"null"}]},"previousBudget":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["daily","lifetime"]},"amountMinorUnits":{"type":"number"}},"required":["type","amountMinorUnits"],"additionalProperties":{}},{"type":"null"}]},"currencyCode":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["updated","level","budgetType","amount","metaId"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/nodes/{nodeId}/rename":{"post":{"operationId":"rename-node","summary":"Rename campaign, ad set or ad","description":"Renames a campaign, ad set or ad in the launch to `newName`.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"nodeId","in":"path","required":true,"description":"ID of the node to rename","schema":{"type":"string","minLength":1}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"newName":{"description":"New name for the node (must be non-empty)","type":"string","minLength":1,"maxLength":500}},"required":["newName"],"additionalProperties":false}}}},"responses":{"200":{"description":"Rename campaign, ad set or ad","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/nodes/{nodeId}/variations":{"post":{"operationId":"duplicate-and-vary","summary":"Duplicate and vary","description":"Duplicates the node `count` times and sets one settings path, `vary.path`, to a different value on each copy, taken in order from `vary.values` (its length must equal `count`). Paths and values are validated against the settings schema. `nameTemplate` names the copies.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"nodeId","in":"path","required":true,"description":"ID of the node to duplicate","schema":{"type":"string","minLength":1}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"number","minimum":1,"maximum":20},"vary":{"type":"object","properties":{"path":{"description":"Dotted settings-schema path to vary across copies (e.g. 'targeting.ageRange', 'optimization.bidAmount', 'budget.dailyAmount'). MUST resolve against getSettingsSchema — invalid paths are rejected by the backend.","type":"string","minLength":1},"values":{"description":"One variant value per copy. Length must equal `count`. Values are shape-checked against the settings schema at the given path on the backend — mismatched types will error.","minItems":1,"type":"array","items":{}}},"required":["path","values"]},"nameTemplate":{"description":"Optional name template, e.g., \"{original} - Variant {i}\"","type":"string"}},"required":["count","vary"],"additionalProperties":false}}}},"responses":{"200":{"description":"Duplicate and vary","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/publish":{"post":{"operationId":"launch-campaign","summary":"Launch campaign","description":"Publishes the launch to the ad platform. Without `confirm: true` nothing is published: the launch is validated and a preview of its campaigns, ad sets, ads and budgets is returned (`mode: preview`). With `confirm: true` the publish jobs are queued and `mode: publish` is returned. A launch that fails validation (in either mode) answers 400 `validation_failed` with the message `Launch validation failed: N issues.` and one `{ field, message }` per issue in `details`, where `field` names the node (`campaigns[<id>]`, `adSets[<id>]` or `ads[<id>]`) and, when known, its setting (`ads[<id>].creative`).","tags":["Launches"],"x-koast-required-scope":"publish","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKeyRequired"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"description":"Set true ONLY after the user has explicitly authorized publishing on a prior turn. When false or omitted, the tool returns a preview and asks for confirmation — it does NOT publish.","type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Launch campaign","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"preview"},"message":{"type":"string"},"preview":{"type":"object","properties":{"campaignCount":{"type":"number"},"adsetCount":{"type":"number"},"adCount":{"type":"number"},"campaigns":{"type":"array","items":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"objective":{"anyOf":[{"type":"string"},{"type":"null"}]},"budget":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["daily","lifetime"]},"amountMinorUnits":{"type":"number"}},"required":["type","amountMinorUnits"],"additionalProperties":{}},{"type":"null"}]},"adsets":{"type":"array","items":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"isLive":{"type":"boolean"},"adCount":{"type":"number"},"budget":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["daily","lifetime"]},"amountMinorUnits":{"type":"number"}},"required":["type","amountMinorUnits"],"additionalProperties":{}},{"type":"null"}]}},"required":["id","name","isLive","adCount","budget"],"additionalProperties":{}}}},"required":["id","name","objective","budget","adsets"],"additionalProperties":{}}}},"required":["campaignCount","adsetCount","adCount","campaigns"],"additionalProperties":{}}},"required":["mode","message","preview"],"additionalProperties":{}},{"type":"object","properties":{"mode":{"type":"string","const":"publish"},"message":{"type":"string"},"data":{"type":"object","properties":{"launchId":{"type":"string"},"jobsQueued":{"type":"number"},"campaignsTotal":{"type":"number"},"adsetsTotal":{"type":"number"},"adsTotal":{"type":"number"}},"additionalProperties":{}}},"required":["mode","message","data"],"additionalProperties":{}}]}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/settings":{"get":{"operationId":"get-settings","summary":"Get settings","description":"Returns the current settings (budget, targeting, schedule, placements, optimization) of one node (`nodeId` and `nodeType`) or of up to 60 nodes at once via `nodes`.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"nodeId","in":"query","required":false,"description":"ID of the node (single-node form; omit when using `nodes`)","schema":{"type":"string","minLength":1}},{"name":"nodeType","in":"query","required":false,"description":"Type of the node (single-node form)","schema":{"type":"string","enum":["campaign","adset","ad"]}}],"responses":{"200":{"description":"Get settings","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"patch":{"operationId":"update-settings","summary":"Update settings","description":"Applies `settings` (dot-notation paths) to every node in `nodeIds`, all of the same `nodeType`. The request is atomic: every path lands or none does, and a rejection names each path and the reason. `budget.dailyAmount` and `budget.lifetimeAmount` are in cents; bid amounts and ad set spend limits are in dollars. Change campaign budget optimization with `budgetStrategy` (`CBO` or `ABO`). Concurrent writes to the same launch return 409.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"nodeIds":{"description":"IDs of the nodes to update (one or more)","minItems":1,"type":"array","items":{"type":"string","minLength":1}},"nodeType":{"description":"Type of the nodes (all nodeIds must share this level)","type":"string","enum":["campaign","adset","ad"]},"settings":{"description":"Key-value pairs where keys are dot-notation setting paths and values are the new values. budget.dailyAmount and budget.lifetimeAmount are CENTS (e.g., 5000 = $50.00). optimization.bidAmount, budget.adSetMinimumSpend, budget.adSetMaximumSpend are DOLLARS. Array-typed paths (targeting.ageRange, targeting.interests, targeting.locations, targeting.excludedLocations, targeting.locales, placements.devices) MUST be native JSON arrays, not strings. `isCBO` is NOT allowed here — use `budgetStrategy`.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"budgetStrategy":{"description":"The ONLY way to change Campaign Budget Optimization. Set \"CBO\" (campaign-level budget) or \"ABO\" (ad-set-level budget) ONLY when the user explicitly asked to switch budget optimization. Omit to leave it unchanged. Never put `isCBO` inside `settings`.","type":"string","enum":["CBO","ABO"]}},"required":["nodeIds","nodeType"],"additionalProperties":false}}}},"responses":{"200":{"description":"Update settings","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/snapshot-templates":{"post":{"operationId":"save-campaign-snapshot","summary":"Save campaign snapshot template","description":"Saves the launch's campaign-level settings as a reusable snapshot template named `name`. Ad sets, ads and creatives are not captured.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Name for the template (non-empty)","type":"string","minLength":1,"maxLength":191},"description":{"description":"Description of what this template is for","type":"string","maxLength":191}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Save campaign snapshot template","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/snapshot-templates/{templateId}/apply":{"post":{"operationId":"apply-snapshot-template","summary":"Apply campaign snapshot template","description":"Copies the campaign settings stored in the snapshot template onto the campaign already in the launch. It does not create ad sets or ads, and fails on a launch with no campaign.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"templateId","in":"path","required":true,"description":"ID of the template to apply","schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Apply campaign snapshot template","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/structure-templates":{"post":{"operationId":"turn-launch-into-template","summary":"Turn launch into structure template","description":"Creates a structure template from the launch's existing structure, optionally named `name`.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":191}},"additionalProperties":false}}}},"responses":{"200":{"description":"Turn launch into structure template","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/structure-templates/{templateId}/apply":{"post":{"operationId":"apply-structure-template","summary":"Apply structure template","description":"Populates the launch, a draft pipeline card, with the structure template's campaign, ad set and ad structure. It never publishes. A card that is already populated is replaced only when `overwrite` is true. Use `suppliedDeferred` for per-account values the template leaves open.","tags":["Launches"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"templateId","in":"path","required":true,"description":"Structure template ID. Omit to read the template currently open in the builder from the Current Context block. Pass an explicit id only when acting on a different template than the one in scope.","schema":{"type":"string","minLength":1}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"overwrite":{"type":"boolean"},"suppliedDeferred":{"description":"Per-account deferred values keyed by adAccountId, supplied at apply.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"assets":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"audiences":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}}}}},"additionalProperties":false}}}},"responses":{"200":{"description":"Apply structure template","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/targeting-options":{"get":{"operationId":"get-targeting-options","summary":"Get targeting options","description":"Searches the targeting options available to the launch (locations, interests, demographics, behaviors and audiences) by `query`, returning the ad platform ids and types to use in targeting settings.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"description":"Search query to filter targeting options","schema":{"type":"string"}}],"responses":{"200":{"description":"Get targeting options","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/tree":{"get":{"operationId":"get-campaign-tree","summary":"Get campaign tree","description":"Returns the launch's structure as a campaign, ad set and ad tree with ids, names, statuses, budgets and live flags, plus counts per level. Settings, metrics and creative data are not included. `importInProgress` is true while a background import is still filling the tree.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Get campaign tree","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"string"},"counts":{"type":"object","properties":{"campaigns":{"type":"number"},"adsets":{"type":"number"},"ads":{"type":"number"},"campaignBreakdown":{"type":"object","properties":{"total":{"type":"number"},"live":{"type":"number"},"draft":{"type":"number"},"active":{"anyOf":[{"type":"number"},{"type":"null"}]},"paused":{"anyOf":[{"type":"number"},{"type":"null"}]},"withIssues":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["total","live","draft","active","paused","withIssues"],"additionalProperties":{}},"adsetBreakdown":{"type":"object","properties":{"total":{"type":"number"},"live":{"type":"number"},"draft":{"type":"number"},"active":{"anyOf":[{"type":"number"},{"type":"null"}]},"paused":{"anyOf":[{"type":"number"},{"type":"null"}]},"withIssues":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["total","live","draft","active","paused","withIssues"],"additionalProperties":{}},"adBreakdown":{"type":"object","properties":{"total":{"type":"number"},"live":{"type":"number"},"draft":{"type":"number"},"active":{"anyOf":[{"type":"number"},{"type":"null"}]},"paused":{"anyOf":[{"type":"number"},{"type":"null"}]},"withIssues":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["total","live","draft","active","paused","withIssues"],"additionalProperties":{}}},"required":["campaigns","adsets","ads","campaignBreakdown","adsetBreakdown","adBreakdown"],"additionalProperties":{}},"importInProgress":{"type":"boolean"},"tree":{"anyOf":[{"type":"object","properties":{"launchId":{"anyOf":[{"type":"string"},{"type":"null"}]},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"anyOf":[{"type":"string"},{"type":"null"}]},"campaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"anyOf":[{"type":"string"},{"type":"null"}]},"isLive":{"type":"boolean"},"platformId":{"anyOf":[{"type":"string"},{"type":"null"}]},"platformStatus":{"anyOf":[{"type":"string"},{"type":"null"}]},"displayStatus":{"anyOf":[{"type":"string"},{"type":"null"}]},"objective":{"anyOf":[{"type":"string"},{"type":"null"}]},"isCBO":{"type":"boolean"},"budget":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["daily","lifetime"]},"amountMinorUnits":{"type":"number"}},"required":["type","amountMinorUnits"],"additionalProperties":{}},{"type":"null"}]},"adsets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"anyOf":[{"type":"string"},{"type":"null"}]},"isLive":{"type":"boolean"},"platformId":{"anyOf":[{"type":"string"},{"type":"null"}]},"platformStatus":{"anyOf":[{"type":"string"},{"type":"null"}]},"displayStatus":{"anyOf":[{"type":"string"},{"type":"null"}]},"budget":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["daily","lifetime"]},"amountMinorUnits":{"type":"number"}},"required":["type","amountMinorUnits"],"additionalProperties":{}},{"type":"null"}]},"ads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"anyOf":[{"type":"string"},{"type":"null"}]},"isLive":{"type":"boolean"},"platformId":{"anyOf":[{"type":"string"},{"type":"null"}]},"platformStatus":{"anyOf":[{"type":"string"},{"type":"null"}]},"displayStatus":{"anyOf":[{"type":"string"},{"type":"null"}]},"creativeName":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","name","status","isLive","platformId","platformStatus","displayStatus","creativeName"],"additionalProperties":{}}}},"required":["id","name","status","isLive","platformId","platformStatus","displayStatus","budget","ads"],"additionalProperties":{}}}},"required":["id","name","status","isLive","platformId","platformStatus","displayStatus","objective","isCBO","budget","adsets"],"additionalProperties":{}}}},"required":["launchId","title","status","campaigns"],"additionalProperties":{}},{"type":"null"}]}},"required":["summary","counts","importInProgress","tree"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/launches/{launchId}/validation":{"get":{"operationId":"validate-launch","summary":"Validate launch","description":"Checks whether the launch can be published. Returns `valid` plus, per campaign, the missing required assets and the structural errors on each campaign, ad set and ad, each with an `inputId` and `message`. Changes nothing.","tags":["Launches"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"launchId","in":"path","required":true,"description":"The campaign launch (batch) id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Validate launch","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"results":{"type":"array","items":{"type":"object","properties":{"campaignId":{"type":"string"},"errors":{"type":"object","properties":{"campaignErrors":{"type":"array","items":{"type":"object","properties":{"inputId":{"type":"string"},"message":{"type":"string"}},"required":["inputId","message"],"additionalProperties":{}}},"adsetErrors":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"object","properties":{"inputId":{"type":"string"},"message":{"type":"string"}},"required":["inputId","message"],"additionalProperties":{}}}},"adErrors":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"object","properties":{"inputId":{"type":"string"},"message":{"type":"string"}},"required":["inputId","message"],"additionalProperties":{}}}},"invariantErrorCount":{"type":"number"}},"required":["campaignErrors","adsetErrors","adErrors","invariantErrorCount"],"additionalProperties":{}}},"required":["campaignId","errors"],"additionalProperties":{}}}},"required":["valid","results"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/pipeline/cards/move":{"post":{"operationId":"move-pipeline-card","summary":"Move pipeline card","description":"Moves the pipeline card `campaignLaunchId` to `stage`: `REQUESTED`, `ASSETS_UPLOADED`, `IN_REVIEW`, `APPROVED` or `FAILED`. `PUBLISHED` cannot be set; a card reaches it only by publishing.","tags":["Pipeline"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignLaunchId":{"description":"The pipeline card (batch) id to move.","type":"string","minLength":1},"stage":{"type":"string","enum":["REQUESTED","ASSETS_UPLOADED","IN_REVIEW","APPROVED","FAILED"]}},"required":["stage"],"additionalProperties":false}}}},"responses":{"200":{"description":"Move pipeline card","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/pipeline/columns":{"get":{"operationId":"list-pipeline-columns","summary":"List pipeline columns","description":"Lists the organization's fixed pipeline columns with their ids, names, stage keys, positions, hidden flag and bound settings.","tags":["Pipeline"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"List pipeline columns","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"columns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"organizationId":{"type":"number"},"name":{"type":"string"},"stageKey":{"type":"string"},"position":{"type":"number"},"isHidden":{"type":"boolean"},"isSystemDefault":{"type":"boolean"},"updatedAt":{"type":"string"},"settings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"columnId":{"type":"number"},"kind":{"type":"string"},"enabled":{"type":"boolean"},"config":{"type":"object","properties":{},"additionalProperties":{}},"updatedAt":{"type":"string"}},"required":["id","columnId","kind","enabled","config","updatedAt"],"additionalProperties":{}}}},"required":["id","organizationId","name","stageKey","position","isHidden","isSystemDefault","updatedAt","settings"],"additionalProperties":{}}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["columns","nextCursor"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/pipeline/columns/{columnId}":{"patch":{"operationId":"configure-pipeline-column","summary":"Configure pipeline column","description":"Updates one of the fixed pipeline columns: rename it with `name`, hide or show it with `isHidden`, or bind a structure template with `bindTemplate` to apply when a card enters the column (`null` unbinds). Binding replaces any publish action on that column. Requires an org admin; columns cannot be created or deleted.","tags":["Pipeline"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"columnId","in":"path","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":32},"isHidden":{"type":"boolean"},"bindTemplate":{"description":"Bind a structure template to apply when a card enters this column. columnOverrides must cover the template's required deferred assets per account.","anyOf":[{"type":"object","properties":{"structureTemplateId":{"type":"string","minLength":1},"columnOverrides":{"description":"Per-account deferred values keyed by adAccountId, supplied at apply.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"assets":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"audiences":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}}}}},"required":["structureTemplateId"]},{"type":"null"}]}},"additionalProperties":false}}}},"responses":{"200":{"description":"Configure pipeline column","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/pipeline/tickets":{"post":{"operationId":"create-pipeline-ticket","summary":"Create pipeline card","description":"Creates a pipeline card (a draft launch) titled `title`. Optionally set its starting `stage` (defaults to `REQUESTED`), attach `creativeIds` and assign teammates with `assigneeIds`.","tags":["Pipeline"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"stage":{"type":"string","enum":["REQUESTED","ASSETS_UPLOADED","IN_REVIEW","APPROVED","FAILED"]},"creativeIds":{"type":"array","items":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"assigneeIds":{"type":"array","items":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"description":{"type":"string","maxLength":2000}},"required":["title"],"additionalProperties":false}}}},"responses":{"200":{"description":"Create pipeline card","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/snapshot-templates":{"get":{"operationId":"list-snapshot-templates","summary":"List campaign snapshot templates","description":"Lists the saved campaign snapshot templates. Results are cursor-paginated.","tags":["Snapshot Templates"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"List campaign snapshot templates","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"templates":{"type":"array","items":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"number"}]}},"required":["id"],"additionalProperties":{}}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["templates","nextCursor"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/snapshot-templates/{templateId}":{"delete":{"operationId":"delete-snapshot-template","summary":"Delete campaign snapshot template","description":"Permanently deletes the campaign snapshot template. Structure templates are not affected.","tags":["Snapshot Templates"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"templateId","in":"path","required":true,"description":"ID of the template to delete","schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}}],"responses":{"200":{"description":"Delete campaign snapshot template","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/structure-templates":{"get":{"operationId":"list-structure-templates","summary":"List structure templates","description":"Lists the saved structure templates, rule-based campaign blueprints applied to pipeline cards. Results are cursor-paginated.","tags":["Structure Templates"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"List structure templates","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"templates":{"type":"array","items":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"number"}]}},"required":["id"],"additionalProperties":{}}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["templates","nextCursor"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"author-structure-template","summary":"Create structure template","description":"Creates a structure template from `config` (a structure state, validated before saving), `audiences` (at least one), `settings` and `accounts`.","tags":["Structure Templates"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Template name","type":"string","minLength":1,"maxLength":191},"config":{"type":"object","properties":{"countMode":{"description":"dynamic = use the real attached-creative count at apply; fixed = exactly n","type":"string","enum":["dynamic","fixed"]},"n":{"description":"creative count (for dynamic, a placeholder the engine substitutes at apply)","type":"integer","exclusiveMinimum":0,"maximum":1000},"adsets":{"description":"fixed = exactly k sets; distributed = ceil(n/per) sets of `per`","type":"string","enum":["fixed","distributed"]},"k":{"description":"number of ad sets when adsets=fixed (clamped 1..20)","type":"integer","exclusiveMinimum":0,"maximum":20},"per":{"description":"creatives per set when adsets=distributed","type":"integer","exclusiveMinimum":0,"maximum":20},"placement":{"description":"fixed-adsets only: broadcast = every set gets every creative; split = partition","type":"string","enum":["broadcast","split"]},"splitMode":{"type":"string","enum":["even","weighted","roundrobin"]},"weights":{"anyOf":[{"maxItems":20,"type":"array","items":{"type":"number","minimum":0,"maximum":100}},{"type":"null"}]},"name":{"type":"string"},"ops":{"description":"fixed-N custom drag-drop ops: clone/move/remove/group/addset","anyOf":[{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}},{"type":"null"}]},"remainderPolicy":{"type":"string","enum":["frontload","lastset","drop"]},"minPerSet":{"type":"integer","minimum":0,"maximum":50},"maxPerSet":{"type":"integer","minimum":0,"maximum":50}},"required":["countMode","n","adsets","k","per","placement","splitMode","weights","name","ops"],"additionalProperties":{}},"audiences":{"description":"Template-level audiences (targetingSet | customAudience | savedAudience). At least one is required to save or apply.","type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}},"settings":{"description":"Step-2 settings (objective, CBO+budget, attribution, performance goal, isAdCategorized) — required to apply.","type":"object","properties":{},"additionalProperties":{}},"scope":{"type":"string","enum":["single","multiple"]},"accounts":{"type":"array","items":{"type":"object","properties":{"adAccountId":{"type":"string","minLength":1},"settings":{"type":"object","properties":{},"additionalProperties":{}},"status":{"type":"string"}},"required":["adAccountId"]}}},"required":["name","config","audiences"],"additionalProperties":false}}}},"responses":{"200":{"description":"Create structure template","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/structure-templates/{templateId}":{"delete":{"operationId":"delete-structure-template","summary":"Delete structure template","description":"Permanently deletes the structure template. Cards already populated from it are not affected.","tags":["Structure Templates"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"templateId","in":"path","required":true,"description":"The structure template id, from listStructureTemplates.","schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Delete structure template","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"description":"The template id that was deleted.","type":"string"}},"required":["deleted"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"get":{"operationId":"get-structure-template","summary":"Get structure template","description":"Returns one structure template: its config, settings, audiences and accounts.","tags":["Structure Templates"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"templateId","in":"path","required":true,"description":"Structure template ID. Omit to read the template currently open in the builder from the Current Context block. Pass an explicit id only when acting on a different template than the one in scope.","schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Get structure template","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"patch":{"operationId":"edit-structure-template-rules","summary":"Edit structure template rules","description":"Updates the structure template. Pass only the fields to change; a new `config` is validated before it is saved.","tags":["Structure Templates"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"templateId","in":"path","required":true,"description":"Structure template ID. Omit to read the template currently open in the builder from the Current Context block. Pass an explicit id only when acting on a different template than the one in scope.","schema":{"type":"string","minLength":1}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"config":{"type":"object","properties":{"countMode":{"description":"dynamic = use the real attached-creative count at apply; fixed = exactly n","type":"string","enum":["dynamic","fixed"]},"n":{"description":"creative count (for dynamic, a placeholder the engine substitutes at apply)","type":"integer","exclusiveMinimum":0,"maximum":1000},"adsets":{"description":"fixed = exactly k sets; distributed = ceil(n/per) sets of `per`","type":"string","enum":["fixed","distributed"]},"k":{"description":"number of ad sets when adsets=fixed (clamped 1..20)","type":"integer","exclusiveMinimum":0,"maximum":20},"per":{"description":"creatives per set when adsets=distributed","type":"integer","exclusiveMinimum":0,"maximum":20},"placement":{"description":"fixed-adsets only: broadcast = every set gets every creative; split = partition","type":"string","enum":["broadcast","split"]},"splitMode":{"type":"string","enum":["even","weighted","roundrobin"]},"weights":{"anyOf":[{"maxItems":20,"type":"array","items":{"type":"number","minimum":0,"maximum":100}},{"type":"null"}]},"name":{"type":"string"},"ops":{"description":"fixed-N custom drag-drop ops: clone/move/remove/group/addset","anyOf":[{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}},{"type":"null"}]},"remainderPolicy":{"type":"string","enum":["frontload","lastset","drop"]},"minPerSet":{"type":"integer","minimum":0,"maximum":50},"maxPerSet":{"type":"integer","minimum":0,"maximum":50}},"required":["countMode","n","adsets","k","per","placement","splitMode","weights","name","ops"],"additionalProperties":{}},"audiences":{"description":"Template-level audiences (targetingSet | customAudience | savedAudience). At least one is required to save or apply.","type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}},"settings":{"type":"object","properties":{},"additionalProperties":{}},"scope":{"type":"string","enum":["single","multiple"]},"status":{"type":"string","enum":["DRAFT","READY","NEEDS_ATTENTION"]},"accounts":{"type":"array","items":{"type":"object","properties":{"adAccountId":{"type":"string","minLength":1},"settings":{"type":"object","properties":{},"additionalProperties":{}},"status":{"type":"string"}},"required":["adAccountId"]}}},"additionalProperties":false}}}},"responses":{"200":{"description":"Edit structure template rules","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/workflows":{"get":{"operationId":"list-workflows","summary":"List workflows","description":"Lists the organization's workflows, multi-step automations built from nodes such as apply template, launch, review gate and Slack notify, with their status, run count and last run time. Results are cursor-paginated.","tags":["Workflows"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"List workflows","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"workflows":{"type":"array","items":{"type":"object","properties":{"workflowId":{"type":"number"},"workflowName":{"type":"string"},"type":{"type":"string"},"status":{"type":"string"},"runCount":{"type":"number"},"isRunning":{"type":"boolean"},"lastRunAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["workflowId","workflowName","type","status","runCount","isRunning","lastRunAt"],"additionalProperties":{}}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["workflows","nextCursor"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"save-workflow","summary":"Save workflow","description":"Creates a workflow from `spec`, or updates an existing one when `workflowId` is given.","tags":["Workflows"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"workflowId":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"},"name":{"type":"string"},"type":{"type":"string","enum":["visual","agent","template"]},"spec":{"description":"Full workflow spec: { name, type, trigger, triggerAdded, nodes[], agentPrompt? }","type":"object","properties":{},"additionalProperties":{}}},"required":["spec"],"additionalProperties":false}}}},"responses":{"200":{"description":"Save workflow","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/workflows/{workflowId}":{"delete":{"operationId":"delete-workflow","summary":"Delete workflow","description":"Permanently deletes the workflow.","tags":["Workflows"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"workflowId","in":"path","required":true,"schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}}],"responses":{"200":{"description":"Delete workflow","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"workflowId":{"type":"string"}},"required":["workflowId"],"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"get":{"operationId":"get-workflow","summary":"Get workflow","description":"Returns one workflow: its spec, nodes, trigger and status.","tags":["Workflows"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"workflowId","in":"path","required":true,"schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}}],"responses":{"200":{"description":"Get workflow","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/workflows/{workflowId}/executions/{executionId}":{"get":{"operationId":"get-workflow-execution","summary":"Get workflow execution","description":"Returns the status of one workflow execution and the result of each of its nodes.","tags":["Workflows"],"x-koast-required-scope":"read","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"workflowId","in":"path","required":true,"schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}},{"name":"executionId","in":"path","required":true,"schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Get workflow execution","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/workflows/{workflowId}/runs":{"post":{"operationId":"run-workflow","summary":"Run workflow","description":"Starts a new execution of the workflow now. If the workflow already has a run in progress, no new run is started.","tags":["Workflows"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"workflowId","in":"path","required":true,"schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Run workflow","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/brands/{brandId}/workflows/{workflowId}/status":{"patch":{"operationId":"set-workflow-status","summary":"Set workflow status","description":"Sets the workflow's `status`: `DRAFT`, `ACTIVE` (armed) or `PAUSED`.","tags":["Workflows"],"x-koast-required-scope":"write","parameters":[{"name":"brandId","in":"path","required":true,"description":"The brand the request acts on. Every brand-scoped resource lives under its brand.","schema":{"type":"integer"}},{"name":"workflowId","in":"path","required":true,"schema":{"type":"string","minLength":1,"pattern":"^[1-9]\\d*$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["DRAFT","ACTIVE","PAUSED"]}},"required":["status"],"additionalProperties":false}}}},"responses":{"200":{"description":"Set workflow status","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/webhooks":{"get":{"operationId":"list-webhook-endpoints","summary":"List webhook endpoints","description":"Lists every webhook endpoint of the organization (at most 20). Requires an organization owner or admin when called with an OAuth token.","tags":["Webhooks"],"x-koast-required-scope":"read","responses":{"200":{"description":"List webhook endpoints","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"eventTypes":{"type":"array","items":{"type":"string"}},"brandIds":{"anyOf":[{"type":"array","items":{"type":"number"}},{"type":"null"}]},"status":{"description":"`disabled_by_failures` means Koast gave up after ~3 days of failed deliveries; enable it again once fixed.","type":"string","enum":["enabled","disabled","disabled_by_failures"]},"disabledReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"disabledAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastSuccessAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastFailureAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}]},"secretRotationExpiresAt":{"description":"While set, deliveries are signed with both the new and the previous secret.","anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","url","eventTypes","brandIds","status","disabledReason","disabledAt","consecutiveFailures","lastSuccessAt","lastFailureAt","lastError","secretRotationExpiresAt","createdAt","updatedAt"],"additionalProperties":false}},"nextCursor":{"type":"null"}},"required":["data","nextCursor"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"post":{"operationId":"create-webhook-endpoint","summary":"Create webhook endpoint","description":"Creates a webhook endpoint and returns its `whsec_…` signing secret. Deliveries follow the Standard Webhooks spec (`webhook-id`, `webhook-timestamp`, `webhook-signature`). At most 20 endpoints per organization (422 `unprocessable` beyond).","tags":["Webhooks"],"x-koast-required-scope":"write","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"description":"HTTPS URL Koast POSTs events to. No credentials in the URL; redirects are not followed.","type":"string","minLength":1,"maxLength":2048},"eventTypes":{"description":"Event types this endpoint receives. `ping` is always delivered by the test send and cannot be subscribed to.","minItems":1,"type":"array","items":{"type":"string","enum":["launch.completed","launch.failed","launch.partially_failed","ad.approved","ad.rejected","delivery.status_changed","metrics.updated","spend.day_closed"]}},"brandIds":{"description":"Only deliver events of these brands. Null delivers events of every brand in the organization.","anyOf":[{"minItems":1,"type":"array","items":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},{"type":"null"}]}},"required":["url","eventTypes"],"additionalProperties":false}}}},"responses":{"201":{"description":"Create webhook endpoint","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"eventTypes":{"type":"array","items":{"type":"string"}},"brandIds":{"anyOf":[{"type":"array","items":{"type":"number"}},{"type":"null"}]},"status":{"description":"`disabled_by_failures` means Koast gave up after ~3 days of failed deliveries; enable it again once fixed.","type":"string","enum":["enabled","disabled","disabled_by_failures"]},"disabledReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"disabledAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastSuccessAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastFailureAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}]},"secretRotationExpiresAt":{"description":"While set, deliveries are signed with both the new and the previous secret.","anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"secret":{"description":"The `whsec_…` signing secret. Verify deliveries with any Standard Webhooks library.","type":"string"}},"required":["id","url","eventTypes","brandIds","status","disabledReason","disabledAt","consecutiveFailures","lastSuccessAt","lastFailureAt","lastError","secretRotationExpiresAt","createdAt","updatedAt","secret"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/webhooks/{endpointId}":{"delete":{"operationId":"delete-webhook-endpoint","summary":"Delete webhook endpoint","description":"Deletes the webhook endpoint. Deliveries still queued for it are not sent.","tags":["Webhooks"],"x-koast-required-scope":"write","parameters":[{"name":"endpointId","in":"path","required":true,"description":"The webhook endpoint id (`ep_…`).","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"204":{"description":"Delete webhook endpoint","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"get":{"operationId":"get-webhook-endpoint","summary":"Get webhook endpoint","description":"Returns one webhook endpoint, including its status and the outcome of its latest deliveries.","tags":["Webhooks"],"x-koast-required-scope":"read","parameters":[{"name":"endpointId","in":"path","required":true,"description":"The webhook endpoint id (`ep_…`).","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"200":{"description":"Get webhook endpoint","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"eventTypes":{"type":"array","items":{"type":"string"}},"brandIds":{"anyOf":[{"type":"array","items":{"type":"number"}},{"type":"null"}]},"status":{"description":"`disabled_by_failures` means Koast gave up after ~3 days of failed deliveries; enable it again once fixed.","type":"string","enum":["enabled","disabled","disabled_by_failures"]},"disabledReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"disabledAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastSuccessAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastFailureAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}]},"secretRotationExpiresAt":{"description":"While set, deliveries are signed with both the new and the previous secret.","anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","url","eventTypes","brandIds","status","disabledReason","disabledAt","consecutiveFailures","lastSuccessAt","lastFailureAt","lastError","secretRotationExpiresAt","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}},"patch":{"operationId":"update-webhook-endpoint","summary":"Update webhook endpoint","description":"Updates the URL, event types, brand filter or status of a webhook endpoint. Setting `status` to `enabled` also clears a disable caused by failed deliveries.","tags":["Webhooks"],"x-koast-required-scope":"write","parameters":[{"name":"endpointId","in":"path","required":true,"description":"The webhook endpoint id (`ep_…`).","schema":{"type":"string","minLength":1,"maxLength":64}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"description":"HTTPS URL Koast POSTs events to. No credentials in the URL; redirects are not followed.","type":"string","minLength":1,"maxLength":2048},"eventTypes":{"description":"Event types this endpoint receives. `ping` is always delivered by the test send and cannot be subscribed to.","minItems":1,"type":"array","items":{"type":"string","enum":["launch.completed","launch.failed","launch.partially_failed","ad.approved","ad.rejected","delivery.status_changed","metrics.updated","spend.day_closed"]}},"brandIds":{"description":"Only deliver events of these brands. Null delivers events of every brand in the organization.","anyOf":[{"minItems":1,"type":"array","items":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},{"type":"null"}]},"status":{"description":"`enabled` also clears a disable caused by failed deliveries.","type":"string","enum":["enabled","disabled"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"Update webhook endpoint","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"eventTypes":{"type":"array","items":{"type":"string"}},"brandIds":{"anyOf":[{"type":"array","items":{"type":"number"}},{"type":"null"}]},"status":{"description":"`disabled_by_failures` means Koast gave up after ~3 days of failed deliveries; enable it again once fixed.","type":"string","enum":["enabled","disabled","disabled_by_failures"]},"disabledReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"disabledAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastSuccessAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastFailureAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}]},"secretRotationExpiresAt":{"description":"While set, deliveries are signed with both the new and the previous secret.","anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","url","eventTypes","brandIds","status","disabledReason","disabledAt","consecutiveFailures","lastSuccessAt","lastFailureAt","lastError","secretRotationExpiresAt","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/webhooks/{endpointId}/deliveries":{"get":{"operationId":"list-webhook-deliveries","summary":"List webhook deliveries","description":"Lists every delivery attempt of the endpoint from the last 30 days, newest first, with status code, latency, a truncated response body and the error.","tags":["Webhooks"],"x-koast-required-scope":"read","parameters":[{"name":"endpointId","in":"path","required":true,"description":"The webhook endpoint id (`ep_…`).","schema":{"type":"string","minLength":1,"maxLength":64}},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"List webhook deliveries","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"eventId":{"type":"string"},"eventType":{"type":"string"},"attempt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string","enum":["succeeded","failed"]},"final":{"description":"True when Koast will not retry this event again.","type":"boolean"},"httpStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"latencyMs":{"anyOf":[{"type":"number"},{"type":"null"}]},"responseBody":{"anyOf":[{"type":"string"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}]},"attemptedAt":{"type":"string"},"nextAttemptAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"resend":{"type":"boolean"}},"required":["id","eventId","eventType","attempt","status","final","httpStatus","latencyMs","responseBody","error","attemptedAt","nextAttemptAt","resend"],"additionalProperties":false}},"nextCursor":{"description":"Pass as `cursor` to read the next page. Null when there is no next page.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","nextCursor"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/webhooks/{endpointId}/enable":{"post":{"operationId":"enable-webhook-endpoint","summary":"Enable webhook endpoint","description":"Enables the endpoint and resets its failure counter. Events that failed while it was disabled can be sent again with resend-failed.","tags":["Webhooks"],"x-koast-required-scope":"write","parameters":[{"name":"endpointId","in":"path","required":true,"description":"The webhook endpoint id (`ep_…`).","schema":{"type":"string","minLength":1,"maxLength":64}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Enable webhook endpoint","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"eventTypes":{"type":"array","items":{"type":"string"}},"brandIds":{"anyOf":[{"type":"array","items":{"type":"number"}},{"type":"null"}]},"status":{"description":"`disabled_by_failures` means Koast gave up after ~3 days of failed deliveries; enable it again once fixed.","type":"string","enum":["enabled","disabled","disabled_by_failures"]},"disabledReason":{"anyOf":[{"type":"string"},{"type":"null"}]},"disabledAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"consecutiveFailures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastSuccessAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastFailureAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastError":{"anyOf":[{"type":"string"},{"type":"null"}]},"secretRotationExpiresAt":{"description":"While set, deliveries are signed with both the new and the previous secret.","anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","url","eventTypes","brandIds","status","disabledReason","disabledAt","consecutiveFailures","lastSuccessAt","lastFailureAt","lastError","secretRotationExpiresAt","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/webhooks/{endpointId}/resend-failed":{"post":{"operationId":"resend-failed-webhook-deliveries","summary":"Resend failed webhook deliveries","description":"Re-queues the latest finally failed delivery of each event (at most 100 events from the most recent 500 attempts). Receivers dedupe on the event `id`.","tags":["Webhooks"],"x-koast-required-scope":"write","parameters":[{"name":"endpointId","in":"path","required":true,"description":"The webhook endpoint id (`ep_…`).","schema":{"type":"string","minLength":1,"maxLength":64}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"202":{"description":"Resend failed webhook deliveries","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"queued":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["queued"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/webhooks/{endpointId}/rotate-secret":{"post":{"operationId":"rotate-webhook-secret","summary":"Rotate webhook secret","description":"Generates a new signing secret and returns it. For 24 hours deliveries carry signatures from both the new and the previous secret, so receivers can switch without dropping events.","tags":["Webhooks"],"x-koast-required-scope":"write","parameters":[{"name":"endpointId","in":"path","required":true,"description":"The webhook endpoint id (`ep_…`).","schema":{"type":"string","minLength":1,"maxLength":64}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Rotate webhook secret","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"secret":{"description":"The current `whsec_…` signing secret.","type":"string"},"previousSecretExpiresAt":{"description":"When the previous secret stops being used to sign. Null when no rotation is in progress.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["secret","previousSecretExpiresAt"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/webhooks/{endpointId}/secret":{"get":{"operationId":"get-webhook-secret","summary":"Get webhook secret","description":"Returns the current `whsec_…` signing secret of the endpoint. Requires the `write` scope: the secret lets its holder sign deliveries, so a read-only key cannot reveal it.","tags":["Webhooks"],"x-koast-required-scope":"write","parameters":[{"name":"endpointId","in":"path","required":true,"description":"The webhook endpoint id (`ep_…`).","schema":{"type":"string","minLength":1,"maxLength":64}}],"responses":{"200":{"description":"Get webhook secret","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"secret":{"description":"The current `whsec_…` signing secret.","type":"string"},"previousSecretExpiresAt":{"description":"When the previous secret stops being used to sign. Null when no rotation is in progress.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["secret","previousSecretExpiresAt"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}},"/v1/webhooks/{endpointId}/test":{"post":{"operationId":"test-webhook-endpoint","summary":"Send webhook test event","description":"Queues a signed `ping` event for the endpoint, regardless of its event types and brand filter. The outcome appears in its deliveries. A disabled endpoint answers 409 `conflict` (\"Enable the endpoint first.\") and nothing is queued.","tags":["Webhooks"],"x-koast-required-scope":"write","parameters":[{"name":"endpointId","in":"path","required":true,"description":"The webhook endpoint id (`ep_…`).","schema":{"type":"string","minLength":1,"maxLength":64}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"202":{"description":"Send webhook test event","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"eventId":{"type":"string"},"queued":{"type":"boolean","const":true}},"required":["eventId","queued"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/ValidationFailed"},"401":{"$ref":"#/components/responses/Unauthenticated"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/Timeout"}}}}},"webhooks":{"ad.approved":{"post":{"operationId":"webhook-ad-approved","summary":"ad.approved","description":"An ad passed the platform's review and is live or scheduled.","tags":["Webhooks"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The delivery id; identical across retries of the same event. Dedupe on the envelope `id`.","schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds at signing time. Reject deliveries older than 5 minutes.","schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1,<base64 HMAC-SHA256>` signatures (Standard Webhooks). Two are sent while a rotated secret overlaps.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Unique event id. Deliveries are at-least-once, so dedupe on it.","type":"string","pattern":"^evt_.*"},"type":{"type":"string","const":"ad.approved"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"apiVersion":{"type":"string","const":"v1"},"organizationId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"brandId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accountId":{"description":"The ad account the event concerns.","anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the event happened on.","type":"string","enum":["meta","whop"]},{"type":"null"}]},"data":{"type":"object","properties":{"ad":{"type":"object","properties":{"providerId":{"description":"The ad platform's ad id.","type":"string"},"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"adSetProviderId":{"anyOf":[{"type":"string"},{"type":"null"}]},"campaignProviderId":{"anyOf":[{"type":"string"},{"type":"null"}]},"campaignLaunchId":{"description":"The Koast launch the ad came from, when it came from one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["providerId","koastId","name","adSetProviderId","campaignProviderId","campaignLaunchId"],"additionalProperties":{}},"previousStatus":{"anyOf":[{"description":"Delivery status as Koast displays it.","type":"string","enum":["LIVE","OFF","UNDER_REVIEW","REJECTED","SCHEDULED","PROCESSING","NOT_DELIVERING","DRAFT"]},{"type":"null"}]},"providerStatus":{"description":"The ad platform's own review status string, unmapped.","anyOf":[{"type":"string"},{"type":"null"}]},"changedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["ad","previousStatus","providerStatus","changedAt"],"additionalProperties":{}}},"required":["id","type","createdAt","apiVersion","organizationId","brandId","accountId","provider","data"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Return any 2xx status to acknowledge the delivery."}}}},"ad.rejected":{"post":{"operationId":"webhook-ad-rejected","summary":"ad.rejected","description":"The platform rejected an ad. `data.reason` carries the platform's message.","tags":["Webhooks"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The delivery id; identical across retries of the same event. Dedupe on the envelope `id`.","schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds at signing time. Reject deliveries older than 5 minutes.","schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1,<base64 HMAC-SHA256>` signatures (Standard Webhooks). Two are sent while a rotated secret overlaps.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Unique event id. Deliveries are at-least-once, so dedupe on it.","type":"string","pattern":"^evt_.*"},"type":{"type":"string","const":"ad.rejected"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"apiVersion":{"type":"string","const":"v1"},"organizationId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"brandId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accountId":{"description":"The ad account the event concerns.","anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the event happened on.","type":"string","enum":["meta","whop"]},{"type":"null"}]},"data":{"type":"object","properties":{"ad":{"type":"object","properties":{"providerId":{"description":"The ad platform's ad id.","type":"string"},"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"adSetProviderId":{"anyOf":[{"type":"string"},{"type":"null"}]},"campaignProviderId":{"anyOf":[{"type":"string"},{"type":"null"}]},"campaignLaunchId":{"description":"The Koast launch the ad came from, when it came from one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["providerId","koastId","name","adSetProviderId","campaignProviderId","campaignLaunchId"],"additionalProperties":{}},"previousStatus":{"anyOf":[{"description":"Delivery status as Koast displays it.","type":"string","enum":["LIVE","OFF","UNDER_REVIEW","REJECTED","SCHEDULED","PROCESSING","NOT_DELIVERING","DRAFT"]},{"type":"null"}]},"providerStatus":{"description":"The ad platform's own review status string, unmapped.","anyOf":[{"type":"string"},{"type":"null"}]},"changedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reason":{"type":"object","properties":{"message":{"description":"The ad platform's rejection reason.","type":"string"},"details":{"description":"Every individual issue the platform listed.","type":"array","items":{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}}}},"required":["message","details"],"additionalProperties":{}}},"required":["ad","previousStatus","providerStatus","changedAt","reason"],"additionalProperties":{}}},"required":["id","type","createdAt","apiVersion","organizationId","brandId","accountId","provider","data"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Return any 2xx status to acknowledge the delivery."}}}},"delivery.status_changed":{"post":{"operationId":"webhook-delivery-status_changed","summary":"delivery.status_changed","description":"A campaign, ad set or ad changed delivery status. Checked every 15 minutes.","tags":["Webhooks"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The delivery id; identical across retries of the same event. Dedupe on the envelope `id`.","schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds at signing time. Reject deliveries older than 5 minutes.","schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1,<base64 HMAC-SHA256>` signatures (Standard Webhooks). Two are sent while a rotated secret overlaps.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Unique event id. Deliveries are at-least-once, so dedupe on it.","type":"string","pattern":"^evt_.*"},"type":{"type":"string","const":"delivery.status_changed"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"apiVersion":{"type":"string","const":"v1"},"organizationId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"brandId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accountId":{"description":"The ad account the event concerns.","anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the event happened on.","type":"string","enum":["meta","whop"]},{"type":"null"}]},"data":{"type":"object","properties":{"level":{"type":"string","enum":["campaign","adset","ad"]},"entity":{"type":"object","properties":{"providerId":{"type":"string"},"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"campaignLaunchId":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["providerId","koastId","name","campaignLaunchId"],"additionalProperties":{}},"from":{"description":"The status Koast last recorded. Null when none was recorded yet.","anyOf":[{"description":"Delivery status as Koast displays it.","type":"string","enum":["LIVE","OFF","UNDER_REVIEW","REJECTED","SCHEDULED","PROCESSING","NOT_DELIVERING","DRAFT"]},{"type":"null"}]},"to":{"description":"Delivery status as Koast displays it.","type":"string","enum":["LIVE","OFF","UNDER_REVIEW","REJECTED","SCHEDULED","PROCESSING","NOT_DELIVERING","DRAFT"]},"providerStatus":{"description":"The ad platform's own status string, unmapped.","anyOf":[{"type":"string"},{"type":"null"}]},"changedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["level","entity","from","to","providerStatus","changedAt"],"additionalProperties":{}}},"required":["id","type","createdAt","apiVersion","organizationId","brandId","accountId","provider","data"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Return any 2xx status to acknowledge the delivery."}}}},"launch.completed":{"post":{"operationId":"webhook-launch-completed","summary":"launch.completed","description":"A launch published every campaign, ad set and ad.","tags":["Webhooks"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The delivery id; identical across retries of the same event. Dedupe on the envelope `id`.","schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds at signing time. Reject deliveries older than 5 minutes.","schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1,<base64 HMAC-SHA256>` signatures (Standard Webhooks). Two are sent while a rotated secret overlaps.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Unique event id. Deliveries are at-least-once, so dedupe on it.","type":"string","pattern":"^evt_.*"},"type":{"type":"string","const":"launch.completed"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"apiVersion":{"type":"string","const":"v1"},"organizationId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"brandId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accountId":{"description":"The ad account the event concerns.","anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the event happened on.","type":"string","enum":["meta","whop"]},{"type":"null"}]},"data":{"type":"object","properties":{"launch":{"type":"object","properties":{"id":{"description":"The Koast launch (batch) id.","type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"description":"The launch status after the outcome was decided.","type":"string"},"startedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["id","title","status","startedAt","finishedAt"],"additionalProperties":{}},"campaigns":{"description":"Every campaign of the launch with its outcome. Empty when `truncated` is true.","type":"array","items":{"type":"object","properties":{"koastId":{"description":"The entity id inside Koast.","anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"description":"The ad platform's own id. Null when the entity was never created there.","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"error":{"description":"Why this entity failed. Null when it succeeded.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]}},"required":["koastId","providerId","name","status","error"],"additionalProperties":{}}},"adSets":{"description":"Every ad set of the launch with its outcome. Empty when `truncated` is true.","type":"array","items":{"type":"object","properties":{"koastId":{"description":"The entity id inside Koast.","anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"description":"The ad platform's own id. Null when the entity was never created there.","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"error":{"description":"Why this entity failed. Null when it succeeded.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]}},"required":["koastId","providerId","name","status","error"],"additionalProperties":{}}},"ads":{"description":"Every ad of the launch with its outcome. Empty when `truncated` is true.","type":"array","items":{"type":"object","properties":{"koastId":{"description":"The entity id inside Koast.","anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"description":"The ad platform's own id. Null when the entity was never created there.","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"error":{"description":"Why this entity failed. Null when it succeeded.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]}},"required":["koastId","providerId","name","status","error"],"additionalProperties":{}}},"error":{"description":"The launch-level failure, when the launch as a whole failed.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]},"truncated":{"description":"Present and true when the full outcome is too large for one event (over 240 KB, typically 1,000+ ads). The entity arrays are then empty; `counts`, `entityIds` and `fullObjectPath` replace them.","type":"boolean"},"counts":{"description":"Only on a truncated event: how many entities of each level succeeded, failed or were skipped.","type":"object","properties":{"campaigns":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"succeeded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","succeeded","failed","skipped"],"additionalProperties":{}},"adSets":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"succeeded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","succeeded","failed","skipped"],"additionalProperties":{}},"ads":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"succeeded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","succeeded","failed","skipped"],"additionalProperties":{}}},"required":["campaigns","adSets","ads"],"additionalProperties":{}},"entityIds":{"description":"Only on a truncated event: the ids and status of every entity, without names or errors. Omitted when even the ids do not fit.","type":"object","properties":{"campaigns":{"type":"array","items":{"type":"object","properties":{"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]}},"required":["koastId","providerId","accountId","status"],"additionalProperties":{}}},"adSets":{"type":"array","items":{"type":"object","properties":{"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]}},"required":["koastId","providerId","accountId","status"],"additionalProperties":{}}},"ads":{"type":"array","items":{"type":"object","properties":{"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]}},"required":["koastId","providerId","accountId","status"],"additionalProperties":{}}}},"required":["campaigns","adSets","ads"],"additionalProperties":{}},"fullObjectPath":{"description":"Only on a truncated event: the API path (GET) of the launch tree, with every campaign, ad set and ad, its platform id and its status.","type":"string"}},"required":["launch","campaigns","adSets","ads","error"],"additionalProperties":{}}},"required":["id","type","createdAt","apiVersion","organizationId","brandId","accountId","provider","data"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Return any 2xx status to acknowledge the delivery."}}}},"launch.failed":{"post":{"operationId":"webhook-launch-failed","summary":"launch.failed","description":"A launch failed.","tags":["Webhooks"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The delivery id; identical across retries of the same event. Dedupe on the envelope `id`.","schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds at signing time. Reject deliveries older than 5 minutes.","schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1,<base64 HMAC-SHA256>` signatures (Standard Webhooks). Two are sent while a rotated secret overlaps.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Unique event id. Deliveries are at-least-once, so dedupe on it.","type":"string","pattern":"^evt_.*"},"type":{"type":"string","const":"launch.failed"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"apiVersion":{"type":"string","const":"v1"},"organizationId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"brandId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accountId":{"description":"The ad account the event concerns.","anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the event happened on.","type":"string","enum":["meta","whop"]},{"type":"null"}]},"data":{"type":"object","properties":{"launch":{"type":"object","properties":{"id":{"description":"The Koast launch (batch) id.","type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"description":"The launch status after the outcome was decided.","type":"string"},"startedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["id","title","status","startedAt","finishedAt"],"additionalProperties":{}},"campaigns":{"description":"Every campaign of the launch with its outcome. Empty when `truncated` is true.","type":"array","items":{"type":"object","properties":{"koastId":{"description":"The entity id inside Koast.","anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"description":"The ad platform's own id. Null when the entity was never created there.","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"error":{"description":"Why this entity failed. Null when it succeeded.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]}},"required":["koastId","providerId","name","status","error"],"additionalProperties":{}}},"adSets":{"description":"Every ad set of the launch with its outcome. Empty when `truncated` is true.","type":"array","items":{"type":"object","properties":{"koastId":{"description":"The entity id inside Koast.","anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"description":"The ad platform's own id. Null when the entity was never created there.","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"error":{"description":"Why this entity failed. Null when it succeeded.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]}},"required":["koastId","providerId","name","status","error"],"additionalProperties":{}}},"ads":{"description":"Every ad of the launch with its outcome. Empty when `truncated` is true.","type":"array","items":{"type":"object","properties":{"koastId":{"description":"The entity id inside Koast.","anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"description":"The ad platform's own id. Null when the entity was never created there.","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"error":{"description":"Why this entity failed. Null when it succeeded.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]}},"required":["koastId","providerId","name","status","error"],"additionalProperties":{}}},"error":{"description":"The launch-level failure, when the launch as a whole failed.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]},"truncated":{"description":"Present and true when the full outcome is too large for one event (over 240 KB, typically 1,000+ ads). The entity arrays are then empty; `counts`, `entityIds` and `fullObjectPath` replace them.","type":"boolean"},"counts":{"description":"Only on a truncated event: how many entities of each level succeeded, failed or were skipped.","type":"object","properties":{"campaigns":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"succeeded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","succeeded","failed","skipped"],"additionalProperties":{}},"adSets":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"succeeded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","succeeded","failed","skipped"],"additionalProperties":{}},"ads":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"succeeded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","succeeded","failed","skipped"],"additionalProperties":{}}},"required":["campaigns","adSets","ads"],"additionalProperties":{}},"entityIds":{"description":"Only on a truncated event: the ids and status of every entity, without names or errors. Omitted when even the ids do not fit.","type":"object","properties":{"campaigns":{"type":"array","items":{"type":"object","properties":{"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]}},"required":["koastId","providerId","accountId","status"],"additionalProperties":{}}},"adSets":{"type":"array","items":{"type":"object","properties":{"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]}},"required":["koastId","providerId","accountId","status"],"additionalProperties":{}}},"ads":{"type":"array","items":{"type":"object","properties":{"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]}},"required":["koastId","providerId","accountId","status"],"additionalProperties":{}}}},"required":["campaigns","adSets","ads"],"additionalProperties":{}},"fullObjectPath":{"description":"Only on a truncated event: the API path (GET) of the launch tree, with every campaign, ad set and ad, its platform id and its status.","type":"string"}},"required":["launch","campaigns","adSets","ads","error"],"additionalProperties":{}}},"required":["id","type","createdAt","apiVersion","organizationId","brandId","accountId","provider","data"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Return any 2xx status to acknowledge the delivery."}}}},"launch.partially_failed":{"post":{"operationId":"webhook-launch-partially_failed","summary":"launch.partially_failed","description":"A launch published some entities and failed others.","tags":["Webhooks"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The delivery id; identical across retries of the same event. Dedupe on the envelope `id`.","schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds at signing time. Reject deliveries older than 5 minutes.","schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1,<base64 HMAC-SHA256>` signatures (Standard Webhooks). Two are sent while a rotated secret overlaps.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Unique event id. Deliveries are at-least-once, so dedupe on it.","type":"string","pattern":"^evt_.*"},"type":{"type":"string","const":"launch.partially_failed"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"apiVersion":{"type":"string","const":"v1"},"organizationId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"brandId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accountId":{"description":"The ad account the event concerns.","anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the event happened on.","type":"string","enum":["meta","whop"]},{"type":"null"}]},"data":{"type":"object","properties":{"launch":{"type":"object","properties":{"id":{"description":"The Koast launch (batch) id.","type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"description":"The launch status after the outcome was decided.","type":"string"},"startedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["id","title","status","startedAt","finishedAt"],"additionalProperties":{}},"campaigns":{"description":"Every campaign of the launch with its outcome. Empty when `truncated` is true.","type":"array","items":{"type":"object","properties":{"koastId":{"description":"The entity id inside Koast.","anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"description":"The ad platform's own id. Null when the entity was never created there.","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"error":{"description":"Why this entity failed. Null when it succeeded.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]}},"required":["koastId","providerId","name","status","error"],"additionalProperties":{}}},"adSets":{"description":"Every ad set of the launch with its outcome. Empty when `truncated` is true.","type":"array","items":{"type":"object","properties":{"koastId":{"description":"The entity id inside Koast.","anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"description":"The ad platform's own id. Null when the entity was never created there.","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"error":{"description":"Why this entity failed. Null when it succeeded.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]}},"required":["koastId","providerId","name","status","error"],"additionalProperties":{}}},"ads":{"description":"Every ad of the launch with its outcome. Empty when `truncated` is true.","type":"array","items":{"type":"object","properties":{"koastId":{"description":"The entity id inside Koast.","anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"description":"The ad platform's own id. Null when the entity was never created there.","anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]},"error":{"description":"Why this entity failed. Null when it succeeded.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]}},"required":["koastId","providerId","name","status","error"],"additionalProperties":{}}},"error":{"description":"The launch-level failure, when the launch as a whole failed.","anyOf":[{"type":"object","properties":{"message":{"description":"What went wrong, as the ad platform or Koast reported it.","type":"string"},"code":{"description":"The machine code behind the message when the platform gave one.","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["message","code"],"additionalProperties":{}},{"type":"null"}]},"truncated":{"description":"Present and true when the full outcome is too large for one event (over 240 KB, typically 1,000+ ads). The entity arrays are then empty; `counts`, `entityIds` and `fullObjectPath` replace them.","type":"boolean"},"counts":{"description":"Only on a truncated event: how many entities of each level succeeded, failed or were skipped.","type":"object","properties":{"campaigns":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"succeeded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","succeeded","failed","skipped"],"additionalProperties":{}},"adSets":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"succeeded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","succeeded","failed","skipped"],"additionalProperties":{}},"ads":{"type":"object","properties":{"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"succeeded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["total","succeeded","failed","skipped"],"additionalProperties":{}}},"required":["campaigns","adSets","ads"],"additionalProperties":{}},"entityIds":{"description":"Only on a truncated event: the ids and status of every entity, without names or errors. Omitted when even the ids do not fit.","type":"object","properties":{"campaigns":{"type":"array","items":{"type":"object","properties":{"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]}},"required":["koastId","providerId","accountId","status"],"additionalProperties":{}}},"adSets":{"type":"array","items":{"type":"object","properties":{"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]}},"required":["koastId","providerId","accountId","status"],"additionalProperties":{}}},"ads":{"type":"array","items":{"type":"object","properties":{"koastId":{"anyOf":[{"type":"string"},{"type":"null"}]},"providerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"accountId":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["succeeded","failed","skipped"]}},"required":["koastId","providerId","accountId","status"],"additionalProperties":{}}}},"required":["campaigns","adSets","ads"],"additionalProperties":{}},"fullObjectPath":{"description":"Only on a truncated event: the API path (GET) of the launch tree, with every campaign, ad set and ad, its platform id and its status.","type":"string"}},"required":["launch","campaigns","adSets","ads","error"],"additionalProperties":{}}},"required":["id","type","createdAt","apiVersion","organizationId","brandId","accountId","provider","data"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Return any 2xx status to acknowledge the delivery."}}}},"metrics.updated":{"post":{"operationId":"webhook-metrics-updated","summary":"metrics.updated","description":"Fresh totals for an ad account. Hourly.","tags":["Webhooks"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The delivery id; identical across retries of the same event. Dedupe on the envelope `id`.","schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds at signing time. Reject deliveries older than 5 minutes.","schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1,<base64 HMAC-SHA256>` signatures (Standard Webhooks). Two are sent while a rotated secret overlaps.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Unique event id. Deliveries are at-least-once, so dedupe on it.","type":"string","pattern":"^evt_.*"},"type":{"type":"string","const":"metrics.updated"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"apiVersion":{"type":"string","const":"v1"},"organizationId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"brandId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accountId":{"description":"The ad account the event concerns.","anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the event happened on.","type":"string","enum":["meta","whop"]},{"type":"null"}]},"data":{"type":"object","properties":{"accountId":{"type":"string"},"datePreset":{"type":"string"},"dateRange":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"}},"required":["start","end"],"additionalProperties":{}},"totalBatches":{"type":"number"},"batchesSampled":{"type":"number"},"batchesUnavailable":{"type":"number"},"totalSpend":{"description":"Null when the spend could not be read, never 0.","anyOf":[{"type":"number"},{"type":"null"}]},"totalResults":{"description":"Null when the results could not be read, never 0.","anyOf":[{"type":"number"},{"type":"null"}]},"currency":{"anyOf":[{"type":"string"},{"type":"null"}]},"asOf":{"description":"ISO time of the live provider read behind these numbers.","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["accountId","datePreset","totalBatches","batchesSampled","batchesUnavailable","totalSpend","totalResults","asOf"],"additionalProperties":{}}},"required":["id","type","createdAt","apiVersion","organizationId","brandId","accountId","provider","data"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Return any 2xx status to acknowledge the delivery."}}}},"ping":{"post":{"operationId":"webhook-ping","summary":"ping","description":"Only from a test send.","tags":["Webhooks"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The delivery id; identical across retries of the same event. Dedupe on the envelope `id`.","schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds at signing time. Reject deliveries older than 5 minutes.","schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1,<base64 HMAC-SHA256>` signatures (Standard Webhooks). Two are sent while a rotated secret overlaps.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Unique event id. Deliveries are at-least-once, so dedupe on it.","type":"string","pattern":"^evt_.*"},"type":{"type":"string","const":"ping"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"apiVersion":{"type":"string","const":"v1"},"organizationId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"brandId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accountId":{"description":"The ad account the event concerns.","anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the event happened on.","type":"string","enum":["meta","whop"]},{"type":"null"}]},"data":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":{}}},"required":["id","type","createdAt","apiVersion","organizationId","brandId","accountId","provider","data"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Return any 2xx status to acknowledge the delivery."}}}},"spend.day_closed":{"post":{"operationId":"webhook-spend-day_closed","summary":"spend.day_closed","description":"An ad account's day ended, in its own timezone, with that day's spend.","tags":["Webhooks"],"security":[],"parameters":[{"name":"webhook-id","in":"header","required":true,"description":"The delivery id; identical across retries of the same event. Dedupe on the envelope `id`.","schema":{"type":"string"}},{"name":"webhook-timestamp","in":"header","required":true,"description":"Unix seconds at signing time. Reject deliveries older than 5 minutes.","schema":{"type":"string"}},{"name":"webhook-signature","in":"header","required":true,"description":"Space-separated `v1,<base64 HMAC-SHA256>` signatures (Standard Webhooks). Two are sent while a rotated secret overlaps.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Unique event id. Deliveries are at-least-once, so dedupe on it.","type":"string","pattern":"^evt_.*"},"type":{"type":"string","const":"spend.day_closed"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"apiVersion":{"type":"string","const":"v1"},"organizationId":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"brandId":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accountId":{"description":"The ad account the event concerns.","anyOf":[{"type":"string"},{"type":"null"}]},"provider":{"anyOf":[{"description":"The ad platform the event happened on.","type":"string","enum":["meta","whop"]},{"type":"null"}]},"data":{"type":"object","properties":{"accountId":{"type":"string"},"date":{"description":"The closed day, in the ad account timezone.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"timezone":{"description":"IANA timezone of the ad account.","type":"string"},"spend":{"description":"Total spend for the day. Null when it could not be read, never 0.","anyOf":[{"type":"number"},{"type":"null"}]},"currency":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["accountId","date","timezone","spend","currency"],"additionalProperties":{}}},"required":["id","type","createdAt","apiVersion","organizationId","brandId","accountId","provider","data"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Return any 2xx status to acknowledge the delivery."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An organization API key (`koast_sk_…`) with the API surface enabled, or an OAuth access token issued by Koast (`koast_at_…`) whose audience covers this API. REST access requires an active Agency plan."}},"schemas":{"ErrorDetail":{"type":"object","properties":{"field":{"type":"string","description":"Dotted path of the offending input field."},"message":{"type":"string"},"code":{"type":"string"}},"required":["field","message"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable machine-readable code.","enum":["unauthenticated","plan_required","surface_disabled","audience_mismatch","insufficient_scope","brand_not_allowed","validation_failed","not_found","capability_unsupported","spend_ceiling_exceeded","spend_ceiling_required","forbidden","rate_limited","idempotency_conflict","idempotency_key_required","stale_read","conflict","unprocessable","account_ambiguous","unavailable","webhooks_unavailable","timeout","internal_error"]},"message":{"type":"string"},"details":{"description":"Field-level issues for validation_failed; otherwise extra context or null.","anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetail"}},{"type":"object"},{"type":"null"}]},"requestId":{"type":"string","description":"Same value as the Koast-Request-Id header."}},"required":["code","message","details","requestId"]}},"required":["error"]}},"parameters":{"Cursor":{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from the previous page's `nextCursor`. Omit for the first page.","schema":{"type":"string"}},"Limit":{"name":"limit","in":"query","required":false,"description":"Page size.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Retrying with the same key within 24 hours returns the first response without acting again.","schema":{"type":"string","maxLength":255}},"IdempotencyKeyRequired":{"name":"Idempotency-Key","in":"header","required":true,"description":"Required here. Retrying with the same key within 24 hours returns the first response without acting again.","schema":{"type":"string","maxLength":255}}},"headers":{"KoastRequestId":{"description":"Unique id of this request; quote it to support.","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests allowed per minute for this organization in this bucket (read or write).","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window.","schema":{"type":"integer"}},"RateLimitReset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"responses":{"ValidationFailed":{"description":"The input failed validation (`validation_failed`) or a required header is missing (`idempotency_key_required`).","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"Missing, unknown, revoked or expired credential.","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The credential is not allowed to do this: `insufficient_scope` (missing read/write/publish scope), `brand_not_allowed` (outside the key's brand list), `forbidden` (no access to the brand, launch or account), `plan_required`, `surface_disabled`, `spend_ceiling_required`, `spend_ceiling_exceeded`.","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"The resource does not exist or is not visible to this credential.","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"`idempotency_conflict` (the Idempotency-Key was reused with a different request or is still in flight), `stale_read` (the resource changed since it was read) or `conflict` (the request conflicts with the resource's current state, such as a live node, a concurrent edit or a racing secret rotation).","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"The request is valid but cannot be carried out (`capability_unsupported`, `account_ambiguous`).","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit or concurrency limit reached.","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected failure.","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"A dependency is not available right now (`unavailable`), or webhooks are not available in this environment (`webhooks_unavailable`).","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Timeout":{"description":"The request did not finish in time. A write may still complete; retry with the same Idempotency-Key.","headers":{"Koast-Request-Id":{"$ref":"#/components/headers/KoastRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}