Recipes
Workflows worth building, including the one that closes a gap nothing else covers.
From a form to a legal invoice
The shape most people want first: someone fills in a form and receives an official invoice.
Form (NIF, name, email, concept, amount)
└─▶ store the raw request
└─▶ NIF → Validate ← real AEAT lookup
├─ invalid ─▶ end: "that NIF does not exist"
└─ valid
└─▶ Customer → Get Many (filter by NIF)
├─ found ─────────────┐
└─ not found ─▶ Create┴─▶ Merge
└─▶ Company → Issuing Readiness
├─ not ready ─▶ end: says what is missing
└─ ready ─▶ Invoice → Create
(issue_directly + send_automatically)Three details carry this workflow:
Validate the NIF first. It is one node and a real lookup against the AEAT registry — an invented NIF is rejected before anything is created.
Ask before you issue. Issuing Readiness answers whether the company can issue right now and
what is missing if not, instead of you attempting it and reading an error.
Derive the idempotency key from the submission. Two clicks on the button, or a re-run, then return the invoice that already exists rather than issuing a second one.
Store the raw form response before anything else. If a later step fails, what the customer asked for is not lost.
Sweep the charges that never became invoices
This one closes a gap nothing else covers, and it is the reason Payment Event is exposed at all.
The native Stripe connection invoices every charge automatically. Sometimes that fails — a missing default series, for instance. When it does:
- No webhook is emitted. There is no event for a payment that failed to invoice.
- The list takes no server-side filter. You cannot query for the broken ones.
So a charge that took money without producing an invoice is only visible by sweeping the collection and sifting. With VeriFactu that is a compliance hole, and it is exactly the sort of boring hourly job you do not want depending on someone remembering.
Schedule (hourly)
└─▶ Payment Event → Get Many ← paginate; no filter available
└─▶ keep needs_action = true
├─ retry_available ─▶ Retry
└─ draft_available ─▶ Generate Draft + notifyEach event carries failure_category and failure_reason, plus retry_available and
draft_available telling you which recovery it accepts: Retry when the cause was transient,
Generate Draft when a human should look before issuing.
Watch for recurring invoices that stopped
Two nodes, and it prevents a quiet revenue leak.
BeeL Trigger (recurring_invoice.paused) ─▶ notify the teamBeeL. pauses a recurring invoice on its own after repeated generation failures or a downgrade. If
nobody watches that event, a monthly invoice silently stops being issued and you find out at the end
of the quarter. To resume it once fixed: Recurring Invoice → Set Status → ACTIVE.
Alert on VeriFactu rejections
BeeL Trigger (verifactu.status.updated) ─▶ if REJECTED ─▶ alertIssuing is not the same as complying. The invoice gets its number immediately, but the AEAT answers afterwards. Most integrations stop at "issued" and never learn that a submission was rejected.
Pair it with a daily sweep as a belt-and-braces: Invoice → Get Many filtered by
verifactu_status = REJECTED catches anything whose webhook delivery was lost.