curl --request PATCH \
--url https://api.scrip.dev/v1/programs/{programId}/automations/{automationId} \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data @- <<EOF
{
"description": "Sends a monthly reminder event to VIP participants",
"event_data": {},
"filter_hints": [
{
"type": "has_tag",
"value": "vip"
}
],
"guard_condition": "participant.counters.purchases >= 1",
"name": "Monthly points reminder",
"participant_filter": "participant.tags.exists(t, t == 'vip')",
"status": "paused",
"trigger": {
"cron_expression": "0 9 1 * *",
"timezone": "America/New_York"
}
}
EOFimport requests
url = "https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}"
payload = {
"description": "Sends a monthly reminder event to VIP participants",
"event_data": {},
"filter_hints": [
{
"type": "has_tag",
"value": "vip"
}
],
"guard_condition": "participant.counters.purchases >= 1",
"name": "Monthly points reminder",
"participant_filter": "participant.tags.exists(t, t == 'vip')",
"status": "paused",
"trigger": {
"cron_expression": "0 9 1 * *",
"timezone": "America/New_York"
}
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
description: 'Sends a monthly reminder event to VIP participants',
event_data: {},
filter_hints: [{type: 'has_tag', value: 'vip'}],
guard_condition: 'participant.counters.purchases >= 1',
name: 'Monthly points reminder',
participant_filter: 'participant.tags.exists(t, t == \'vip\')',
status: 'paused',
trigger: {cron_expression: '0 9 1 * *', timezone: 'America/New_York'}
})
};
fetch('https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'description' => 'Sends a monthly reminder event to VIP participants',
'event_data' => [
],
'filter_hints' => [
[
'type' => 'has_tag',
'value' => 'vip'
]
],
'guard_condition' => 'participant.counters.purchases >= 1',
'name' => 'Monthly points reminder',
'participant_filter' => 'participant.tags.exists(t, t == \'vip\')',
'status' => 'paused',
'trigger' => [
'cron_expression' => '0 9 1 * *',
'timezone' => 'America/New_York'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}"
payload := strings.NewReader("{\n \"description\": \"Sends a monthly reminder event to VIP participants\",\n \"event_data\": {},\n \"filter_hints\": [\n {\n \"type\": \"has_tag\",\n \"value\": \"vip\"\n }\n ],\n \"guard_condition\": \"participant.counters.purchases >= 1\",\n \"name\": \"Monthly points reminder\",\n \"participant_filter\": \"participant.tags.exists(t, t == 'vip')\",\n \"status\": \"paused\",\n \"trigger\": {\n \"cron_expression\": \"0 9 1 * *\",\n \"timezone\": \"America/New_York\"\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"description\": \"Sends a monthly reminder event to VIP participants\",\n \"event_data\": {},\n \"filter_hints\": [\n {\n \"type\": \"has_tag\",\n \"value\": \"vip\"\n }\n ],\n \"guard_condition\": \"participant.counters.purchases >= 1\",\n \"name\": \"Monthly points reminder\",\n \"participant_filter\": \"participant.tags.exists(t, t == 'vip')\",\n \"status\": \"paused\",\n \"trigger\": {\n \"cron_expression\": \"0 9 1 * *\",\n \"timezone\": \"America/New_York\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"description\": \"Sends a monthly reminder event to VIP participants\",\n \"event_data\": {},\n \"filter_hints\": [\n {\n \"type\": \"has_tag\",\n \"value\": \"vip\"\n }\n ],\n \"guard_condition\": \"participant.counters.purchases >= 1\",\n \"name\": \"Monthly points reminder\",\n \"participant_filter\": \"participant.tags.exists(t, t == 'vip')\",\n \"status\": \"paused\",\n \"trigger\": {\n \"cron_expression\": \"0 9 1 * *\",\n \"timezone\": \"America/New_York\"\n }\n}"
response = http.request(request)
puts response.read_body{
"created_at": "2024-01-15T10:30:00Z",
"description": "Sends a weekly reminder event to VIP participants",
"error_message": "participant not found",
"event_data": {},
"execution_completed_at": "2024-01-15T09:00:42Z",
"execution_error": "fanout aborted: program is archived",
"execution_started_at": "2024-01-15T09:00:00Z",
"execution_status": "completed",
"filter_hints": [
{
"type": "has_tag",
"value": "vip"
}
],
"guard_condition": "participant.counters.purchases >= 1",
"id": "990e8400-e29b-41d4-a716-446655440000",
"last_error": "failed to enqueue event: queue unavailable",
"last_evaluated_at": "2024-01-15T10:30:00Z",
"last_run_at": "2024-01-15T09:00:00Z",
"name": "Weekly points reminder",
"next_run_at": "2024-01-22T09:00:00Z",
"participant_filter": "participant.tags.exists(t, t == 'vip')",
"participant_id": "550e8400-e29b-41d4-a716-446655440001",
"participants_processed": 150,
"participants_skipped_error": 0,
"participants_total": 150,
"processed_at": "2024-02-01T09:00:05Z",
"program_id": "550e8400-e29b-41d4-a716-446655440000",
"scope": "participants",
"source": "api",
"source_event_id": "770e8400-e29b-41d4-a716-446655440000",
"source_rule_id": "880e8400-e29b-41d4-a716-446655440000",
"status": "active",
"trigger": {
"cron_expression": "0 9 * * 1",
"timezone": "America/Chicago",
"type": "cron"
},
"updated_at": "2024-01-15T10:30:00Z",
"warnings": [
{
"client_ref": "<string>",
"code": "unknown_state_key",
"key": "purchaseCnt",
"kind": "counter",
"message": "unknown counter \"purchaseCnt\" — no rule in this program writes it; did you mean \"purchase_count\"?",
"rule_id": "<string>",
"rule_set_id": "<string>",
"scope": "participant",
"suggestion": "purchase_count"
}
]
}{
"code": "bad_request",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Invalid request parameters"
}{
"code": "unauthorized",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Missing or invalid credentials"
}{
"code": "not_found",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Resource not found"
}{
"code": "unsupported_media_type",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Content-Type must be application/json"
}{
"code": "internal_error",
"message": "An internal error occurred"
}Update an automation
Partially update an automation.
curl --request PATCH \
--url https://api.scrip.dev/v1/programs/{programId}/automations/{automationId} \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data @- <<EOF
{
"description": "Sends a monthly reminder event to VIP participants",
"event_data": {},
"filter_hints": [
{
"type": "has_tag",
"value": "vip"
}
],
"guard_condition": "participant.counters.purchases >= 1",
"name": "Monthly points reminder",
"participant_filter": "participant.tags.exists(t, t == 'vip')",
"status": "paused",
"trigger": {
"cron_expression": "0 9 1 * *",
"timezone": "America/New_York"
}
}
EOFimport requests
url = "https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}"
payload = {
"description": "Sends a monthly reminder event to VIP participants",
"event_data": {},
"filter_hints": [
{
"type": "has_tag",
"value": "vip"
}
],
"guard_condition": "participant.counters.purchases >= 1",
"name": "Monthly points reminder",
"participant_filter": "participant.tags.exists(t, t == 'vip')",
"status": "paused",
"trigger": {
"cron_expression": "0 9 1 * *",
"timezone": "America/New_York"
}
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
description: 'Sends a monthly reminder event to VIP participants',
event_data: {},
filter_hints: [{type: 'has_tag', value: 'vip'}],
guard_condition: 'participant.counters.purchases >= 1',
name: 'Monthly points reminder',
participant_filter: 'participant.tags.exists(t, t == \'vip\')',
status: 'paused',
trigger: {cron_expression: '0 9 1 * *', timezone: 'America/New_York'}
})
};
fetch('https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'description' => 'Sends a monthly reminder event to VIP participants',
'event_data' => [
],
'filter_hints' => [
[
'type' => 'has_tag',
'value' => 'vip'
]
],
'guard_condition' => 'participant.counters.purchases >= 1',
'name' => 'Monthly points reminder',
'participant_filter' => 'participant.tags.exists(t, t == \'vip\')',
'status' => 'paused',
'trigger' => [
'cron_expression' => '0 9 1 * *',
'timezone' => 'America/New_York'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}"
payload := strings.NewReader("{\n \"description\": \"Sends a monthly reminder event to VIP participants\",\n \"event_data\": {},\n \"filter_hints\": [\n {\n \"type\": \"has_tag\",\n \"value\": \"vip\"\n }\n ],\n \"guard_condition\": \"participant.counters.purchases >= 1\",\n \"name\": \"Monthly points reminder\",\n \"participant_filter\": \"participant.tags.exists(t, t == 'vip')\",\n \"status\": \"paused\",\n \"trigger\": {\n \"cron_expression\": \"0 9 1 * *\",\n \"timezone\": \"America/New_York\"\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"description\": \"Sends a monthly reminder event to VIP participants\",\n \"event_data\": {},\n \"filter_hints\": [\n {\n \"type\": \"has_tag\",\n \"value\": \"vip\"\n }\n ],\n \"guard_condition\": \"participant.counters.purchases >= 1\",\n \"name\": \"Monthly points reminder\",\n \"participant_filter\": \"participant.tags.exists(t, t == 'vip')\",\n \"status\": \"paused\",\n \"trigger\": {\n \"cron_expression\": \"0 9 1 * *\",\n \"timezone\": \"America/New_York\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scrip.dev/v1/programs/{programId}/automations/{automationId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"description\": \"Sends a monthly reminder event to VIP participants\",\n \"event_data\": {},\n \"filter_hints\": [\n {\n \"type\": \"has_tag\",\n \"value\": \"vip\"\n }\n ],\n \"guard_condition\": \"participant.counters.purchases >= 1\",\n \"name\": \"Monthly points reminder\",\n \"participant_filter\": \"participant.tags.exists(t, t == 'vip')\",\n \"status\": \"paused\",\n \"trigger\": {\n \"cron_expression\": \"0 9 1 * *\",\n \"timezone\": \"America/New_York\"\n }\n}"
response = http.request(request)
puts response.read_body{
"created_at": "2024-01-15T10:30:00Z",
"description": "Sends a weekly reminder event to VIP participants",
"error_message": "participant not found",
"event_data": {},
"execution_completed_at": "2024-01-15T09:00:42Z",
"execution_error": "fanout aborted: program is archived",
"execution_started_at": "2024-01-15T09:00:00Z",
"execution_status": "completed",
"filter_hints": [
{
"type": "has_tag",
"value": "vip"
}
],
"guard_condition": "participant.counters.purchases >= 1",
"id": "990e8400-e29b-41d4-a716-446655440000",
"last_error": "failed to enqueue event: queue unavailable",
"last_evaluated_at": "2024-01-15T10:30:00Z",
"last_run_at": "2024-01-15T09:00:00Z",
"name": "Weekly points reminder",
"next_run_at": "2024-01-22T09:00:00Z",
"participant_filter": "participant.tags.exists(t, t == 'vip')",
"participant_id": "550e8400-e29b-41d4-a716-446655440001",
"participants_processed": 150,
"participants_skipped_error": 0,
"participants_total": 150,
"processed_at": "2024-02-01T09:00:05Z",
"program_id": "550e8400-e29b-41d4-a716-446655440000",
"scope": "participants",
"source": "api",
"source_event_id": "770e8400-e29b-41d4-a716-446655440000",
"source_rule_id": "880e8400-e29b-41d4-a716-446655440000",
"status": "active",
"trigger": {
"cron_expression": "0 9 * * 1",
"timezone": "America/Chicago",
"type": "cron"
},
"updated_at": "2024-01-15T10:30:00Z",
"warnings": [
{
"client_ref": "<string>",
"code": "unknown_state_key",
"key": "purchaseCnt",
"kind": "counter",
"message": "unknown counter \"purchaseCnt\" — no rule in this program writes it; did you mean \"purchase_count\"?",
"rule_id": "<string>",
"rule_set_id": "<string>",
"scope": "participant",
"suggestion": "purchase_count"
}
]
}{
"code": "bad_request",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Invalid request parameters"
}{
"code": "unauthorized",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Missing or invalid credentials"
}{
"code": "not_found",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Resource not found"
}{
"code": "unsupported_media_type",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Content-Type must be application/json"
}{
"code": "internal_error",
"message": "An internal error occurred"
}name, description, event_data, status, the nested trigger object, and filter fields (participant_filter, guard_condition, filter_hints). Scheduling fields inside trigger are validated against the automation’s trigger type: a cron_expression on a one_time automation is rejected.
Set status to paused to temporarily stop the automation from firing, and back to active to re-enable it. A failed automation can also be set back to active once you have fixed its configuration. Pausing does not stop a delivery run already in progress; it prevents future triggers from starting. Updating a cron automation’s cron_expression or timezone recomputes its next run time in the same request.
Authorizations
API key passed in the X-API-Key header.
Path Parameters
Program ID
Automation ID
Body
Fields to update
Human-readable description
"Sends a monthly reminder event to VIP participants"
Replacement JSON object to store and submit unchanged when the trigger fires
Checks derived from participant_filter that narrow the participants to consider. Scrip still evaluates the full CEL filter for each candidate.
Show child attributes
Show child attributes
Updated CEL guard condition evaluated at trigger time
"participant.counters.purchases >= 1"
Human-readable label (1-255 chars)
1 - 255"Monthly points reminder"
Updated CEL expression for participant enrollment
"participant.tags.exists(t, t == 'vip')"
Set to active or paused
active, paused "paused"
Updated trigger configuration
Show child attributes
Show child attributes
{
"cron_expression": "0 9 1 * *",
"timezone": "America/New_York"
}
Response
Updated automation
When this automation was created
"2024-01-15T10:30:00Z"
Optional human-readable description of what this automation does
"Sends a weekly reminder event to VIP participants"
Error message if the one-time automation failed
"participant not found"
Event data submitted when this automation fires
When the current fan-out execution completed
"2024-01-15T09:00:42Z"
Error message if the fan-out execution failed, or JSON-encoded diagnostics for completed runs with CEL eval skips
"fanout aborted: program is archived"
When the current fan-out execution started
"2024-01-15T09:00:00Z"
Status of the current run sending events to participants, separate from the automation's status.
- idle: no run is in progress.
- executing: participants are currently being processed.
- completed: the current run finished; the automation definition may remain active for future runs.
- failed: the current run stopped with an error; the automation definition may remain active for a retry or future run.
idle, executing, completed, failed "completed"
Checks derived from participant_filter that narrow the participants to consider. Scrip still evaluates the full CEL filter for each candidate.
Show child attributes
Show child attributes
CEL expression evaluated at trigger time; skips the participant if false
"participant.counters.purchases >= 1"
Unique identifier for this automation
"990e8400-e29b-41d4-a716-446655440000"
Error message from the most recent cron execution, if any (cron trigger only)
"failed to enqueue event: queue unavailable"
When participant filters were last evaluated (participant_state trigger only)
"2024-01-15T10:30:00Z"
When this automation last fired (cron trigger only)
"2024-01-15T09:00:00Z"
Human-readable label for this automation
"Weekly points reminder"
When this automation will next fire (cron trigger only)
"2024-01-22T09:00:00Z"
CEL expression that determines which participants are enrolled
"participant.tags.exists(t, t == 'vip')"
Target participant for program-scoped one-time automations
"550e8400-e29b-41d4-a716-446655440001"
Participants processed so far in the current run
150
Participants skipped because participant_filter or guard_condition CEL evaluation errored
0
Total participants to process in the current run
150
When this one-time automation was processed
"2024-02-01T09:00:05Z"
The program this automation belongs to
"550e8400-e29b-41d4-a716-446655440000"
Whether the automation sends one program event or an event for each selected participant: program or participants.
"participants"
Origin of the automation.
- api: created directly through the Automations API.
- rule_action: created by a SCHEDULE_EVENT or BROADCAST rule action.
- system: created by Scrip for scheduled tasks such as tier expiration.
api, rule_action, system "api"
The event whose processing created this automation. Omitted when no source event is recorded, for example on automations created through the API.
"770e8400-e29b-41d4-a716-446655440000"
The rule whose action created this automation. Omitted when no rule action created it, including automations created through the API.
"880e8400-e29b-41d4-a716-446655440000"
Lifecycle state of the automation definition.
- active: eligible to fire when its trigger is due.
- paused: temporarily prevented from firing and may be reactivated.
- completed: a one-time automation fired successfully and is terminal.
- failed: stopped firing after a definition-level failure until explicitly reactivated.
- archived: soft-deleted and permanently prevented from firing.
active, paused, completed, failed, archived "active"
Trigger configuration (type, schedule, and timing)
Show child attributes
Show child attributes
{
"cron_expression": "0 9 * * 1",
"timezone": "America/Chicago",
"type": "cron"
}
When this automation was last updated
"2024-01-15T10:30:00Z"
Non-blocking advisories about participant_filter/guard_condition — e.g. a counter/tag/attribute key no rule in the program writes. Present on create/update only; never blocks the save.
Show child attributes
Show child attributes