Who this is for. Anyone building a job's actions who needs one action type's exact behaviour: what it takes, what it leaves for later actions, and when it fails. Afterwards you can wire an action with the right settings the first time.

Every action type a job can run, one entry each: what it takes, what it leaves in the batch for later actions (runData.get('its-name')), what happens when it fails, and whether it can run in a synchronous job. The types are read from the platform's source. Worked configurations are on Actions, what a job does.

A failed action stops the batch with the status error: the actions after it do not run and the ones before it are not undone. The entries below say when an action fails and when it does not. An unpublished action is skipped only when it is a direct, top-level action of the job; inside a condition's branch or a loop it still runs.

Records

Retrieve records

TakesEntity (not orders, invoices, quotes or form submissions); criteria as JSON, each value a template; order; limit; offset
Leavesrecords, and record when exactly one matched
Fails whenThe criteria are not valid JSON, a criterion compares a date field (criteria are text, and a date needs a real date: select in a template instead), or the limit is not a number. Finding nothing is a success with an empty list
SynchronousYes. Unpublished records are included in a synchronous run
ExampleProduct variants, {"code": "{$event->getQueryParameter('sku')}"}, limit 1

Create record

TakesEntity (not custom entity records, orders, invoices or form submissions); a template rendering the new record's data as JSON
Leavesid of the new record, and the data used
Fails whenThe rendered data is not JSON, or the record fails validation
SynchronousYes. From a synchronous job the new record fires CreateRecord jobs; from an asynchronous one it fires none
ExampleA person with externalId set from the triggering submission

Update record

TakesSource (the event's record, the loop's record, a Retrieve records result, or an entity and id); with a Retrieve records result, its Record index, which counts from 0 and defaults to 1, so set it to 0 for the first or only record; a template rendering the changed fields as JSON, in which a to-many field such as a person's groups replaces the whole set rather than adding to it
LeavesThe data applied
Fails whenThere is no source record (with the default record index and a single result: "Index 1 does not exist in collection with 1 elements"), the data is not JSON, or the change fails validation
SynchronousYes, and it then fires the record's UpdateRecord jobs: guard against recursion
ExampleSource: the event's record; data {"status": "synced"}. A find-or-create of a person, with the record index and the groups merge, is worked through on Creating records from a submission

Delete record

TakesSource, as for Update record
LeavesA message
Fails whenThere is no source record, or the record cannot be deleted
SynchronousYes
ExampleInside a loop over expired offers: source, the loop's record

HTTP

HTTP request

TakesMethod; URL; headers; body template; timeout 10 to 120 s (60 by default); retries 0 to 10; accepted status codes (2** by default, comma-separated)
LeavesresponseCode, responseHeaders, responseData (JSON or XML, parsed), responseBody
Fails whenThe status is not accepted after the retries, or the request times out. The batch log records the request it sent, headers included
SynchronousYes; the caller waits for the other system too
ExamplePOST to a CRM, Authorization: Bearer {$siteData->get('crm-api-key')}, accepted 2**,409

HTTP response

TakesStatus code; headers; body; stop execution
LeavesThe status, headers and body sent
Fails whenThe status does not render to a three-digit code from 100 to 599, or the body template fails (a hand-typed JSON body in Smarty does)
SynchronousOnly meaningful there: it is the reply to a synchronous web event. The last one to succeed is sent
Example404, Content-Type: application/json, {$payload|json_encode}

Messages and output

Send mail

TakesTo, cc, bcc (addresses, Name <address> or person ids, one per line); from; reply-to; subject; body typed in or from a template file
LeavesThe template used; the message is queued
Fails whenA template fails to render, or an address is not a valid email, Name <address> or person id. Delivery problems happen after the batch, in the mailer, and do not fail it
SynchronousYes; the message is only queued
ExampleTo {$event->getRecord()->data['email']}, body templates/hooks/emails/thank-you.html. No attachments. Worked emails: Email from jobs

Render template

TakesA template typed in, or a file under templates/hooks/
Leavescontent; very long output is kept in a temporary file instead
Fails whenThe template has an error, which is reported when the job runs, not when it is saved
SynchronousYes
ExampleA CSV of the products an earlier Retrieve records found, saved next by Create file

Files

Create file

TakesFilename (a template); days until it expires; content from a template, a template file, or an earlier Render template or HTTP request
LeavesThe file record
Fails whenThe source action has no content (an HTTP request action whose answer was parsed as JSON or XML leaves none, so Create file fails with "HTTP response body did not contain any content"), or the file cannot be written
SynchronousYes
ExampleSource: an HTTP request to an HTML-to-PDF service; filename /certificates/{$event->getRecordId()}-{bin2hex(openssl_random_pseudo_bytes(8))}.pdf. A name without a folder is kept in the batch's folder and deleted with the batch

Merge files

TakesThe files, by criteria or listed by a template; output filename; expiry
Leavesfile, the joined file
Fails whenThe files cannot be found or read
SynchronousYes
ExampleThe CSV parts a loop wrote, joined end to end into one export

Merge PDFs

TakesAs Merge files; the files must already be PDFs
Leavesfile, the joined PDF
Fails whenThe files cannot be found or read. It converts nothing: give it anything but PDFs and the result is not a usable PDF
SynchronousYes
ExampleA generated certificate followed by a standard terms page

Flow

Condition

TakesIf branches, each of type entity event (criteria against the event's record) or template (matches on setMatching(true)), and an optional else; child actions per branch
LeavesWhich branch matched, in the log
Fails whenA branch's template has an error. No match and no else is skipped, and the job carries on
SynchronousYes
Example{if $runData->get('find-contact')->record}{$result->setMatching(true)}{/if}

Loop

TakesSource (a Retrieve records action's records, an HTTP request action's JSON or XML answer at a property path, elements a template adds with loopHelper, the web event body at a path, or a site data key); processing parallel or sequential; wait success, done or none; retries 0 to 5; stop on error
LeavesOne loop element per item, each with its own status; loopRecord and loopElement inside
Fails whenDepends on its settings: see error containment. A batch waits for its loop for at most eight hours. A template source that adds a record rather than a plain value or array fails
SynchronousYes, but its elements run one after another inside the request
ExampleSource: find-products; parallel; wait done; stop on error off

Trigger job

TakesThe target job; event data, a template rendering JSON
LeavestargetBatch, the target batch's id. No reply: that exists only for a batch a web event started, never for one a job triggered
Fails whenA synchronous target ends in error. An asynchronous target is only queued, so its failure does not reach this batch
SynchronousYes; a synchronous target then runs inside the same request
ExampleTarget "Job: after order → email warehouse", data {$payload|json_encode}

Stop

TakesThe batch status to end with: success, error or skipped; optionally, force the batch's clean-up
LeavesEnds the batch, or inside a loop just that loop element, with the chosen status once the current top-level action finishes: later actions in the same condition branch still run, and only the later top-level actions are skipped. Earlier actions keep their effects
Fails whenNever itself. A stop with status error marks the batch as an error
SynchronousYes, but a web caller with no reply sent gets HTTP 500 for skipped or error: reply first with an HTTP response set to stop
ExampleInside a condition that matches test records on production

AI agent

TakesAn agent from the agent library, its instructions and the batch's data
LeavesThe agent's result
Fails whenThe agent cannot run, for example with no provider credentials configured. An escalation to a person pauses the batch as waiting rather than failing it
SynchronousNo. Refused on a synchronous job, and inside a loop
ExampleClassify an enquiry's topic before routing it. Setup: AI Agents