A trigger defines what makes a workflow run automatically, so you set it once instead of running the workflow by hand. A trigger can be a recurring schedule (e.g. every 15 minutes, or every weekday at 09:00) or the completion of another workflow (chaining one run after another). Each workflow has at most one active trigger.
Use these endpoints to read, set or replace, and remove a workflow's trigger. All endpoints are under /rest/beta and require auth via session JWT or sg_… API key Bearer token.
Endpoints
| Method |
Path |
Purpose |
GET |
/rest/beta/workflows/{id}/trigger |
Read the current trigger configuration |
PUT |
/rest/beta/workflows/{id}/trigger |
Set or replace the trigger (idempotent) |
DELETE |
/rest/beta/workflows/{id}/trigger |
Turn the trigger off |
Trigger type: time (schedule)
Run the workflow on a recurring schedule. Use friendly fields (recommended) or a raw cron expression — the two forms are mutually exclusive; supplying both returns 422.
Friendly fields
{ "type": "time", "frequency": "daily", "time": "09:00", "timezone": "Europe/Berlin" }
| Field |
Required for |
Allowed values |
frequency |
always |
minutes, hourly, daily, weekly, monthly |
every |
minutes, hourly |
minutes: 15 or 30; hourly: 1, 2, 4, 6, 8, 12 |
time |
daily, weekly, monthly |
"HH:MM" — minute is always coerced to :00 |
weekday |
weekly |
a day name (sunday … saturday) or a list of day names for multiple days, e.g. ["monday","thursday"] |
day_of_month |
monthly |
1–31 or "last" |
timezone |
optional |
IANA name (e.g. "America/New_York"). Defaults to the workflow's current timezone. |
HH:00 constraint: The minute component of time is always silently coerced to 00. Schedules run at the top of the hour. "09:45" is stored and executed as "09:00".
Friendly → cron mapping
| Friendly input |
Generated cron |
minutes, every 15 |
*/15 * * * * |
minutes, every 30 |
*/30 * * * * |
hourly, every N (1, 2, 4, 6, 8, 12) |
0 0-23/N * * * |
daily at hour H |
0 H * * * |
weekly at hour H on weekday(s) D |
0 H * * D (sunday=0 … saturday=6; multiple days → 0 H * * 1,2,4,5) |
monthly at hour H on day DOM |
0 H DOM * * ("last" → L) |
Reading a trigger (GET) — cron is authoritative
cron is always the source of truth. The friendly fields (frequency, every, time, weekday, day_of_month) are a convenience filled in only when the schedule maps cleanly to the table above:
- A
weekly schedule with one day returns weekday as a string; with several days it returns a list (cron day lists like 1,2,4,5 and ranges like 1-5 are both parsed).
- Advanced / compound schedules are not expressed in the friendly fields. Schedules created in the Sheetgo dashboard can combine things the friendly syntax does not model — an hour window, an hour step, and a weekday restriction together (e.g.
0 6-18/2 * * 1,2,3,4,5 = every 2 hours from 06:00–18:00, Monday–Friday). For these, every friendly field is null and only cron is populated. Read cron to get the exact schedule.
Raw cron expression (power-user escape hatch)
{ "type": "time", "cron": "0 9 * * *", "timezone": "UTC" }
- Provide
cron instead of friendly fields. The two forms are mutually exclusive.
- The minute field must be
0, */15, or */30. Any other value returns 422 invalid_trigger.
Trigger type: workflow_finished (chained execution)
Run this workflow immediately after another workflow completes.
{ "type": "workflow_finished", "after_workflow_id": "abc123" }
after_workflow_id is the parent workflow whose completion fires this trigger.
- Requires workflow ownership (not just edit permission) — see
not_workflow_owner below.
- Returns
409 circular_trigger if the relationship would create a trigger loop.
Response shape
GET and PUT return the full read model; DELETE returns the disabled state.
{
"active": true,
"type": "time",
"frequency": "daily",
"every": null,
"time": "09:00",
"weekday": null,
"day_of_month": null,
"cron": "0 9 * * *",
"timezone": "Europe/Berlin",
"after_workflow_id": null
}
An inactive / never-set trigger returns { "active": false, "type": null, ... } with all other fields null.
curl examples
Daily time trigger:
curl -X PUT /rest/beta/workflows/{id}/trigger \
-H "Authorization: Bearer sg_..." \
-H "Content-Type: application/json" \
-d '{"type":"time","frequency":"daily","time":"09:00","timezone":"Europe/Berlin"}'
15-minute interval:
curl -X PUT /rest/beta/workflows/{id}/trigger \
-H "Authorization: Bearer sg_..." \
-H "Content-Type: application/json" \
-d '{"type":"time","frequency":"minutes","every":15}'
workflow_finished trigger:
curl -X PUT /rest/beta/workflows/{id}/trigger \
-H "Authorization: Bearer sg_..." \
-H "Content-Type: application/json" \
-d '{"type":"workflow_finished","after_workflow_id":"parent-workflow-id"}'
Turn off a trigger:
curl -X DELETE /rest/beta/workflows/{id}/trigger \
-H "Authorization: Bearer sg_..."
Error codes
All errors return { "code": "...", "detail": "..." }.
| HTTP |
code |
When |
| 422 |
invalid_trigger |
Bad/missing fields, both cron and friendly fields supplied, or raw-cron minute not 0, */15, */30. |
| 403 |
permission_denied |
Caller lacks edit or disable permission on the workflow. |
| 403 |
not_workflow_owner |
workflow_finished requires workflow ownership. |
| 403 |
plan_upgrade_required |
The account plan does not include this trigger type or feature. |
| 409 |
circular_trigger |
The chosen parent would create a trigger loop. |
| 404 |
workflow_not_found |
The workflow (or parent) does not exist or is not accessible. |
| 500 |
— |
{ "status": 0, "error": "internal" } |