Factuarea APIDevelopers
Contract

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_atWhen the invoice was issued. null while it is a draft or scheduled.
sent_atWhen the invoice was first delivered to the customer, or null. A resend never moves it.
sent_viaChannel of that first delivery: email or manual. null while not delivered.
is_senttrue 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-sent on 2026-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.

ItemDefault version (2026-06-01) and 2026-09-012026-10-01
status of an issued invoicesentissued
sent_atIssuance instantFirst delivery, or null
issued_at, is_sent, sent_viaNot presentPresent
scheduled_actiondraft for "issue without sending"issue
GET /v1/invoices/statusesLists sent (label «Enviado»)Lists issued, same position
by_status in GET /v1/invoices/statsKey sentKey issued
POST /v1/invoices/{invoice}/mark-sentIssues a draftRecords 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}/send issues a draft and emails it, as before. The response can still show is_sent: false: the mark appears when the mail server accepts the message, together with the invoice.marked_sent event.
  • POST /v1/invoices/{invoice}/unsend clears the delivery mark (sent_at and sent_via back to null) of an issued or overdue invoice and emits invoice.unsent. The status, the number, the VeriFactu record and the stock never move. An invoice with payments in force answers 422, and a second call is a no-op. Observable change on earlier versions: there, sent_at carries the issuance instant, so it no longer becomes null after unsend. Read is_sent with 2026-10-01 to know whether the mark is set.
  • POST /v1/invoices/bulk-status takes new_status: "issued" to issue drafts without emailing them. sent is 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:

InputAccepted as
status=sent on GET /v1/invoices and in POST /v1/invoices/export/excelstatus=issued
new_status: "sent" on POST /v1/invoices/bulk-statusissued
scheduled_action: "draft" on POST /v1/invoices/{invoice}/scheduleissue

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_modeEach run
draftLeaves the invoice as a draft.
issueIssues it without emailing it (is_sent: false). Issuing without sending was impossible until now.
issue_and_sendIssues 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

EventWhen
invoice.issuedThe 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_sentThe invoice becomes sent: email accepted by the mail server or manual mark.
invoice.unsentThe delivery mark is cleared with unsend.
invoice.sentDeprecated 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_at equal to the issuance instant, no issued_at, is_sent or sent_via).
  • An endpoint created without api_version is 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 no Factuarea-Version header and no pinned key, or from the app, that is the default version, so the endpoint is pinned to 2026-05-22. To receive the new vocabulary, create it with Factuarea-Version: 2026-10-01 or with "api_version": "2026-10-01".
  • The api_version of 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 of POST /v1/invoices/{invoice}/issue.
  • mark_invoice_as_sent now records a manual delivery. On a draft it returns invoice_cannot_be_marked_as_sent and points to issue_invoice or send_invoice.
  • search_invoices accepts issued (and sent as its alias) and the is_sent filter; bulk_change_invoice_status and schedule_invoice accept the new values.
  • create_recurring_invoice, update_recurring_invoice and create_recurring_invoice_from_invoice accept generation_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

  1. Accept issued wherever you read an invoice status, and read delivery from is_sent, sent_at and sent_via.
  2. Replace issuing through mark-sent with POST /v1/invoices/{invoice}/issue, which works in every version.
  3. Send Factuarea-Version: 2026-10-01, or pin it on the key, and run your tests against the sandbox.
  4. Subscribe your webhook endpoints to invoice.issued and, when ready, invoice.marked_sent and invoice.unsent; then move each endpoint to the 2026-10-01 payload version.

New endpoints1

EndpointDescription
POST/v1/invoices/{invoice}/issueIssue an invoice

Updated endpoints20

EndpointDescription
POST/v1/invoices/{invoice}/mark-sentMark an invoice as sent
POST/v1/invoices/{invoice}/unsendUnsend an invoice
POST/v1/invoices/{invoice}/sendSend invoice by email
GET/v1/invoicesList all invoices
GET/v1/invoices/{invoice}Retrieve an invoice
GET/v1/invoices/statusesList invoice statuses
GET/v1/invoices/statsGet invoice statistics
POST/v1/invoices/{invoice}/scheduleSchedule an invoice
POST/v1/invoices/bulk-statusBulk change invoice status
POST/v1/invoices/export/excelExport invoices to a spreadsheet
POST/v1/invoices/{invoice}/create-recurringCreate a recurring invoice from an invoice
POST/v1/recurring_invoicesCreate a recurring invoice
PUT/v1/recurring_invoices/{recurring_invoice}Update a recurring invoice
GET/v1/recurring_invoices/{recurring_invoice}Retrieve a recurring invoice
GET/v1/recurring_invoicesList all recurring invoices
POST/v1/webhook_endpointsCreate a webhook endpoint
PUT/v1/webhook_endpoints/{webhook_endpoint}Update a webhook endpoint
POST/v1/webhook_endpoints/{webhook_endpoint}/test_eventSend a test event
GET/v1/eventsList all events
GET/v1/events/{event}Retrieve an event

On this page

Need a hand?Contact support