Generation triggers
What this page is — rules that create a document automatically when something happens elsewhere in Orbit: an order placed or paid, a deal won, a form submitted.
What it is for — so the documents that follow predictably from an event — the invoice after payment, the agreement after a won deal — exist without anybody remembering to make them.
The problem it solves — documents that should follow automatically from an event depend on someone remembering to create them.
Route: /org/settings?tab=papers → Generation triggers · Permission:
Configure triggers/webhooks/auto-generation rules..
1. What it is
A trigger joins one event to one document type. The events are a curated list — a typed event name that is never published would produce a trigger that silently never fires.
| Event | Published when | Default source map | Title example |
|---|---|---|---|
Order paid order.paid | A customer order is marked paid | order_id ← order.id | Tax Invoice for {{order.number}} |
Order placed order.placed | An order is created, not yet paid | order_id ← order.id | Proforma Invoice for {{order.number}} |
Deal won deal.won | A CRM deal moves to won | deal_id ← deal.id, contact_id ← contact_id | Agreement — {{deal.title}} |
Intake form submitted form.submitted | A marketing or intake form is submitted | form_id, submission_id | Request from {{event.fields.customer_name}} |
How an event becomes a document:
| Step | What happens |
|---|---|
| 1 | The publishing module writes the event to the Papers outbox, in its own transaction |
| 2 | The outbox worker picks it up — about every minute |
| 3 | Each active trigger for that event creates a document from the type's published version, in the event's project |
| 4 | The source map links the document to the record, so merge sources like order.* and deal.* fill fields |
| 5 | Optionally, the document is submitted and/or finalized automatically |
| 6 | Redelivery of the same event does not generate a second document |
2. Why you would use it
- The late documents stop being late. Invoices after payment and agreements after a won deal are the ones that wait on someone noticing.
- Data flows in, not typed in. The order or deal fills the document through merge sources.
- Fully hands-off, if you want. With auto-finalize an invoice is numbered and sealed the moment payment lands.
- Safe under retries. The outbox is at-least-once; generation is idempotent.
3. Step by step
- + Trigger → pick the Event.
- Pick the Document type — only active, published types are offered.
- Write a Title template, starting from the example.
- Keep the default Source map unless you know the payload.
- Choose Auto-submit and Auto-finalize.
- Save and leave it active. Cause the event once in a test project and check the documents list.
4. Field reference
| Field | Rules | Refusal |
|---|---|---|
| Event | One of the four | event_type is required |
| Document type | In scope, active, published | type_id does not reference a document type in this scope · at generation: target type has no published version |
| Title template | Tokens from the event payload | — |
| Source map | Document reference key → payload path | source_map must be a JSON object of source_ref key -> payload path |
| Auto-submit | Submits the generated draft | Subject to the lifecycle's rules |
| Auto-finalize | Seals the generated document | Numbered from the type's sequence; a failure is recorded, and the draft remains |
| Active | On / off | — |
The panel offers only keys each publisher actually sends. Editing the map to a path that is not in the payload produces documents whose merge fields are silently empty.
5. Worked example
A storefront finance team wants a tax invoice for every paid order.
| Setting | Value |
|---|---|
| Event | Order paid |
| Document type | Tax Invoice |
| Title template | Tax Invoice for {{order.number}} |
| Source map | order_id ← order.id (default) |
| Auto-finalize | On |
Order SO-10429 is paid at 14:02. At about 14:03 the list shows Tax Invoice for SO-10429, already finalized:
number INV/2026-27/00118, sealed PDF, line items and customer filled from the order via order.* merge
sources.
The payment gateway retries the webhook at 14:05. No second invoice appears.
A month later someone retires the Tax Invoice type while drafting a new one. Paid orders now generate nothing — target type has no published version in the outbox audit — until they publish the replacement and point the trigger at it.
6. The admin contract
| Must be true | Where | What breaks without it |
|---|---|---|
| The role holds Configure triggers/webhooks/auto-generation rules. | Role editor | The section is missing |
| The type is active and published | Type Designer | Generation fails, recorded only in the outbox audit |
| The type's fields use matching merge sources | Fields | Documents arrive empty |
| A numbering sequence is bound, for auto-finalize | Behaviour | Invoices seal unnumbered |
| The outbox worker job is enabled | Job monitor | Events queue and nothing is generated |
7. Downstream
| When… | Then |
|---|---|
| The event fires | A document appears in the event's project |
| Auto-finalize is on | It is numbered and sealed at once |
| You deactivate a trigger | Future events generate nothing; past documents stay |
8. Don't confuse this with…
| Intake forms | Form-specific bridges with a field map. Both can fire on one submission |
| Webhooks | Papers telling other systems about documents |
| Capture inbox | Files arriving from outside |
9. Troubleshooting
| Symptom | Cause |
|---|---|
| No document was generated | Trigger inactive, type unpublished, outbox worker off, or the event happened in another project |
| Fields are empty | The type's fields lack matching merge sources, or the source map was edited |
| Two documents per form submission | A trigger and an intake bridge both listen |
| An auto-finalized document has no number | The type binds no sequence |
| A retried event created nothing new | Idempotency — expected |