Skip to content
Cowliss is in beta: features and pricing may change.

Automations

An automation is a JSON definition, a trigger and a list of steps (schema: /schemas/automation.json), addressed by its key in its app and running its latest ready version: a key is unique per app, so every route that names one takes appId and a request without it is a 422 naming the parameter. Create and update write a definition the way a push of that one file would. Status decides whether the automation fires, and neither a push nor a write touches it: a key is off until it is turned on. The spine is a display outline derived from the steps. An automation belongs to one app and fires on that app’s events only. A trigger’s event is a pattern in which * matches any sequence of characters, one or a list of them, and a pattern reaches Cowliss’s own system. events only when its literal prefix starts with system.: see Event patterns. Executions are on the Executions page.

List the organization’s automations

Auth: Session token.

Query parameters

{
"cursor": "string",
"limit": 50,
"status": "on",
"appId": "string",
"q": "string",
"tag": "string"
}
Field Type Required Constraints
cursor string no
limit integer no default 50; 1 ≤ x ≤ 100
status “on” | “off” | “paused” no
appId string no length 0–200
q string no length 0–200
tag string no length 0–50

Response 200

{
"data": [
{
"orgId": "string",
"key": "string",
"appId": "string",
"tags": [
"string"
],
"trigger": {
"event": "string"
},
"purpose": "string",
"description": "string",
"spine": [
{
"name": "sleep",
"detail": "string",
"timeout": "string",
"steps": [],
"otherwise": []
}
],
"status": "on",
"source": "push",
"createdAt": "2026-01-15T09:30:00.000Z",
"updatedAt": "2026-01-15T09:30:00.000Z",
"latestVersion": {
"id": "string",
"status": "compiling",
"appId": "string",
"error": "string",
"protocol": 42,
"source": "push",
"pushedAt": "2026-01-15T09:30:00.000Z",
"bundle": "string"
}
}
],
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object[] yes
data[] object yes
data[].orgId string yes
data[].key string yes
data[].appId string yes
data[].tags string[] yes
data[].trigger object | object | object yes
data[].purpose string yes
data[].description string | null yes
data[].spine object[] yes
data[].spine[] object yes
data[].spine[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data[].spine[].detail string no length 0–200
data[].spine[].timeout string no length 0–50
data[].spine[].steps object[] no
data[].spine[].steps[] object no
data[].spine[].steps[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data[].spine[].steps[].detail string no length 0–200
data[].spine[].steps[].timeout string no length 0–50
data[].spine[].steps[].steps object[] no
data[].spine[].steps[].otherwise object[] no
data[].spine[].otherwise object[] no
data[].spine[].otherwise[] object no
data[].spine[].otherwise[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data[].spine[].otherwise[].detail string no length 0–200
data[].spine[].otherwise[].timeout string no length 0–50
data[].spine[].otherwise[].steps object[] no
data[].spine[].otherwise[].otherwise object[] no
data[].status “on” | “off” | “paused” yes
data[].source “push” | “api” yes
data[].createdAt string (date-time) yes
data[].updatedAt string (date-time) yes
data[].latestVersion object | null yes
data[].latestVersion.id string yes
data[].latestVersion.status “compiling” | “ready” | “failed” yes
data[].latestVersion.appId string yes
data[].latestVersion.error string | null yes
data[].latestVersion.protocol integer yes -2147483648 ≤ x ≤ 2147483647
data[].latestVersion.source “push” | “api” yes
data[].latestVersion.pushedAt string (date-time) yes
data[].latestVersion.bundle string yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Create an automation from its definition

Admin only. Files the definition exactly as cow push files an automations/<key>.json file, and the automation starts off. A key the app already holds is refused: change that automation with automations.update instead.

Auth: Session token.

Request body

{
"data": {
"appId": "string",
"key": "string",
"definition": {
"trigger": {
"event": "string"
},
"purpose": "marketing",
"from": "string",
"tags": [],
"description": "string",
"enrollment": {
"cooldown": "string"
},
"steps": [
{
"id": "string",
"type": "sleep",
"duration": "string"
}
]
}
}
}
Field Type Required Constraints
data object yes
data.appId string yes
data.key string yes length 0–64
data.definition object yes
data.definition.trigger object | object | object yes
data.definition.purpose “marketing” | “transactional” yes
data.definition.from string yes length 0–200
data.definition.tags string[] no default []; items 0–20
data.definition.description string no length 0–500
data.definition.enrollment object no
data.definition.enrollment.cooldown string | integer yes
data.definition.steps one of[] yes
data.definition.steps[] one of yes
data.definition.steps[]〈sleep〉 object yes
data.definition.steps[]〈sleep〉.id string yes length 0–64
data.definition.steps[]〈sleep〉.type “sleep” yes
data.definition.steps[]〈sleep〉.duration string | integer yes
data.definition.steps[]〈waitForEvent〉 object yes
data.definition.steps[]〈waitForEvent〉.id string yes length 0–64
data.definition.steps[]〈waitForEvent〉.type “waitForEvent” yes
data.definition.steps[]〈waitForEvent〉.event string | string[] yes
data.definition.steps[]〈waitForEvent〉.timeout string | integer yes
data.definition.steps[]〈sendEmail〉 object yes
data.definition.steps[]〈sendEmail〉.id string yes length 0–64
data.definition.steps[]〈sendEmail〉.type “sendEmail” yes
data.definition.steps[]〈sendEmail〉.template string yes length 0–64
data.definition.steps[]〈sendEmail〉.props record<string, any> no default {}
data.definition.steps[]〈sendEmail〉.from string no length 0–200
data.definition.steps[]〈sendWebhook〉 object yes
data.definition.steps[]〈sendWebhook〉.id string yes length 0–64
data.definition.steps[]〈sendWebhook〉.type “sendWebhook” yes
data.definition.steps[]〈sendWebhook〉.webhook string no length 1–∞
data.definition.steps[]〈sendWebhook〉.destination string no length 1–∞
data.definition.steps[]〈sendWebhook〉.payload record<string, any> no default {}
data.definition.steps[]〈branch〉 object yes
data.definition.steps[]〈branch〉.id string yes length 0–64
data.definition.steps[]〈branch〉.type “branch” yes
data.definition.steps[]〈branch〉.if string | number | boolean | string | number | boolean | AutomationRule[] | record<string, any> | null[] | record<string, any> | null yes
data.definition.steps[]〈branch〉.then one of[] yes
data.definition.steps[]〈branch〉.then[] one of yes
data.definition.steps[]〈branch〉.else one of[] no
data.definition.steps[]〈branch〉.else[] one of no
data.definition.steps[]〈exit〉 object yes
data.definition.steps[]〈exit〉.id string yes length 0–64
data.definition.steps[]〈exit〉.type “exit” yes
data.definition.steps[]〈restart〉 object yes
data.definition.steps[]〈restart〉.id string yes length 0–64
data.definition.steps[]〈restart〉.type “restart” yes

Response 201

{
"data": {
"orgId": "string",
"key": "string",
"appId": "string",
"tags": [
"string"
],
"trigger": {
"event": "string"
},
"purpose": "string",
"description": "string",
"spine": [
{
"name": "sleep",
"detail": "string",
"timeout": "string",
"steps": [],
"otherwise": []
}
],
"status": "on",
"source": "push",
"createdAt": "2026-01-15T09:30:00.000Z",
"updatedAt": "2026-01-15T09:30:00.000Z",
"latestVersion": {
"id": "string",
"status": "compiling",
"appId": "string",
"error": "string",
"protocol": 42,
"source": "push",
"pushedAt": "2026-01-15T09:30:00.000Z",
"bundle": "string"
}
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.orgId string yes
data.key string yes
data.appId string yes
data.tags string[] yes
data.trigger object | object | object yes
data.purpose string yes
data.description string | null yes
data.spine object[] yes
data.spine[] object yes
data.spine[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data.spine[].detail string no length 0–200
data.spine[].timeout string no length 0–50
data.spine[].steps object[] no
data.spine[].steps[] object no
data.spine[].steps[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data.spine[].steps[].detail string no length 0–200
data.spine[].steps[].timeout string no length 0–50
data.spine[].steps[].steps object[] no
data.spine[].steps[].steps[] object no
data.spine[].steps[].otherwise object[] no
data.spine[].steps[].otherwise[] object no
data.spine[].otherwise object[] no
data.spine[].otherwise[] object no
data.spine[].otherwise[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data.spine[].otherwise[].detail string no length 0–200
data.spine[].otherwise[].timeout string no length 0–50
data.spine[].otherwise[].steps object[] no
data.spine[].otherwise[].steps[] object no
data.spine[].otherwise[].otherwise object[] no
data.spine[].otherwise[].otherwise[] object no
data.status “on” | “off” | “paused” yes
data.source “push” | “api” yes
data.createdAt string (date-time) yes
data.updatedAt string (date-time) yes
data.latestVersion object | null yes
data.latestVersion.id string yes
data.latestVersion.status “compiling” | “ready” | “failed” yes
data.latestVersion.appId string yes
data.latestVersion.error string | null yes
data.latestVersion.protocol integer yes -2147483648 ≤ x ≤ 2147483647
data.latestVersion.source “push” | “api” yes
data.latestVersion.pushedAt string (date-time) yes
data.latestVersion.bundle string yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Replace an automation’s definition

Admin only. Files the definition as a new version, the way a push of the changed file does. Runs already in flight finish on the version they started on; new runs take this one.

Auth: Session token.

Query parameters

{
"appId": "string"
}
Field Type Required Constraints
appId string yes

Request body

{
"data": {
"definition": {
"trigger": {
"event": "string"
},
"purpose": "marketing",
"from": "string",
"tags": [],
"description": "string",
"enrollment": {
"cooldown": "string"
},
"steps": [
{
"id": "string",
"type": "sleep",
"duration": "string"
}
]
}
}
}
Field Type Required Constraints
data object yes
data.definition object yes
data.definition.trigger object | object | object yes
data.definition.purpose “marketing” | “transactional” yes
data.definition.from string yes length 0–200
data.definition.tags string[] no default []; items 0–20
data.definition.description string no length 0–500
data.definition.enrollment object no
data.definition.enrollment.cooldown string | integer yes
data.definition.steps one of[] yes
data.definition.steps[] one of yes
data.definition.steps[]〈sleep〉 object yes
data.definition.steps[]〈sleep〉.id string yes length 0–64
data.definition.steps[]〈sleep〉.type “sleep” yes
data.definition.steps[]〈sleep〉.duration string | integer yes
data.definition.steps[]〈waitForEvent〉 object yes
data.definition.steps[]〈waitForEvent〉.id string yes length 0–64
data.definition.steps[]〈waitForEvent〉.type “waitForEvent” yes
data.definition.steps[]〈waitForEvent〉.event string | string[] yes
data.definition.steps[]〈waitForEvent〉.timeout string | integer yes
data.definition.steps[]〈sendEmail〉 object yes
data.definition.steps[]〈sendEmail〉.id string yes length 0–64
data.definition.steps[]〈sendEmail〉.type “sendEmail” yes
data.definition.steps[]〈sendEmail〉.template string yes length 0–64
data.definition.steps[]〈sendEmail〉.props record<string, any> no default {}
data.definition.steps[]〈sendEmail〉.from string no length 0–200
data.definition.steps[]〈sendWebhook〉 object yes
data.definition.steps[]〈sendWebhook〉.id string yes length 0–64
data.definition.steps[]〈sendWebhook〉.type “sendWebhook” yes
data.definition.steps[]〈sendWebhook〉.webhook string no length 1–∞
data.definition.steps[]〈sendWebhook〉.destination string no length 1–∞
data.definition.steps[]〈sendWebhook〉.payload record<string, any> no default {}
data.definition.steps[]〈branch〉 object yes
data.definition.steps[]〈branch〉.id string yes length 0–64
data.definition.steps[]〈branch〉.type “branch” yes
data.definition.steps[]〈branch〉.if string | number | boolean | string | number | boolean | AutomationRule[] | record<string, any> | null[] | record<string, any> | null yes
data.definition.steps[]〈branch〉.then one of[] yes
data.definition.steps[]〈branch〉.then[] one of yes
data.definition.steps[]〈branch〉.else one of[] no
data.definition.steps[]〈branch〉.else[] one of no
data.definition.steps[]〈exit〉 object yes
data.definition.steps[]〈exit〉.id string yes length 0–64
data.definition.steps[]〈exit〉.type “exit” yes
data.definition.steps[]〈restart〉 object yes
data.definition.steps[]〈restart〉.id string yes length 0–64
data.definition.steps[]〈restart〉.type “restart” yes

Response 200

{
"data": {
"orgId": "string",
"key": "string",
"appId": "string",
"tags": [
"string"
],
"trigger": {
"event": "string"
},
"purpose": "string",
"description": "string",
"spine": [
{
"name": "sleep",
"detail": "string",
"timeout": "string",
"steps": [],
"otherwise": []
}
],
"status": "on",
"source": "push",
"createdAt": "2026-01-15T09:30:00.000Z",
"updatedAt": "2026-01-15T09:30:00.000Z",
"latestVersion": {
"id": "string",
"status": "compiling",
"appId": "string",
"error": "string",
"protocol": 42,
"source": "push",
"pushedAt": "2026-01-15T09:30:00.000Z",
"bundle": "string"
}
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.orgId string yes
data.key string yes
data.appId string yes
data.tags string[] yes
data.trigger object | object | object yes
data.purpose string yes
data.description string | null yes
data.spine object[] yes
data.spine[] object yes
data.spine[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data.spine[].detail string no length 0–200
data.spine[].timeout string no length 0–50
data.spine[].steps object[] no
data.spine[].steps[] object no
data.spine[].steps[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data.spine[].steps[].detail string no length 0–200
data.spine[].steps[].timeout string no length 0–50
data.spine[].steps[].steps object[] no
data.spine[].steps[].steps[] object no
data.spine[].steps[].otherwise object[] no
data.spine[].steps[].otherwise[] object no
data.spine[].otherwise object[] no
data.spine[].otherwise[] object no
data.spine[].otherwise[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data.spine[].otherwise[].detail string no length 0–200
data.spine[].otherwise[].timeout string no length 0–50
data.spine[].otherwise[].steps object[] no
data.spine[].otherwise[].steps[] object no
data.spine[].otherwise[].otherwise object[] no
data.spine[].otherwise[].otherwise[] object no
data.status “on” | “off” | “paused” yes
data.source “push” | “api” yes
data.createdAt string (date-time) yes
data.updatedAt string (date-time) yes
data.latestVersion object | null yes
data.latestVersion.id string yes
data.latestVersion.status “compiling” | “ready” | “failed” yes
data.latestVersion.appId string yes
data.latestVersion.error string | null yes
data.latestVersion.protocol integer yes -2147483648 ≤ x ≤ 2147483647
data.latestVersion.source “push” | “api” yes
data.latestVersion.pushedAt string (date-time) yes
data.latestVersion.bundle string yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Inspect one automation

Auth: Session token.

Query parameters

{
"appId": "string"
}
Field Type Required Constraints
appId string yes

Response 200

{
"data": {
"orgId": "string",
"key": "string",
"appId": "string",
"tags": [
"string"
],
"trigger": {
"event": "string"
},
"purpose": "string",
"description": "string",
"spine": [
{
"name": "sleep",
"detail": "string",
"timeout": "string",
"steps": [],
"otherwise": []
}
],
"status": "on",
"source": "push",
"createdAt": "2026-01-15T09:30:00.000Z",
"updatedAt": "2026-01-15T09:30:00.000Z",
"latestVersion": {
"id": "string",
"status": "compiling",
"appId": "string",
"error": "string",
"protocol": 42,
"source": "push",
"pushedAt": "2026-01-15T09:30:00.000Z",
"bundle": "string"
},
"segment": {
"id": "string",
"orgId": "string",
"appId": "string",
"name": "string",
"description": "string",
"tags": [
"string"
],
"definition": {
"match": "all",
"predicates": [
{
"kind": "trait",
"name": "string",
"op": "eq",
"value": {}
}
]
},
"source": "push",
"automationKey": "string",
"createdAt": "2026-01-15T09:30:00.000Z",
"updatedAt": "2026-01-15T09:30:00.000Z",
"memberCount": 42
}
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.orgId string yes
data.key string yes
data.appId string yes
data.tags string[] yes
data.trigger object | object | object yes
data.purpose string yes
data.description string | null yes
data.spine object[] yes
data.spine[] object yes
data.spine[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data.spine[].detail string no length 0–200
data.spine[].timeout string no length 0–50
data.spine[].steps object[] no
data.spine[].steps[] object no
data.spine[].steps[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data.spine[].steps[].detail string no length 0–200
data.spine[].steps[].timeout string no length 0–50
data.spine[].steps[].steps object[] no
data.spine[].steps[].steps[] object no
data.spine[].steps[].otherwise object[] no
data.spine[].steps[].otherwise[] object no
data.spine[].otherwise object[] no
data.spine[].otherwise[] object no
data.spine[].otherwise[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data.spine[].otherwise[].detail string no length 0–200
data.spine[].otherwise[].timeout string no length 0–50
data.spine[].otherwise[].steps object[] no
data.spine[].otherwise[].steps[] object no
data.spine[].otherwise[].otherwise object[] no
data.spine[].otherwise[].otherwise[] object no
data.status “on” | “off” | “paused” yes
data.source “push” | “api” yes
data.createdAt string (date-time) yes
data.updatedAt string (date-time) yes
data.latestVersion object | null yes
data.latestVersion.id string yes
data.latestVersion.status “compiling” | “ready” | “failed” yes
data.latestVersion.appId string yes
data.latestVersion.error string | null yes
data.latestVersion.protocol integer yes -2147483648 ≤ x ≤ 2147483647
data.latestVersion.source “push” | “api” yes
data.latestVersion.pushedAt string (date-time) yes
data.latestVersion.bundle string yes
data.segment object | null yes
data.segment.id string yes
data.segment.orgId string yes
data.segment.appId string yes
data.segment.name string yes
data.segment.description string | null yes
data.segment.tags string[] yes
data.segment.definition object yes
data.segment.definition.match “all” | “any” yes default "all"
data.segment.definition.predicates array of variants yes items 1–∞
data.segment.definition.predicates[] one of yes
data.segment.definition.predicates[]〈trait〉 object yes
data.segment.definition.predicates[]〈trait〉.kind “trait” yes
data.segment.definition.predicates[]〈trait〉.name string yes length 1–200
data.segment.definition.predicates[]〈trait〉.op “eq” | “neq” | “gt” | “gte” | “lt” | “lte” | “exists” | “notExists” | “contains” | “before” | “after” yes
data.segment.definition.predicates[]〈trait〉.value any no
data.segment.definition.predicates[]〈event〉 object yes
data.segment.definition.predicates[]〈event〉.kind “event” yes
data.segment.definition.predicates[]〈event〉.name string | string[] yes
data.segment.definition.predicates[]〈event〉.op “performed” | “notPerformed” yes
data.segment.definition.predicates[]〈event〉.atLeast integer yes default 1; 1 ≤ x ≤ ∞
data.segment.definition.predicates[]〈event〉.withinDays integer no 1 ≤ x ≤ ∞
data.segment.source “push” | “api” yes
data.segment.automationKey string | null yes
data.segment.createdAt string (date-time) yes
data.segment.updatedAt string (date-time) yes
data.segment.memberCount integer yes 0 ≤ x ≤ ∞
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Automation operational stats

Auth: Session token.

Query parameters

{
"appId": "string"
}
Field Type Required Constraints
appId string yes

Response 200

{
"data": {
"executions": {
"entered": 42,
"active": 42,
"completed": 42,
"failed": 42,
"lastStartedAt": "2026-01-15T09:30:00.000Z"
},
"deliveries": {
"byStatus": {
"sent": 42
},
"sentLast30d": 42
}
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.executions object yes
data.executions.entered integer yes
data.executions.active integer yes
data.executions.completed integer yes
data.executions.failed integer yes
data.executions.lastStartedAt string (date-time) | null yes
data.deliveries object yes
data.deliveries.byStatus record<sent | delivered | bounced | complained | failed | skipped_disabled | skipped_paused | skipped_suspended | skipped_suppressed | skipped_quota | skipped_unknown_purpose | skipped_frequency_cap | skipped_consent | skipped_domain | skipped_ssrf | skipped_spam | would_send | would_skip_disabled | would_skip_paused | would_skip_suspended | would_skip_suppressed | would_skip_quota | would_skip_unknown_purpose | would_skip_frequency_cap | would_skip_consent | would_skip_domain | would_skip_ssrf | would_skip_spam, integer> yes
data.deliveries.sentLast30d integer yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Put automations on, off or on hold

Admin only. Turning an automation off lets executions in flight finish, while putting it on hold pauses them before their next step. Turning a held automation on resumes them.

Auth: Session token, or an org pipeline key.

Request body

{
"data": {
"keys": [
"string"
],
"appId": "string",
"status": "on"
}
}
Field Type Required Constraints
data object yes
data.keys string[] no items 1–100
data.appId string yes
data.status “on” | “off” | “paused” yes

Response 200

{
"data": [
{
"orgId": "string",
"key": "string",
"appId": "string",
"tags": [
"string"
],
"trigger": {
"event": "string"
},
"purpose": "string",
"description": "string",
"spine": [
{
"name": "sleep",
"detail": "string",
"timeout": "string",
"steps": [],
"otherwise": []
}
],
"status": "on",
"source": "push",
"createdAt": "2026-01-15T09:30:00.000Z",
"updatedAt": "2026-01-15T09:30:00.000Z",
"latestVersion": {
"id": "string",
"status": "compiling",
"appId": "string",
"error": "string",
"protocol": 42,
"source": "push",
"pushedAt": "2026-01-15T09:30:00.000Z",
"bundle": "string"
},
"enrollment": {
"counts": {
"scanned": 42,
"enrolled": 42,
"skipped": {
"completed": 42,
"cooldown": 42,
"running": 42
}
},
"url": "string"
}
}
],
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object[] yes
data[] object yes
data[].orgId string yes
data[].key string yes
data[].appId string yes
data[].tags string[] yes
data[].trigger object | object | object yes
data[].purpose string yes
data[].description string | null yes
data[].spine object[] yes
data[].spine[] object yes
data[].spine[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data[].spine[].detail string no length 0–200
data[].spine[].timeout string no length 0–50
data[].spine[].steps object[] no
data[].spine[].steps[] object no
data[].spine[].steps[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data[].spine[].steps[].detail string no length 0–200
data[].spine[].steps[].timeout string no length 0–50
data[].spine[].steps[].steps object[] no
data[].spine[].steps[].otherwise object[] no
data[].spine[].otherwise object[] no
data[].spine[].otherwise[] object no
data[].spine[].otherwise[].name “sleep” | “waitForEvent” | “send.email” | “send.webhook” | “profile.get” | “profiles.get” | “restart” | “traits.set” | “traits.unset” | “events.track” | “if” | “loop” | “end” yes
data[].spine[].otherwise[].detail string no length 0–200
data[].spine[].otherwise[].timeout string no length 0–50
data[].spine[].otherwise[].steps object[] no
data[].spine[].otherwise[].otherwise object[] no
data[].status “on” | “off” | “paused” yes
data[].source “push” | “api” yes
data[].createdAt string (date-time) yes
data[].updatedAt string (date-time) yes
data[].latestVersion object | null yes
data[].latestVersion.id string yes
data[].latestVersion.status “compiling” | “ready” | “failed” yes
data[].latestVersion.appId string yes
data[].latestVersion.error string | null yes
data[].latestVersion.protocol integer yes -2147483648 ≤ x ≤ 2147483647
data[].latestVersion.source “push” | “api” yes
data[].latestVersion.pushedAt string (date-time) yes
data[].latestVersion.bundle string yes
data[].enrollment object | null yes
data[].enrollment.counts object | null yes
data[].enrollment.counts.scanned integer yes
data[].enrollment.counts.enrolled integer yes
data[].enrollment.counts.skipped object yes
data[].enrollment.counts.skipped.completed integer yes
data[].enrollment.counts.skipped.cooldown integer yes
data[].enrollment.counts.skipped.running integer yes
data[].enrollment.url string yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Count the executions a hold until a given day would end

Auth: Session token.

Query parameters

{
"before": "2026-01-15T09:30:00.000Z",
"appId": "string"
}
Field Type Required Constraints
before string (date-time) yes
appId string yes

Response 200

{
"data": {
"due": 42,
"inFlight": 42
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.due integer yes
data.inFlight integer yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Delete an automation

Admin only. Executions already in flight finish, but no new ones start. A push never deletes an automation, so this is the only way to remove one whose file was deleted from your code.

Auth: Session token.

Query parameters

{
"appId": "string"
}
Field Type Required Constraints
appId string yes

Response 200

{
"data": {
"deleted": true
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.deleted true yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

GET /v1/automations/{key}/enrollment/preview

Section titled “GET /v1/automations/{key}/enrollment/preview”

Count who turning this automation on would reach

Auth: Session token.

Query parameters

{
"appId": "string"
}
Field Type Required Constraints
appId string yes

Response 200

{
"data": {
"scanned": 42,
"enrolled": 42,
"skipped": {
"completed": 42,
"cooldown": 42,
"running": 42
}
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.scanned integer yes
data.enrolled integer yes
data.skipped object yes
data.skipped.completed integer yes
data.skipped.cooldown integer yes
data.skipped.running integer yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Enroll the automation’s current members

Admin only. Starts an enrollment for recipients currently in the automation’s segment. If an enrollment is already running, this returns the existing enrollment rather than starting another.

Auth: Session token.

Query parameters

{
"appId": "string"
}
Field Type Required Constraints
appId string yes

Response 202

{
"data": {
"scanned": 42,
"enrolled": 42,
"skipped": {
"completed": 42,
"cooldown": 42,
"running": 42
},
"state": "none"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.scanned integer yes
data.enrolled integer yes
data.skipped object yes
data.skipped.completed integer yes
data.skipped.cooldown integer yes
data.skipped.running integer yes
data.state “none” | “running” | “done” | “cancelled” | “stopped” | “failed” yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

How far the automation’s enrollment has got

The state is none, with zero counts, when no enrollment has run for the automation.

Auth: Session token.

Query parameters

{
"appId": "string"
}
Field Type Required Constraints
appId string yes

Response 200

{
"data": {
"scanned": 42,
"enrolled": 42,
"skipped": {
"completed": 42,
"cooldown": 42,
"running": 42
},
"state": "none"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.scanned integer yes
data.enrolled integer yes
data.skipped object yes
data.skipped.completed integer yes
data.skipped.cooldown integer yes
data.skipped.running integer yes
data.state “none” | “running” | “done” | “cancelled” | “stopped” | “failed” yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

POST /v1/automations/{key}/enrollment/cancel

Section titled “POST /v1/automations/{key}/enrollment/cancel”

Stop a running enrollment

Admin only. Recipients already enrolled remain in the automation and their executions continue. Stopping the enrollment only prevents remaining recipients from enrolling.

Auth: Session token.

Query parameters

{
"appId": "string"
}
Field Type Required Constraints
appId string yes

Response 200

{
"data": {
"scanned": 42,
"enrolled": 42,
"skipped": {
"completed": 42,
"cooldown": 42,
"running": 42
},
"state": "none"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.scanned integer yes
data.enrolled integer yes
data.skipped object yes
data.skipped.completed integer yes
data.skipped.cooldown integer yes
data.skipped.running integer yes
data.state “none” | “running” | “done” | “cancelled” | “stopped” | “failed” yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.

Dry-run an automation against a real user

Admin only. Runs the automation’s latest ready version against the specified profile with sends disabled, delivering no emails or webhooks. The execution proceeds even if the automation is turned off.

Auth: Session token.

Query parameters

{
"appId": "string"
}
Field Type Required Constraints
appId string yes

Request body

{
"data": {
"profileId": "string"
}
}
Field Type Required Constraints
data object yes
data.profileId string yes length 1–∞

Response 201

{
"data": {
"id": "string",
"orgId": "string",
"appId": "string",
"automationKey": "string",
"profileId": "string",
"workflowId": "string",
"runId": "string",
"versionId": "string",
"triggerEventId": "string",
"status": "running",
"step": "string",
"timerDeadline": "2026-01-15T09:30:00.000Z",
"journalEntries": 42,
"error": "string",
"startedAt": "2026-01-15T09:30:00.000Z",
"updatedAt": "2026-01-15T09:30:00.000Z",
"endedAt": "2026-01-15T09:30:00.000Z"
},
"meta": {
"requestId": "string",
"nextCursor": "string",
"hasMore": true,
"warnings": [
{
"code": "string",
"message": "string",
"suggestion": "string"
}
]
}
}
Field Type Required Constraints
data object yes
data.id string yes
data.orgId string yes
data.appId string yes
data.automationKey string yes
data.profileId string yes
data.workflowId string yes
data.runId string yes
data.versionId string yes
data.triggerEventId string | null yes
data.status “running” | “waiting” | “completed” | “failed” | “cancelled” yes
data.step string | null yes
data.timerDeadline string (date-time) | null yes
data.journalEntries integer yes -2147483648 ≤ x ≤ 2147483647
data.error string | null yes
data.startedAt string (date-time) yes
data.updatedAt string (date-time) yes
data.endedAt string (date-time) | null yes
meta object no
meta.requestId string no
meta.nextCursor string | null no
meta.hasMore boolean no
meta.warnings object[] no
meta.warnings[] object no
meta.warnings[].code string yes
meta.warnings[].message string yes
meta.warnings[].suggestion string no

Errors follow the shared envelope and code table.