Webhook events
launch.completed
A launch published every campaign, ad set and ad.
Event type: launch.completed.
When it fires
A launch published every campaign, ad set and ad.
Envelope
Every event shares these top-level fields. The event-specific fields are under data.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique event id. Deliveries are at-least-once, so dedupe on it. |
type | "launch.completed" | Yes | |
createdAt | string (date-time) | Yes | |
apiVersion | "v1" | Yes | |
organizationId | integer | Yes | |
brandId | integer | null | Yes | |
accountId | string | null | Yes | The ad account the event concerns. |
provider | string | null | Yes | The ad platform the event happened on. One of meta, whop. |
Data
| Field | Type | Required | Description |
|---|---|---|---|
data.launch | object | Yes | |
data.launch.id | string | Yes | The Koast launch (batch) id. |
data.launch.title | string | null | Yes | |
data.launch.status | string | Yes | The launch status after the outcome was decided. |
data.launch.startedAt | string (date-time) | null | Yes | |
data.launch.finishedAt | string (date-time) | null | Yes | |
data.campaigns | object[] | Yes | Every campaign of the launch with its outcome. Empty when truncated is true. |
data.campaigns[].koastId | string | null | Yes | The entity id inside Koast. |
data.campaigns[].providerId | string | null | Yes | The ad platform's own id. Null when the entity was never created there. |
data.campaigns[].name | string | null | Yes | |
data.campaigns[].status | string | Yes | One of succeeded, failed, skipped. |
data.campaigns[].error | object | null | Yes | Why this entity failed. Null when it succeeded. |
data.campaigns[].error.message | string | Yes | What went wrong, as the ad platform or Koast reported it. |
data.campaigns[].error.code | string | null | Yes | The machine code behind the message when the platform gave one. |
data.adSets | object[] | Yes | Every ad set of the launch with its outcome. Empty when truncated is true. |
data.adSets[].koastId | string | null | Yes | The entity id inside Koast. |
data.adSets[].providerId | string | null | Yes | The ad platform's own id. Null when the entity was never created there. |
data.adSets[].name | string | null | Yes | |
data.adSets[].status | string | Yes | One of succeeded, failed, skipped. |
data.adSets[].error | object | null | Yes | Why this entity failed. Null when it succeeded. |
data.adSets[].error.message | string | Yes | What went wrong, as the ad platform or Koast reported it. |
data.adSets[].error.code | string | null | Yes | The machine code behind the message when the platform gave one. |
data.ads | object[] | Yes | Every ad of the launch with its outcome. Empty when truncated is true. |
data.ads[].koastId | string | null | Yes | The entity id inside Koast. |
data.ads[].providerId | string | null | Yes | The ad platform's own id. Null when the entity was never created there. |
data.ads[].name | string | null | Yes | |
data.ads[].status | string | Yes | One of succeeded, failed, skipped. |
data.ads[].error | object | null | Yes | Why this entity failed. Null when it succeeded. |
data.ads[].error.message | string | Yes | What went wrong, as the ad platform or Koast reported it. |
data.ads[].error.code | string | null | Yes | The machine code behind the message when the platform gave one. |
data.error | object | null | Yes | The launch-level failure, when the launch as a whole failed. |
data.error.message | string | Yes | What went wrong, as the ad platform or Koast reported it. |
data.error.code | string | null | Yes | The machine code behind the message when the platform gave one. |
data.truncated | boolean | No | 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. |
data.counts | object | No | Only on a truncated event: how many entities of each level succeeded, failed or were skipped. |
data.counts.campaigns | object | Yes | |
data.counts.campaigns.total | integer | Yes | |
data.counts.campaigns.succeeded | integer | Yes | |
data.counts.campaigns.failed | integer | Yes | |
data.counts.campaigns.skipped | integer | Yes | |
data.counts.adSets | object | Yes | |
data.counts.adSets.total | integer | Yes | |
data.counts.adSets.succeeded | integer | Yes | |
data.counts.adSets.failed | integer | Yes | |
data.counts.adSets.skipped | integer | Yes | |
data.counts.ads | object | Yes | |
data.counts.ads.total | integer | Yes | |
data.counts.ads.succeeded | integer | Yes | |
data.counts.ads.failed | integer | Yes | |
data.counts.ads.skipped | integer | Yes | |
data.entityIds | object | No | Only on a truncated event: the ids and status of every entity, without names or errors. Omitted when even the ids do not fit. |
data.entityIds.campaigns | object[] | Yes | |
data.entityIds.campaigns[].koastId | string | null | Yes | |
data.entityIds.campaigns[].providerId | string | null | Yes | |
data.entityIds.campaigns[].accountId | string | null | Yes | |
data.entityIds.campaigns[].status | string | Yes | One of succeeded, failed, skipped. |
data.entityIds.adSets | object[] | Yes | |
data.entityIds.adSets[].koastId | string | null | Yes | |
data.entityIds.adSets[].providerId | string | null | Yes | |
data.entityIds.adSets[].accountId | string | null | Yes | |
data.entityIds.adSets[].status | string | Yes | One of succeeded, failed, skipped. |
data.entityIds.ads | object[] | Yes | |
data.entityIds.ads[].koastId | string | null | Yes | |
data.entityIds.ads[].providerId | string | null | Yes | |
data.entityIds.ads[].accountId | string | null | Yes | |
data.entityIds.ads[].status | string | Yes | One of succeeded, failed, skipped. |
data.fullObjectPath | string | No | 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. |
Example payload
{
"id": "evt_2xKq7Vb9mN4pR8sT",
"type": "launch.completed",
"createdAt": "2026-09-19T14:30:00Z",
"apiVersion": "v1",
"organizationId": 1,
"brandId": 1,
"accountId": "string",
"provider": "meta",
"data": {
"launch": {
"id": "string",
"title": "string",
"status": "string",
"startedAt": "2026-09-19T14:30:00Z",
"finishedAt": "2026-09-19T14:30:00Z"
},
"campaigns": [
{
"koastId": "string",
"providerId": "string",
"name": "string",
"status": "succeeded",
"error": {
"message": "string",
"code": "string"
}
}
],
"adSets": [
{
"koastId": "string",
"providerId": "string",
"name": "string",
"status": "succeeded",
"error": {
"message": "string",
"code": "string"
}
}
],
"ads": [
{
"koastId": "string",
"providerId": "string",
"name": "string",
"status": "succeeded",
"error": {
"message": "string",
"code": "string"
}
}
],
"error": {
"message": "string",
"code": "string"
},
"truncated": true,
"counts": {
"campaigns": {
"total": 1,
"succeeded": 1,
"failed": 1,
"skipped": 1
},
"adSets": {
"total": 1,
"succeeded": 1,
"failed": 1,
"skipped": 1
},
"ads": {
"total": 1,
"succeeded": 1,
"failed": 1,
"skipped": 1
}
},
"entityIds": {
"campaigns": [
{
"koastId": "string",
"providerId": "string",
"accountId": "string",
"status": "succeeded"
}
],
"adSets": [
{
"koastId": "string",
"providerId": "string",
"accountId": "string",
"status": "succeeded"
}
],
"ads": [
{
"koastId": "string",
"providerId": "string",
"accountId": "string",
"status": "succeeded"
}
]
},
"fullObjectPath": "string"
}
}Delivery headers
| Header | Required | Description |
|---|---|---|
webhook-id | Yes | The delivery id; identical across retries of the same event. Dedupe on the envelope id. |
webhook-timestamp | Yes | Unix seconds at signing time. Reject deliveries older than 5 minutes. |
webhook-signature | Yes | Space-separated v1,<base64 HMAC-SHA256> signatures (Standard Webhooks). Two are sent while a rotated secret overlaps. |
Acknowledge
| Your response | Meaning |
|---|---|
2XX | Return any 2xx status to acknowledge the delivery. |
Signing, retries and endpoint setup are in the Webhooks guide.