# Recipes

Workflows worth building, including the one that closes a gap nothing else covers.

## From a form to an issued invoice

The shape most people want first: someone fills in a form and receives an invoice.

```text
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.

<Callout type="info">
  Store the raw form response before anything else. If a later step fails, what the customer asked
  for is not lost.
</Callout>

---

## Sweep the charges that never became invoices

This one closes a gap nothing else covers.

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. A charge that took money without producing an invoice is only
visible by asking for it: a payment with no invoice that nobody notices. It is exactly the sort of
boring hourly job you do not want depending on someone remembering.

<Callout type="warn" title="Build this one with the HTTP Request node">
  In the current release of the node (0.2.2), the **Payment Event** operations and **Payment
  Connection → Disconnect** still address a connection by its provider, a route shape the API no
  longer serves, so they fail. Until a release fixes them, call the API from an **HTTP Request** node
  with a header credential `Authorization: Bearer <your API key>`. Each connection has its own ID,
  which **Payment Connection → Get Many** returns.
</Callout>

```text
Schedule (hourly)
  └─▶ Payment Connection → Get Many          ← gives each connection's id
       └─▶ HTTP Request: GET /v1/companies/{company_id}/payment-connections/{connection_id}/events
           ?needs_action=true                ← only the events still worth acting on
            ├─ retry_available ─▶ HTTP Request: POST …/events/{event_id}/retry
            └─ draft_available ─▶ HTTP Request: POST …/events/{event_id}/draft + notify
```

Each 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,
`draft` when a human should look before issuing. The full request and response are in
[List payment events](/payment-events/listCompanyPaymentEvents).

---

## Watch for recurring invoices that stopped

Two nodes, and it prevents a quiet revenue leak.

```text
BeeL Trigger (recurring_invoice.paused) ─▶ notify the team
```

BeeL. 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

```text
BeeL Trigger (verifactu.status.updated) ─▶ if REJECTED ─▶ alert
```

Issuing 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.

---

## Events the trigger does not offer

The **BeeL Trigger** lists eight events. The API sends two more that the trigger does not offer in
version 0.2.2:

- `invoice.pdf.generated` — the PDF of an invoice is ready.
- `invoice.schedule_failed` — a scheduled invoice could not be generated on its date.

To start a workflow on either one, use n8n's generic **Webhook** node and subscribe to it yourself:

1. Add a **Webhook** node (method `POST`) and turn on its **Raw Body** option. The signature is
   computed over the exact bytes BeeL. sent.
2. Create the subscription with an **HTTP Request** node or any client:
   `POST /v1/accounts/{account_id}/webhooks` with the Webhook node's production URL and the events
   you want. See [Create a webhook subscription](/webhooks/createAccountWebhookSubscription). The
   response carries the signing secret, and only this once: store it in an n8n credential.
3. Verify the `BeeL-Signature` header before doing anything with the payload: an HMAC-SHA256 of
   `t`, a `.` and the raw body, with that secret, plus the 5-minute timestamp check. The steps are
   in [Signatures](/webhooks/signatures). Stop the workflow when it does not match.

The BeeL Trigger does all three for you, which is why it is the better choice for the events it
lists.

## Related

<Related>

- [Install and connect](/n8n/install) — set up the node first
- [Webhook events](/webhooks/events) — every event BeeL. sends
- [Signature verification](/webhooks/signatures) — verify a delivery yourself

</Related>

---

Full OpenAPI spec: https://docs.beel.es/api/openapi