Developers

Issuance and auto-send

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

Issuing an invoice is the act of freezing it, booking it into the accounting platform behind your integration, and (optionally) sending it to the customer. Invoia supports two patterns, and both behave the same way on either platform — see Accounting platforms.

Explicit issuance

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

# 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 the guard is the same one the UI's issue button rides.

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:

// 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:

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)

Issuance in Invoia is two steps: book the invoice into the accounting platform, then send it to the customer (email or EAN). Booking is what makes the invoice real. If booking succeeds but the send fails (the platform's email service returns 5xx, say), you get a 200 with a send_error. On e-conomic the send is part of the booking call and cannot fail on its own, so send_error there is always null — the same shape, one fewer state the platform can reach:

{
  "object": "invoice",
  "id": "…",
  "status": "issued",
  "dinero_invoice_guid": "…",
  "send_error": "The platform's email service is unavailable"
}

Do not retry issue — the invoice is already booked, and a retry returns the same already-issued result. Resending is done from the Invoia workspace; there is no Public API endpoint for it, and on e-conomic there cannot be — a booked document there cannot be sent again through the API at all (Accounting platforms).

Editing after issue

Once an invoice has a dinero_invoice_guid — the frozen wire name for the handle the accounting platform gave it, on either platform — 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 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.