Guide 09 · Developer docs

Automation, jobs and integration

A job is a trigger, conditions and an ordered list of actions, set up under Customization › Orchestration in the admin; jobs were called hooks before the module was renamed, and the API's routes keep that name. What starts a job, what it can do, branches and loops, email, scheduled work, integrations with other systems, and every event and action.

L2–L3
Unit 03 · What a job does

Record actions

Retrieve Records, Create Record, Update Record and Delete Record: a working configuration for each, how fields are mapped from the event and earlier actions, which entities each can reach, and the failures that surprise people.

Who this is for. Anyone whose job reads or changes records on the site. Afterwards you can find, create, update and delete records from a job, and read the results in later actions.

Record actions work on the API's models and accept the API's syntax: the data a Create Record or Update Record sends is the JSON you would send to /cdna-api/… for that entity (Writing areas has the shape of each layout area type). They run with the permissions of the backend user who created the job.

Retrieve Records

Finds records and makes them available to later actions and loops. Its fields:

FieldTakes
EntityPages, blogs and posts, books, units and book pages, carts, categories, tags, custom fields, global components, widgets, custom entity records, FAQ pages and questions, files, folders and images, products, variants, descriptions and product categories, stock interests, rewrites, people, groups and users, and the site's own records
CriteriaBuilt with the admin's query builder; every value can contain template code. Through the API the criteria can also be JSON, keyed by field with an optional operator: {"code": "…"}, {"name_contains": "…"}, {"id_in": [1, 2]}
Order byJSON: {"name": "asc"}
Records limit, OffsetNumbers, or template code that renders to one. An empty limit retrieves every match

It leaves records (the collection) and record (the record when exactly one matched, otherwise empty). Finding nothing is a success with an empty collection: test for it with a condition rather than letting a later action fail on a missing record.

Two limits to know before designing a job around it:

  • Orders, invoices, quotes and form submissions are not in the list. A job holds one of those only as the record of its own entity event, or by calling the site's REST API with an HTTP Request, as the worked integration does.
  • A date field cannot be compared in the criteria. Criteria values are rendered to text, and a date column needs a date object: the action fails with Could not convert PHP value '…' of type 'string' to type 'datetime'. Select by date in a template with query instead (how).

Create Record

Takes an entity and Create data, a template that renders the new record as JSON, without an id. Build it as a value and encode it. Here a contact form submission becomes a person, reading the answers keyed by field name:

Template code
{$answers = $event->getRecord()->getData()}
{$data = [
  'firstName'  => $answers['firstName'],
  'lastName'   => $answers['lastName'],
  'email'      => $answers['email'],
  'externalId' => "form-submission:{$event->getRecordId()}"
]}
{$data|json_encode}
{% set answers = event.getRecord().getData() %}
{{ {
  'firstName': answers.firstName,
  'lastName': answers.lastName,
  'email': answers.email,
  'externalId': 'form-submission:' ~ event.getRecordId()
}|json_encode }}

It leaves id, the new record's id, with the entity and the data it sent. It fails when the rendered data is not JSON, is empty, contains an id, or fails the entity's validation, and the run log shows the parsed data either way. Give created records an externalId derived from what started the job, so a re-run can find the record instead of creating a second one (Idempotency and replay).

Create Record reaches fewer entities than Retrieve Records: not custom entity records and not carts, which a job can find and update but not create. It can also create admin notifications. A step-by-step find-or-create of a person from a form is on Creating records from a submission.

Update Record

Update Record and Delete Record first need to know which record. The Source setting answers it:

SourceThe record is
Entity EventThe record the job's entity event is about
ActionA record found by an earlier Retrieve Records, at Record index. The index counts from 0 and defaults to 1, so set it to 0 for the first or only record, or the action fails with Index 1 does not exist in collection with 1 elements
Loop RecordThe record of the current loop element
Entity and Record IDA fixed entity and an id, which can be template code

Update data renders the changed fields as JSON. Only the fields you send change, but a to-many field you send, such as a person's groups, replaces the whole set rather than adding to it. The action leaves the data it applied.

Template code
{$changes = ['status' => 'synced', 'syncedAt' => date('c')]}
{$changes|json_encode}
{{ {'status': 'synced', 'syncedAt': 'now'|date('c')}|json_encode }}

Delete Record

Takes a source, as Update Record, and deletes that record. It leaves the entity and id it deleted. Inside a loop over expired offers, with source Loop Record, it removes each in turn. A delete raises the entity's Deleted event only when it runs inside a web request; from a background job it raises none (which writes start jobs).

The records a job sees

Records reach a job as the API's models, not as the models a page template receives. Read a layout area through the active revision, getActiveRevision().getAreaText('intro'): getAreaText() on the record itself is a page-template method. A form submission's answers are getData(), keyed by field name. Unpublished records are included, so filter on published yourself when a job should only touch live content.

The other actions

Calling another system, and answering a web event: HTTP request and response.

Rendering output and sending it as email: Render template and send email.

The Send Email action is on the same page, Send Email.

Files, merged files, PDFs and certificates: Files, PDFs and certificates.

Trigger job and Stop: Stopping a job early and Chaining one job to another.

AI agents: AI agent actions.

Every action type, one entry each, is in the job action reference.

Go deeper

Was this page helpful?

Your answer goes to the docs team.