# Issuance and auto-send

> Explicit issuance vs the auto-send cron; booked-but-send-failed.

Source: https://invoia.io/developers/api/issuance

Issuing an invoice is the act of freezing it, booking it into Dinero,
and (optionally) sending it to the customer. Invoia supports two
patterns.

## Explicit issuance [#explicit-issuance]

Drive it from your integration when your workflow says "this project is
done":

```bash
# One-time invoice.
curl -X POST https://invoia.io/api/v1/invoices/ext:proj_ACME_migration/issue \
  -H "Authorization: Bearer $INVOIA_API_KEY"

# A series occurrence.
curl -X POST https://invoia.io/api/v1/recurring-series/ext:acme-retainer/occurrences/2026-07-01/issue \
  -H "Authorization: Bearer $INVOIA_API_KEY"
```

Issuance is **synchronous** and **idempotent** — a timeout-then-retry
returns the already-issued result, never double-books. Under the hood
Invoia's Dinero GUID guard is the same one the UI's issue button rides.

## auto\_send (cron-driven) [#auto_send-cron-driven]

Every invoice carries an `auto_send` boolean. When it's on, the Invoia
cron issues the invoice on its issue date without your involvement —
the exact same behaviour as the UI. Leave it on for hands-off retainers
and rely on the `invoice.issued` webhook to learn about the booking:

```js
// Your webhook receiver.
app.post('/webhooks/invoia', (req, res) => {
  const event = req.body
  if (event.type === 'invoice.issued') {
    await syncInvoiceToPmTool(event.data)
  }
  res.status(200).end()
})
```

Toggle it via the invoice PATCH:

```bash
curl -X PATCH https://invoia.io/api/v1/invoices/ext:proj_ACME_migration \
  -H "Authorization: Bearer $INVOIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "auto_send": false }'
```

## Booked-but-send-failed (200 + `send_error`) [#booked-but-send-failed-200--send_error]

Issuance in Invoia is two steps: **book** the invoice into Dinero, then
**send** it to the customer (email or EAN). Booking is what makes the
invoice real. If booking succeeds but the send fails (e.g. Dinero's
email service returns 5xx), you get a **200** with a `send_error`:

```json
{
  "object": "invoice",
  "id": "…",
  "status": "issued",
  "dinero_invoice_guid": "…",
  "send_error": {
    "code": "SEND_FAILED",
    "message": "Dinero email service unavailable."
  }
}
```

**Do not retry issue** — the invoice is already booked. Retry the send
instead (`POST /invoices/{ref}/resend`; slice-forthcoming). This
prevents the classic "retry the failure and double-book" trap.

## Editing after issue [#editing-after-issue]

Once an invoice has a `dinero_invoice_guid`, it is frozen. Attempting to
edit it returns `409 INVOICE_ALREADY_ISSUED`. Raise a **credit note**
instead — full or partial — via `POST /credit-notes`.

## Bulk issuance [#bulk-issuance]

Bulk issuance stays **cron-driven**: `auto_send=true` on a set of
invoices lets Invoia issue them together on the issue date. The API is
single-item only. If you need to issue N invoices, iterate — each call
is idempotent so re-runs are safe.
