Issued is not sent: API version 2026-10-01
Invoices separate issuing from delivering. Opt-in version 2026-10-01 publishes status issued with issued_at, is_sent and sent_via; new POST /v1/invoices/{invoice}/issue; mark-sent records a manual delivery from that version on; new events invoice.issued, invoice.marked_sent and invoice.unsent, with invoice.sent kept as a deprecated alias; webhook payloads versioned per endpoint; recurring invoices gain generation_mode. The default version does not change.
Until now the API called the fiscal act of issuing an invoice "sending" it:
draft → sent assigned the series number, froze the issuer and customer data,
registered the VeriFactu record and booked the stock, but emailed nobody.
Meanwhile the real email delivery left no trace on the invoice. This release
separates the two facts. Issuing is a status; delivering to the customer is a
mark of its own, independent of the status and of payment.
The new vocabulary lives behind the dated version 2026-10-01. The default
version stays 2026-06-01: an integration that sends no
Factuarea-Version header and has no pinned key keeps receiving exactly the
previous contract.
Two axes: issued and sent
Field (from 2026-10-01) | Meaning |
|---|---|
status: "issued" | The invoice has been issued: definitive number, VeriFactu record, stock movements. It replaces sent as the issued status. overdue, paid and partially_paid keep their meaning. |
issued_at | When the invoice was issued. null while it is a draft or scheduled. |
sent_at | When the invoice was first delivered to the customer, or null. A resend never moves it. |
sent_via | Channel of that first delivery: email or manual. null while not delivered. |
is_sent | true if and only if sent_at is not null. |
An issued or overdue invoice can be sent or not, and paying it does not mark
it as sent. The mark is set in two ways only:
- Email: when the mail server accepts a delivery email of the invoice
(
POST /v1/invoices/{invoice}/send,bulk-send, recurring and scheduled runs, automations, the app and the MCP). A queued or failed email and a payment reminder never set it. A draft emailed before issuing is not marked either. - Manual: with
POST /v1/invoices/{invoice}/mark-senton2026-10-01, for invoices you delivered through your own channel (WhatsApp, paper, a portal).
What changes with 2026-10-01
Send Factuarea-Version: 2026-10-01 on each request or pin that version on the
API key. Every invoice object in any v1 response follows the effective version,
also inside quote, pro-forma and delivery-note conversions, recurring invoice
runs, GET /v1/events and webhook deliveries listed with
GET /v1/webhook_endpoints/{webhook_endpoint}/deliveries.
| Item | Default version (2026-06-01) and 2026-09-01 | 2026-10-01 |
|---|---|---|
status of an issued invoice | sent | issued |
sent_at | Issuance instant | First delivery, or null |
issued_at, is_sent, sent_via | Not present | Present |
scheduled_action | draft for "issue without sending" | issue |
GET /v1/invoices/statuses | Lists sent (label «Enviado») | Lists issued, same position |
by_status in GET /v1/invoices/stats | Key sent | Key issued |
POST /v1/invoices/{invoice}/mark-sent | Issues a draft | Records a manual delivery |
Two request-side changes are additive and apply to every version: the
is_sent filter on GET /v1/invoices and the new issue operation.
New: issue an invoice
POST /v1/invoices/{invoice}/issue issues a draft without sending it. It
needs the invoices:write scope and, because issuing consumes a series number
and cannot be undone, it accepts an Idempotency-Key. Any status other than
draft answers 422 invalid_status_transition.
curl -X POST "https://api.factuarea.com/v1/invoices/$INVOICE_ID/issue" \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Factuarea-Version: 2026-10-01" \
-H "Idempotency-Key: issue-fac-2026-00042"{
"data": {
"number": "FAC-2026-00042",
"status": "issued",
"issued_at": "2026-03-15T11:45:00Z",
"sent_at": null,
"sent_via": null,
"is_sent": false
}
}The excerpt shows only the fields of this release. Without the header the same
call answers with status: "sent" and sent_at equal to the issuance instant.
mark-sent depends on the version
POST /v1/invoices/{invoice}/mark-sent keeps its previous meaning on earlier
versions: it issues a draft without emailing it. From 2026-10-01 it only
records a manual delivery: is_sent: true, sent_via: "manual" and sent_at,
without touching the status, the number or the VeriFactu record.
On 2026-10-01 it accepts issued and overdue invoices and is idempotent: an
invoice already sent keeps its original date and channel. On a draft it answers:
{
"error": {
"type": "invalid_request_error",
"code": "business_rule_violation",
"subcode": "invoice_cannot_be_marked_as_sent",
"message": "La factura FAC-2026-BORRADOR es un borrador y todavía no puede marcarse como enviada: emítela antes.",
"doc_url": "https://docs.factuarea.com/guides/errors#business_rule_violation",
"request_id": "req_5e99aabe287e78db589da44c56"
}
}Branch on error.subcode. Issue the invoice first with
POST /v1/invoices/{invoice}/issue, or email it with
POST /v1/invoices/{invoice}/send.
Scheduled invoices are issued by their schedule
Behavior change in every version. Only a draft can be issued. A
scheduled invoice is no longer issued through the generic paths:
POST /v1/invoices/{invoice}/mark-sent on versions before 2026-10-01 and
POST /v1/invoices/{invoice}/issue answer 422 invalid_status_transition,
whatever version you send. Before this release, mark-sent issued it as if it
were a draft.
To issue a scheduled invoice before its date, unschedule it first with
POST /v1/invoices/{invoice}/unschedule and then issue it. Otherwise, let the
schedule run: it issues the invoice at scheduled_for.
send, unsend and bulk-status
POST /v1/invoices/{invoice}/sendissues a draft and emails it, as before. The response can still showis_sent: false: the mark appears when the mail server accepts the message, together with theinvoice.marked_sentevent.POST /v1/invoices/{invoice}/unsendclears the delivery mark (sent_atandsent_viaback tonull) of anissuedoroverdueinvoice and emitsinvoice.unsent. The status, the number, the VeriFactu record and the stock never move. An invoice with payments in force answers422, and a second call is a no-op. Observable change on earlier versions: there,sent_atcarries the issuance instant, so it no longer becomesnullafterunsend. Readis_sentwith2026-10-01to know whether the mark is set.POST /v1/invoices/bulk-statustakesnew_status: "issued"to issue drafts without emailing them.sentis still accepted as its alias and never marks an invoice as delivered.
Input aliases in every version
Your existing requests keep working whatever version you use:
| Input | Accepted as |
|---|---|
status=sent on GET /v1/invoices and in POST /v1/invoices/export/excel | status=issued |
new_status: "sent" on POST /v1/invoices/bulk-status | issued |
scheduled_action: "draft" on POST /v1/invoices/{invoice}/schedule | issue |
A value outside the catalog is still rejected with 422 and the list of allowed
values. scheduled_action now takes issue (issue without sending) or
issue_and_send (issue and email it).
Recurring invoices: generation_mode
Recurring invoices gain generation_mode, available in every version on
POST /v1/recurring_invoices, PUT /v1/recurring_invoices/{recurring_invoice},
POST /v1/invoices/{invoice}/create-recurring and in every recurring invoice
response:
generation_mode | Each run |
|---|---|
draft | Leaves the invoice as a draft. |
issue | Issues it without emailing it (is_sent: false). Issuing without sending was impossible until now. |
issue_and_send | Issues it and emails it to the auto_delivery recipients. It is marked as sent when the mail server accepts the email; a failed delivery leaves it issued and not sent. |
send_automatically stays as a derived compatibility field: true only with
issue_and_send. Without generation_mode, send_automatically: true still
selects issue_and_send and false selects draft; sending both with
contradictory values answers 422. Existing recurring invoices keep their
behavior: the ones that emailed their invoices are issue_and_send, the rest
draft. See Recurring invoices.
Events and webhooks
| Event | When |
|---|---|
invoice.issued | The invoice is issued: issue, send or mark-sent on a draft (before 2026-10-01), bulk-status, created already issued, scheduled or recurring runs. |
invoice.marked_sent | The invoice becomes sent: email accepted by the mail server or manual mark. |
invoice.unsent | The delivery mark is cleared with unsend. |
invoice.sent | Deprecated alias of invoice.issued: same instant, same data.object. |
An endpoint subscribed to invoice.sent keeps receiving it and can still be
edited with that subscription. Subscribe new integrations to invoice.issued;
the removal of the alias will be announced with a Sunset date. Automation
rules no longer accept invoice.sent as a trigger: creating or updating a rule
with it answers 422 automation_trigger_type_invalid naming
invoice.issued.
Webhook payloads are versioned per endpoint with its api_version. The
supported payload versions are 2026-05-22 and 2026-10-01:
- Endpoints that existed before this release were pinned to
2026-05-22: their invoice snapshots keep the previous vocabulary (status: "sent",sent_atequal to the issuance instant, noissued_at,is_sentorsent_via). - An endpoint created without
api_versionis pinned when it is created: it gets the newest payload version that is not later than the effective REST version of the request that creates it. With noFactuarea-Versionheader and no pinned key, or from the app, that is the default version, so the endpoint is pinned to2026-05-22. To receive the new vocabulary, create it withFactuarea-Version: 2026-10-01or with"api_version": "2026-10-01". - The
api_versionof the delivered envelope is the version of that delivery. The stored event is never rewritten: the projection happens when delivering.
Change the version of an endpoint with
PUT /v1/webhook_endpoints/{webhook_endpoint} once your receiver understands
the new vocabulary. See Webhooks.
MCP
The MCP server has no versions and always speaks the latest contract:
- New tool
issue_invoice(invoices:write), the mirror ofPOST /v1/invoices/{invoice}/issue. mark_invoice_as_sentnow records a manual delivery. On a draft it returnsinvoice_cannot_be_marked_as_sentand points toissue_invoiceorsend_invoice.search_invoicesacceptsissued(andsentas its alias) and theis_sentfilter;bulk_change_invoice_statusandschedule_invoiceaccept the new values.create_recurring_invoice,update_recurring_invoiceandcreate_recurring_invoice_from_invoiceacceptgeneration_mode.- Every tool that returns an invoice uses the new vocabulary.
If an agent used mark_invoice_as_sent to issue invoices, switch it to
issue_invoice.
How to adopt it
- Accept
issuedwherever you read an invoicestatus, and read delivery fromis_sent,sent_atandsent_via. - Replace issuing through
mark-sentwithPOST /v1/invoices/{invoice}/issue, which works in every version. - Send
Factuarea-Version: 2026-10-01, or pin it on the key, and run your tests against the sandbox. - Subscribe your webhook endpoints to
invoice.issuedand, when ready,invoice.marked_sentandinvoice.unsent; then move each endpoint to the2026-10-01payload version.
New endpoints1
| Endpoint | Description |
|---|---|
POST/v1/invoices/{invoice}/issue | Issue an invoice |