powered by

Triggers and scheduling

Start a workflow from a record change, a schedule, a dashboard button or an API route, and add trigger filters so it only runs when it should.

Last updated

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. Any of them starts the same steps.

Trigger Trigger Type Starts a job when
Event Event A record is created or updated, a user registers or is invited, a payment or subscription changes, or someone taps a push notification button
Timed Timed A cron schedule comes due
Manual Manual Someone runs it from a record in the Anythink dashboard, or your code calls the trigger endpoint
API route API Call A POST reaches the workflow's own route

Every job starts with a payload of id, entity_name and data. Steps read them as {{ $anythink.trigger.id }}, {{ $anythink.trigger.entity_name }} and {{ $anythink.trigger.data.<field> }}. Each trigger type fills them differently, as the sections below show. For the model behind jobs and steps, see How workflows work.

Add a trigger

Every workflow needs at least one trigger. You choose the first when you create the workflow, and you can add more later.

In the Anythink dashboard

  1. Open Workflows and select New Workflow, or open an existing workflow.
  2. In the editor, select the Workflow Settings icon in the toolbar. For a new workflow the same fields are on the create form.
  3. Under Triggers, select Add trigger.
  4. Choose a Trigger Type and fill in the fields it shows: Event Type and Entity for an event, Schedule for a timed trigger, Entities for a manual trigger, API Route for an API call.
  5. Leave Enabled ticked, then select Save Changes.

With the CLI

workflows create makes a workflow with one trigger. The options depend on the type:

bash
# Event: a record changes
anythink workflows create order-paid \
  --trigger Event --event EntityUpdated --entity orders --enabled

# Timed: a cron schedule, in UTC
anythink workflows create nightly-report \
  --trigger Timed --cron "0 2 * * *" --enabled

# API route: no leading slash
anythink workflows create sync-orders \
  --trigger Api --api-route sync-orders --enabled

Each command prints the new workflow's id. Add steps with anythink workflows step-add, as described in Step types. To give a workflow more than one trigger, or a Manual trigger, use Workflow Settings in the Anythink dashboard.

With an AI assistant (MCP)

Create a workflow called nightly-report with a timed trigger that runs at 02:00 every day, and enable it.

The assistant runs workflows create through the cli tool. Name the trigger type, and the event, entity, cron expression or route that goes with it.

Event triggers

An event trigger runs a workflow when something happens in your project. Pick an Event Type. The dashboard shows the names below with spaces (Entity Created), and the CLI and API use them as written.

Event Starts when $anythink.trigger.id $anythink.trigger.data
EntityCreated A record is created through the REST API, in bulk or by import, or by a workflow step The new record's id The fields that were sent. It doesn't include the new id or values the server filled in.
EntityUpdated A record is updated The record's id The whole record as it is after the update
UserRegistered Someone registers with your project The user's id first_name, last_name, email, referral_code
UserInvited A user is invited to your project The user's id first_name, last_name, email, referral_code
PaymentCreated, PaymentSucceeded, PaymentFailed AnythinkPay records a payment 0 The payment
SubscriptionCreated, SubscriptionActivated, SubscriptionExpired A subscription is created, activated or expires 0 The subscription
PaymentMethodCaptured, PaymentMethodCaptureFailed, PaymentMethodRemoved A saved payment method is captured, fails to capture or is removed 0 The payment method
PushActionTaken A user taps an action button on a push notification The user's id, or 0 notification_id, category, action_id, target_user_id, received_at, responded_at and any extra data the app sent

For EntityCreated and EntityUpdated, choose the Entity to watch. The trigger can't be saved without one, and the entity has to exist. {{ $anythink.trigger.entity_name }} holds its name.

Note: On EntityCreated, the trigger data holds the fields in the create request. Read the new record's id from {{ $anythink.trigger.id }}, or add a Read data step to load the saved record.

Payment and subscription events are raised for Stripe activity. See Webhooks for the data each carries and an end-to-end example. For PushActionTaken, iOS button group is the notification category, and leaving it empty matches every category. See Push notifications from a workflow.

Event triggers fire for changes made by any route into the data: the REST API, the Anythink dashboard, imports, and other workflows' Create data and Update data steps. A workflow that updates the entity it watches starts itself again, so give it a filter that stops the loop.

Trigger filters

A filter makes an event trigger skip events you don't care about. It's checked before a job is created, so a filtered-out event creates no job and leaves nothing in Job History.

A filter is a tree of and, or and not groups around conditions:

json
{
  "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. A null field never matches.
in value is a list that contains the field's value, such as ["paid", "shipped"]
contains The field's text contains value, ignoring case
is_null, is_not_null The field is missing or null, or is present and not null
changed The field's value is different from before the update
changed_to The field changed and now equals value

Use only the operators in this table.

  • field is a top-level field on the record. Dotted paths and related records aren't supported.
  • On EntityCreated, the filter sees only the fields in the create request. On EntityUpdated, it sees the whole record after the update.
  • changed and changed_to need the previous values, which only EntityUpdated has. They never match on other events.
  • Types matter: the boolean true doesn't equal the text "true". Text that looks like a date, such as 2026-09-01, is compared as a date.
  • An empty and matches everything and an empty or matches nothing.
  • For PushActionTaken, the filter runs against the trigger data, so { "field": "action_id", "op": "eq", "value": "snooze" } reacts to one button.

In the Anythink dashboard

  1. In Workflow Settings, set Trigger Type to Event and choose an Event Type and Entity.
  2. Under the entity, select Add filter. The builder is headed Fire only when….
  3. Pick a field, an operator and a value. Select + Condition for more, or + Group for a nested group.
  4. Choose All of these to require every condition, or Any of these to require one.
  5. Select Save Changes. To remove the filter, select Remove filter.

The builder builds and and or groups. To save a not group, use the CLI or the API.

With the CLI

bash
anythink workflows create order-paid \
  --trigger Event --event EntityUpdated --entity orders \
  --filter '{"and":[{"field":"status","op":"changed_to","value":"paid"},{"field":"total","op":"gte","value":100}]}' \
  --enabled

For a long filter, put the JSON in a file and pass --filter-file filter.json instead.

With an AI assistant (MCP)

Create a workflow called order-paid that runs when an order is updated, but only when its status changes to paid and the total is at least 100. Enable it.

The assistant runs workflows create with --filter through the cli tool.

Timed triggers

A timed trigger runs on a cron schedule.

Setting Value
cron_expression Five fields: minute, hour, day of month, month, day of week. There's 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 * *

A scheduled job has no record behind it. $anythink.trigger.id and $anythink.trigger.data are empty and entity_name is null. Begin with a Read data step to fetch what the job should work on. Each due schedule starts one job, and a schedule that was missed isn't replayed.

In the Anythink dashboard

  1. In Workflow Settings, set Trigger Type to Timed.
  2. Under Schedule, choose Interval, Daily, Weekly or Monthly and set the time. Times are UTC. An interval runs every 1 to 30 minutes or every 1 to 12 hours.
  3. Or select Use cron expression and enter the five fields.
  4. Check the summary under the schedule, such as Daily at 02:00, then select Save Changes and make sure the workflow is enabled.
  5. To run it once without waiting, select Test Workflow in the toolbar and then Run Test. This fires the workflow now and ignores the schedule.

With the CLI

bash
anythink workflows create nightly-report \
  --trigger Timed --cron "0 2 * * *" --enabled

anythink workflows trigger 42
anythink workflows jobs 42

Replace 42 with the workflow's id. workflows trigger runs it once now, and workflows jobs lists the runs. Without --cron the schedule is 0 9 * * *.

With an AI assistant (MCP)

Create a workflow called nightly-report that runs every weekday at 08:30 UTC, and enable it. Then run it once and show me the job.

The assistant runs workflows create --trigger Timed --cron "30 8 * * 1-5", then workflows trigger and workflows jobs through the cli tool.

Manual triggers

A manual trigger lists the entities it applies to. On the detail page of a record in one of those entities, the Workflows section lists the workflow with a play button. Selecting it and confirming starts a job with that record's id in {{ $anythink.trigger.id }} and the entity name in {{ $anythink.trigger.entity_name }}. trigger.data is empty, so load the record with a Read data step if you need its fields.

Your code can start the same job:

http
POST https://api.my.anythink.cloud/org/{project_id}/workflows/{workflow_id}/trigger
x-api-key: <your key>
Content-Type: application/json

{
  "entity_name": "orders",
  "entity_id": 1042,
  "data": "{\"reason\":\"manual resend\"}"
}
Field Detail
entity_name Required for a Manual trigger, and it must be one of the trigger's entities. Otherwise the call is rejected with a message that the workflow isn't permitted for that entity.
entity_id Optional. It becomes trigger.id.
data Optional. It's a JSON string, not an object, and it becomes trigger.data.

The caller needs the anythink_workflows:trigger permission. A successful call returns 204 No Content and the job runs in the background. See API keys for creating a key that carries only that permission.

In the Anythink dashboard

  1. In Workflow Settings, set Trigger Type to Manual.
  2. In Entities, choose one or more entities.
  3. Select Save Changes and enable the workflow.
  4. Open a record in one of those entities. In its Workflows section, select the play button next to the workflow and confirm with Trigger.
  5. To pick a record and edit the payload before running, select Test Workflow in the workflow editor, choose the Entity and Record, and select Run Test.

With the CLI

bash
anythink workflows trigger 42 \
  --entity orders --entity-id 1042 \
  --payload '{"reason":"manual resend"}'

--entity is required for a workflow with a Manual trigger. --payload is plain JSON, and the CLI sends it as the data string for you.

With an AI assistant (MCP)

Run workflow 42 for order 1042 with the payload {"reason": "manual resend"}, then show me the job.

The assistant runs workflows trigger and workflows jobs through the cli tool.

API route triggers

An API route trigger gives the workflow its own route:

http
POST https://api.my.anythink.cloud/org/{project_id}/workflows/api/sync-orders?id=1042&entity_name=orders
x-api-key: <your key>
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, with no slashes. Stored in lower case and matched without regard to case.
Uniqueness Unique across the project's API route triggers, including disabled ones
Authentication A user token, or an API key, with anythink_workflows:trigger
Payload The JSON body becomes trigger.data. The optional id and entity_name query parameters become trigger.id and trigger.entity_name. An empty body gives an empty data.
Response 204 No Content once the job is queued. 404 when no enabled trigger has that route.

The response doesn't wait for the workflow. This suits fire-and-forget work such as imports, syncs and notifications. If your app needs a result, have the workflow write it to a record and read that record. Webhooks covers creating the key and an end-to-end example.

In the Anythink dashboard

  1. In Workflow Settings, set Trigger Type to API Call.
  2. Enter an API Route such as sync-orders, with no leading slash.
  3. Select Save Changes and enable the workflow.

With the CLI

bash
anythink workflows create sync-orders \
  --trigger Api --api-route sync-orders --enabled

anythink fetch "/workflows/api/sync-orders?id=1042&entity_name=orders" \
  --method POST --body '{"source":"shopify"}'

The second command calls the route as the active profile. Then run anythink workflows jobs <workflow_id> to see the job.

With an AI assistant (MCP)

Create a workflow called sync-orders with an API route trigger on the route sync-orders, and enable it. Then call the route with {"source": "shopify"}.

The assistant runs workflows create and fetch through the cli tool.

Workflows with several triggers

  • Events: if more than one trigger on a workflow matches the same event, the workflow runs once. If several workflows watch the same event, each starts its own job.
  • Schedules: each timed trigger runs on its own schedule.
  • Which trigger started it: steps can't tell. If it matters, use separate workflows, or branch on the payload's shape with a Condition or Run a script step.

Enabling and disabling

  • The workflow's Enable Workflow setting stops its event and timed triggers from starting jobs, and hides its buttons on records.
  • Each trigger also has its own Enabled switch. Clear it to stop one trigger and leave the rest running.
  • For an API route, the trigger's Enabled switch decides whether the route answers. Clear it and callers get 404.
  • Changes apply to jobs that haven't started yet. A job that's already running finishes with the version it started with.

Check it worked

Fire the trigger once, then read the job.

  1. Cause the event, wait for the schedule, press the record button, or call the route.
  2. Open the workflow, select View Job History in the toolbar, and open the newest job. It shows the payload the trigger produced and the log and output of every step.
  3. Or run anythink workflows jobs <workflow_id>.

If an event trigger with a filter produced no job, the filter didn't match. Check the field name and value against the data in the table above, remembering that EntityCreated only has the fields that were sent. Test workflows and read job history covers reading jobs and tracking down failures.

Next steps