Start workflows from data events, schedules, dashboard buttons or your own API routes, and use trigger filters so a workflow only runs when it should.
A trigger decides when a workflow runs and what data the job starts with. A workflow can have several triggers of different types — for example, run when an order is created and every night at 02:00 to catch anything missed.
Add and edit triggers in the workflow editor under Workflow Settings.
Event triggers run a workflow when something happens in your project.
| Event | Fires when | $anythink.trigger.id |
$anythink.trigger.data |
|---|---|---|---|
EntityCreated |
A record is created through the API, in bulk or by import | The new record's id | The fields that were sent, not the saved row (see below) |
EntityUpdated |
A record is updated | The record's id | The full record after the update |
UserRegistered |
Someone registers in your project | The user's id | first_name, last_name, email, referral_code |
UserInvited |
A user is invited | The user's id | first_name, last_name, email, referral_code |
SubscriptionCreated, SubscriptionActivated, SubscriptionExpired |
An AnythinkPay subscription is created, activated or expires | 0 |
The subscription |
PaymentCreated, PaymentSucceeded, PaymentFailed |
An AnythinkPay payment is created, succeeds or fails | 0 |
The payment |
PaymentMethodCaptured, PaymentMethodCaptureFailed, PaymentMethodRemoved |
A saved payment method is captured, fails to capture or is removed | 0 |
The payment method |
PushActionTaken |
A user taps a push notification action button | The user's id, or 0 |
notification_id, category, action_id, target_user_id, received_at, responded_at and any custom data |
For the three entity events, choose the entity in Entity. For PushActionTaken, the entity box is the notification category; leave it empty to react to every category.
Note: On
EntityCreated,trigger.dataholds the fields in the create request, so it doesn't include the newidor values the server filled in. Use{{ $anythink.trigger.id }}for the id, or add a Read data step to load the saved record.
Limit:
EntityDeletedappears in the event list but doesn't fire yet. Don't build on it.
A filter makes an event trigger skip events you don't care about. Filters are checked before a job is created, so a filtered-out event costs nothing and leaves no job in Job History.
Filters are a tree of and, or and not groups around conditions:
{
"and": [
{ "field": "status", "op": "changed_to", "value": "paid" },
{ "field": "total", "op": "gte", "value": 100 }
]
}
op |
Matches when |
|---|---|
eq, neq |
The field equals (or doesn't equal) value. Numbers compare as numbers. |
gt, gte, lt, lte |
The field compares with value as a number, then as a date, then as text. Null never matches. |
in |
value is a list that contains the field's value |
contains |
The field's text contains value, ignoring case |
is_null, is_not_null |
The field is missing or null, or present and not null |
changed |
The field's value is different from before the update |
changed_to |
The field changed and now equals value |
How filters behave:
field is a top-level field on the record. Dotted paths and related records aren't supported.changed and changed_to only work on EntityUpdated, the only event that knows the previous values.true doesn't equal the text "true".2026-09-01) is compared as a date.and matches everything; an empty or matches nothing.op counts as a match, so check spelling — a typo makes the filter let every event through.The dashboard filter builder covers and conditions. Use the workflow API to save or and not groups.
Timed triggers run on a cron schedule.
| Setting | Value |
|---|---|
cron_expression |
Five fields: minute, hour, day of month, month, day of week. No seconds field. |
| Time zone | UTC. 0 9 * * * runs at 09:00 UTC, which is 10:00 in London during summer time. |
| Resolution | One minute. Anythink checks for due schedules every minute. |
| Schedule | Cron |
|---|---|
| Every 15 minutes | */15 * * * * |
| Every day at 02:00 UTC | 0 2 * * * |
| Weekdays at 08:30 UTC | 30 8 * * 1-5 |
| First day of the month | 0 0 1 * * |
Timed jobs start with an empty payload: there's no trigger.id or trigger.data. Begin with a Read data step to fetch what the job should work on.
Limit: Missed runs aren't caught up. If a timed workflow is disabled, it doesn't run while disabled; when you enable it again it runs once at the next minute, then follows its schedule.
Note: An invalid cron expression is saved but never runs. After saving, check the schedule's next run time.
Manual triggers add the workflow to the Workflows menu on records of the entities you choose. Running it from a record starts a job with that record's id in {{ $anythink.trigger.id }} and the entity name in the payload; trigger.data is empty, so load the record with Read data if you need its fields.
You can also start a workflow from your own code:
POST /org/{orgId}/workflows/{workflowId}/trigger
Authorization: Bearer <token>
Content-Type: application/json
{
"entity_name": "orders",
"entity_id": 1042,
"data": "{\"reason\":\"manual resend\"}"
}
data is a JSON string, not an object. It becomes trigger.data.entity_name is required and must be one of the trigger's entities.anythink_workflows:trigger permission.204 No Content. The job runs in the background.Limit:
anythink workflows create <name> --trigger Manual --entity <entity>saves the trigger with no entities attached, so calls to it are then rejected with "not permitted for this workflow". Until this is fixed, create the workflow first, then set its entities in the Anythink dashboard.
An API endpoint trigger gives the workflow its own route:
POST /org/{orgId}/workflows/api/sync-orders?id=1042&entity_name=orders
Authorization: Bearer <token>
Content-Type: application/json
{ "source": "shopify", "since": "2026-09-01T00:00:00Z" }
| Rule | Detail |
|---|---|
| Method | POST only |
| Route | One path segment, such as sync-orders. Don't include slashes. Stored in lower case and matched without regard to case. |
| Uniqueness | Unique across the project's API endpoint triggers, including disabled ones |
| Authentication | A user token or an API key with anythink_workflows:trigger |
| Payload | The JSON body becomes trigger.data; the id and entity_name query parameters become trigger.id and the entity name |
| Response | 204 No Content when the job is queued, 404 when no enabled trigger has that route |
The response doesn't wait for the workflow, so an API endpoint trigger suits fire-and-forget work: imports, syncs and notifications. If your app needs the result, have the workflow write it to a record and read that record.
entity_name. Keep manual and API triggers on separate workflows.Note:
anythink workflows seeddoesn't apply a seed file'striggersarray — the workflow is created with a single default Manual trigger regardless of what the file specifies, even thoughworkflows exportproduces atriggersarray in the same shape. Add extra triggers in the Anythink dashboard until this is fixed.
Note: Calls to the trigger endpoint and to API routes check the trigger's Enabled switch, not the workflow's. To stop a workflow's API route, disable that trigger.