HOC SiteDokümantasyon

Yaşam döngüleri

Kayıtlar oluşturulduğunda veya değiştiğinde e-posta, uygulama içi ve tarayıcı bildirimleri, alan güncellemeleri, zamanlanmış tetikleyiciler ve kayıt oluşturma eylemlerini otomatikleştirin (şema odaklı; nesne türü başına en fazla 20 olay).

Per object type, lifecycles run automated actions when entries are created, updated, or become due on a schedule. Configure them in Admin → Objects → Lifecycles, or via the API/MCP lifecycle endpoints.

How it works

A lifecycle config is { version: 3, events: [...] }. Each event has: id, name, optional enabled (default true), when (trigger), constraints (all must pass), and actions. On create/update, matching events run in order. Schedule events are evaluated by a periodic worker sweep (not one-shot enqueue). Actions can send email, create in-app notifications, modify fields, create related entries, update matching entries, adjust a number, or run an integration query. update_matching_entries writes existing rows of another type, then recalculates this entry before the next action. Nested email/notification actions can include links or one-click trigger tokens that apply modify_field effects when opened.

Scheduled events

Use when: { type: "schedule", anchorPath, offsetDays } where anchorPath is an own date/dateTime field or created_at/mutated_at. offsetDays is an integer (default 0; negative allowed). Due instant is the start of the UTC calendar day of the anchor plus the offset. The event is eligible when now >= due. Each firing is recorded once per (entry, event, due_at); if the anchor date later changes, a new due key can fire again.

Field bindings & templates

Binding paths reference own fields (title) or short relation chains (author.display_name, max depth limited by schema). Email/notification subject and title use template segments: { kind: "text", text } or { kind: "field", fieldKey }. HTML bodies may embed {{fieldKey}} placeholders for field chips from the rich-text editor.

Constraints

Constraints are field_compare (leftPath + op + optional right) or related_count (inverse relation count). field_compare rights may be a literal, another field path, or { kind: "relative_date", path, offsetDays } for date comparisons. created_at / mutated_at may be used as date sides. Use changed / changed_to only on update events. related_count counts entries of another type whose relation field points at the current entry (op: eq/neq/lt/gt).

Safety guards

The engine rejects configs that form modify-field cycles across events, or that modify the same field twice in one event. create_entry may trigger the destination type's entry_created events with the same depth/ruleStack caps as nested updates. Prefer a single modify_field per field per event; chain follow-up work with constraints on the next update.

API & MCP

Read/update lifecycle JSON with GET/PUT /api/v1/{locale}/{websiteId}/objects/{objectTypeId}/lifecycle. MCP tools: get_object_lifecycle, save_object_lifecycle. Use get_docs path=lifecycles for this guide.

Reference

Event triggers

  • entry_created — Fires after a new entry is successfully created.
  • entry_updated — Fires after an entry is updated. Pair with changed / changed_to constraints.
  • schedule — Fires from the task worker when now is on/after anchorPath + offsetDays (day granularity).

Actions

  • send_email — Email to self, a user-relation path, or legacy email field. Optional nested link/trigger actions.
  • create_notification — In-app notification to a relation_user path. Optional link actions.
  • modify_field — Set a field on the current entry to a literal value.
  • create_entry — Create an entry of another type. Each target field maps from a literal, a compatible source field, or self (relation to the triggering entry).
  • adjust_number — Add or subtract from a number field, optionally through relationPath. Provide delta and/or deltaFromField (a number on the triggering entry, multiplied by sign 1 or -1). mode check reads the value and fails when the result would go below zero. mode apply (default) is one conditional update that changes nothing when the result would go below zero.
  • update_matching_entries — Update existing entries of objectTypeSlug whose where clauses match this entry. set is an array of 1–8 items, each { fieldKey, valueFrom: "literal", value } or { fieldKey, valueFrom: "self" }. valueFrom self writes a relation to the triggering entry. Calculated fields on this entry are recomputed before the next action.
  • run_integration_query — Run an integration query by queryId. request.delivery await on that query finishes before the action returns. queue (the default when delivery is omitted) enqueues the call.

Constraint operators

  • eq / neq — Equal / not equal to literal or field.
  • empty / not_empty — Presence checks.
  • lt / gt — Numeric comparisons (and related_count).
  • before / after — Date/time comparisons (literal, field, or relative_date).
  • changed / changed_to — Update-only: field changed, or changed to a value.
  • related_count — Compare how many inverse-related entries exist (eq/neq/lt/gt).

Relation hops

  • forward — Follow a relation field on the current type.
  • inverse — Hop via another type that points at this entry.
  • match — Match another type on a shared field value.

Examples

Welcome email after approval

On update, when approved changes to true, email the member and include a login link.

{
  "version": 3,
  "events": [
    {
      "id": "welcome_after_approval",
      "name": "Welcome member",
      "when": {
        "type": "entry_updated"
      },
      "constraints": [
        {
          "type": "field_compare",
          "leftPath": "approved",
          "op": "changed_to",
          "right": {
            "kind": "literal",
            "value": true
          }
        }
      ],
      "actions": [
        {
          "type": "send_email",
          "emailFieldKey": "self",
          "subject": [
            {
              "kind": "text",
              "text": "Welcome to "
            },
            {
              "kind": "field",
              "fieldKey": "display_name"
            }
          ],
          "bodyHtml": "<p>Your account is ready.</p>",
          "actions": [
            {
              "type": "link",
              "label": "Sign in",
              "pathTemplate": "/login"
            }
          ]
        }
      ]
    }
  ]
}

Email verification with trigger

On create, send a verification email whose button is a trigger token that sets email_verified (and optionally approved) when clicked.

{
  "version": 3,
  "events": [
    {
      "id": "send_email_verification",
      "name": "Send email verification",
      "when": {
        "type": "entry_created"
      },
      "constraints": [],
      "actions": [
        {
          "type": "send_email",
          "emailFieldKey": "self",
          "subject": [
            {
              "kind": "text",
              "text": "Verify your email"
            }
          ],
          "bodyHtml": "<p>Click below to verify.</p>",
          "actions": [
            {
              "type": "trigger",
              "label": "Verify your email",
              "tokenTtlMinutes": 1440,
              "effects": [
                {
                  "type": "modify_field",
                  "fieldKey": "email_verified",
                  "value": true
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Notify author on status change

Create an in-app notification for a related user when a status field changes.

{
  "version": 3,
  "events": [
    {
      "id": "notify_status",
      "name": "Notify author of status",
      "when": {
        "type": "entry_updated"
      },
      "constraints": [
        {
          "type": "field_compare",
          "leftPath": "status",
          "op": "changed"
        }
      ],
      "actions": [
        {
          "type": "create_notification",
          "targetPath": [
            {
              "kind": "forward",
              "fieldKey": "author"
            }
          ],
          "title": [
            {
              "kind": "text",
              "text": "Status updated"
            }
          ],
          "bodyHtml": "<p>Your item status changed.</p>",
          "actions": [
            {
              "type": "link",
              "label": "View",
              "pathTemplate": "/items/[id]",
              "appendEntryHash": true
            }
          ]
        }
      ]
    }
  ]
}

Schedule first related entry

When first_service_after is due and no service appointments point at this order yet, create one with mapped fields.

{
  "version": 3,
  "events": [
    {
      "id": "schedule_first_service",
      "name": "Create first service appointment",
      "when": {
        "type": "schedule",
        "anchorPath": "first_service_after",
        "offsetDays": 0
      },
      "constraints": [
        {
          "type": "related_count",
          "objectTypeSlug": "service_appointment",
          "fieldKey": "order",
          "op": "eq",
          "value": 0
        }
      ],
      "actions": [
        {
          "type": "create_entry",
          "objectTypeSlug": "service_appointment",
          "fields": [
            {
              "fieldKey": "order",
              "source": {
                "kind": "self"
              }
            },
            {
              "fieldKey": "scheduled_for",
              "source": {
                "kind": "field",
                "path": "first_service_after"
              }
            },
            {
              "fieldKey": "status",
              "source": {
                "kind": "literal",
                "value": "planned"
              }
            }
          ]
        }
      ]
    }
  ]
}

Notes

  • Omit enabled or set enabled: true to keep an event active; set enabled: false to soft-disable.
  • Locale overlays can localize event names, email subject/body, and action labels per website locale.
  • Trigger tokens are time-limited (tokenTtlMinutes) and apply effects once when redeemed.
  • Schedule events use day granularity only; hour/minute offsets are out of scope for v1.