Emitida no es enviada: versión de la API 2026-10-01
Las facturas separan la emisión de la entrega. La versión opcional 2026-10-01 publica el estado issued con issued_at, is_sent y sent_via; nuevo POST /v1/invoices/{invoice}/issue; mark-sent registra una entrega manual desde esa versión; nuevos eventos invoice.issued, invoice.marked_sent e invoice.unsent, con invoice.sent como alias deprecado; payloads de webhook versionados por endpoint; las facturas recurrentes ganan generation_mode. La versión predeterminada no cambia.
Hasta ahora la API llamaba «enviar» al acto fiscal de emitir una factura:
draft → sent asignaba el número de serie, congelaba los datos del emisor y del
cliente, daba de alta el registro VeriFactu y descontaba stock, pero no mandaba
ningún correo. Y el envío real por email no dejaba rastro en la factura. Esta
publicación separa los dos hechos. Emitir es un estado; entregar la factura al
cliente es una marca propia, independiente del estado y del cobro.
El vocabulario nuevo vive tras la versión por fecha 2026-10-01. La versión
predeterminada sigue siendo 2026-06-01: una integración que no envía la
cabecera Factuarea-Version y no tiene la clave fijada sigue recibiendo
exactamente el contrato anterior.
Dos ejes: emitida y enviada
Campo (desde 2026-10-01) | Significado |
|---|---|
status: "issued" | La factura está emitida: número definitivo, registro VeriFactu, movimientos de stock. Sustituye a sent como estado emitido. overdue, paid y partially_paid conservan su significado. |
issued_at | Cuándo se emitió la factura. null mientras es un borrador o está programada. |
sent_at | Cuándo se entregó por primera vez al cliente, o null. Un reenvío nunca lo mueve. |
sent_via | Canal de esa primera entrega: email o manual. null mientras no se ha entregado. |
is_sent | true si y solo si sent_at no es null. |
Una factura issued u overdue puede estar enviada o no, y cobrarla no la
marca como enviada. La marca solo se pone de dos formas:
- Email: cuando el servidor de correo acepta un email de entrega de la
factura (
POST /v1/invoices/{invoice}/send,bulk-send, ejecuciones recurrentes y programadas, automatizaciones, la app y el MCP). Un correo en cola o fallido y un recordatorio de pago nunca la ponen. Tampoco se marca un borrador enviado por correo antes de emitirlo. - Manual: con
POST /v1/invoices/{invoice}/mark-senten2026-10-01, para facturas que entregaste por un canal propio (WhatsApp, papel, un portal).
Qué cambia con 2026-10-01
Envía Factuarea-Version: 2026-10-01 en cada petición o fija esa versión en la
API key. Todo objeto factura de cualquier respuesta v1 sigue la versión
efectiva, también dentro de las conversiones de presupuestos, proformas y
albaranes, las ejecuciones de facturas recurrentes, GET /v1/events y las
entregas de webhook que lista
GET /v1/webhook_endpoints/{webhook_endpoint}/deliveries.
| Elemento | Versión predeterminada (2026-06-01) y 2026-09-01 | 2026-10-01 |
|---|---|---|
status de una factura emitida | sent | issued |
sent_at | Instante de emisión | Primera entrega, o null |
issued_at, is_sent, sent_via | No aparecen | Aparecen |
scheduled_action | draft para «emitir sin enviar» | issue |
GET /v1/invoices/statuses | Lista sent (etiqueta «Enviado») | Lista issued, en la misma posición |
by_status en GET /v1/invoices/stats | Clave sent | Clave issued |
POST /v1/invoices/{invoice}/mark-sent | Emite un borrador | Registra una entrega manual |
Dos cambios del lado de la petición son aditivos y se aplican en todas las
versiones: el filtro is_sent de GET /v1/invoices y la nueva operación
issue.
Nuevo: emitir una factura
POST /v1/invoices/{invoice}/issue emite un draft sin enviarlo. Necesita el
scope invoices:write y, como emitir consume un número de serie y no se puede
deshacer, acepta un Idempotency-Key. Cualquier estado distinto de draft
responde 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
}
}El extracto muestra solo los campos de esta publicación. Sin la cabecera, la
misma llamada responde con status: "sent" y sent_at igual al instante de
emisión.
mark-sent depende de la versión
POST /v1/invoices/{invoice}/mark-sent conserva su significado anterior en las
versiones previas: emite un borrador sin enviarlo por correo. Desde
2026-10-01 solo registra una entrega manual: is_sent: true,
sent_via: "manual" y sent_at, sin tocar el estado, el número ni el registro
VeriFactu.
En 2026-10-01 admite facturas issued y overdue y es idempotente: una
factura ya enviada conserva su fecha y su canal originales. Sobre un borrador
responde:
{
"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"
}
}Ramifica según error.subcode. Emite antes la factura con
POST /v1/invoices/{invoice}/issue o envíala por correo con
POST /v1/invoices/{invoice}/send.
Las facturas programadas se emiten con su programación
Cambio de comportamiento en todas las versiones. Solo se puede emitir un
draft. Una factura scheduled ya no se emite por los caminos genéricos:
POST /v1/invoices/{invoice}/mark-sent en versiones anteriores a 2026-10-01
y POST /v1/invoices/{invoice}/issue responden 422
invalid_status_transition, sea cual sea la versión que envíes. Antes de
esta publicación, mark-sent la emitía como si fuera un borrador.
Para emitir una factura programada antes de su fecha, desprográmala primero con
POST /v1/invoices/{invoice}/unschedule y después emítela. Si no, deja que se
ejecute la programación: emite la factura en scheduled_for.
send, unsend y bulk-status
POST /v1/invoices/{invoice}/sendemite un borrador y lo envía por correo, como antes. La respuesta puede mostrar todavíais_sent: false: la marca aparece cuando el servidor de correo acepta el mensaje, junto con el eventoinvoice.marked_sent.POST /v1/invoices/{invoice}/unsendborra la marca de envío (sent_atysent_viavuelven anull) de una facturaissueduoverduey emiteinvoice.unsent. El estado, el número, el registro VeriFactu y el stock no se mueven nunca. Una factura con cobros vigentes responde422, y una segunda llamada no tiene efecto. Cambio observable en las versiones anteriores: en ellassent_atlleva el instante de emisión, así que ya no pasa anulltrasunsend. Leeis_sentcon2026-10-01para saber si la marca está puesta.POST /v1/invoices/bulk-statusaceptanew_status: "issued"para emitir borradores sin enviarlos por correo.sentse sigue aceptando como su alias y nunca marca una factura como entregada.
Alias de entrada en todas las versiones
Tus peticiones actuales siguen funcionando, uses la versión que uses:
| Entrada | Se acepta como |
|---|---|
status=sent en GET /v1/invoices y en POST /v1/invoices/export/excel | status=issued |
new_status: "sent" en POST /v1/invoices/bulk-status | issued |
scheduled_action: "draft" en POST /v1/invoices/{invoice}/schedule | issue |
Un valor fuera del catálogo se sigue rechazando con 422 y la lista de valores
admitidos. scheduled_action acepta ahora issue (emitir sin enviar) o
issue_and_send (emitir y enviar por correo).
Facturas recurrentes: generation_mode
Las facturas recurrentes ganan generation_mode, disponible en todas las
versiones en POST /v1/recurring_invoices,
PUT /v1/recurring_invoices/{recurring_invoice},
POST /v1/invoices/{invoice}/create-recurring y en todas las respuestas de
facturas recurrentes:
generation_mode | Cada ejecución |
|---|---|
draft | Deja la factura en borrador. |
issue | La emite sin enviarla por correo (is_sent: false). Hasta ahora no se podía emitir sin enviar. |
issue_and_send | La emite y la envía por correo a los destinatarios de auto_delivery. Se marca como enviada cuando el servidor de correo acepta el email; si la entrega falla, queda emitida y sin enviar. |
send_automatically se conserva como campo de compatibilidad derivado: true
solo con issue_and_send. Sin generation_mode, send_automatically: true
sigue seleccionando issue_and_send y false selecciona draft; enviar ambos
con valores contradictorios responde 422. Las facturas recurrentes existentes
conservan su comportamiento: las que enviaban sus facturas por correo pasan a
issue_and_send y el resto a draft. Consulta
Facturas recurrentes.
Eventos y webhooks
| Evento | Cuándo |
|---|---|
invoice.issued | Se emite la factura: issue, send o mark-sent sobre un borrador (antes de 2026-10-01), bulk-status, creación ya emitida, ejecuciones programadas o recurrentes. |
invoice.marked_sent | La factura pasa a enviada: email aceptado por el servidor de correo o marca manual. |
invoice.unsent | Se borra la marca de envío con unsend. |
invoice.sent | Alias deprecado de invoice.issued: mismo instante, mismo data.object. |
Un endpoint suscrito a invoice.sent lo sigue recibiendo y se puede seguir
editando con esa suscripción. Suscribe las integraciones nuevas a
invoice.issued; la retirada del alias se anunciará con una fecha Sunset. Las
reglas de automatización ya no aceptan invoice.sent como disparador: crear o
actualizar una regla con él responde 422 automation_trigger_type_invalid
indicando invoice.issued.
Los payloads de webhook se versionan por endpoint con su api_version. Las
versiones de payload admitidas son 2026-05-22 y 2026-10-01:
- Los endpoints que ya existían antes de esta publicación quedaron fijados a
2026-05-22: sus snapshots de factura conservan el vocabulario anterior (status: "sent",sent_atigual al instante de emisión, sinissued_at,is_sentnisent_via). - Un endpoint creado sin
api_versionqueda fijado al crearse: recibe la versión de payload más reciente que no sea posterior a la versión REST efectiva de la petición que lo crea. Sin cabeceraFactuarea-Versionni versión fijada en la clave, o desde la aplicación, esa es la versión por defecto, así que el endpoint queda fijado a2026-05-22. Para recibir el vocabulario nuevo, créalo conFactuarea-Version: 2026-10-01o con"api_version": "2026-10-01". - El
api_versiondel sobre entregado es la versión de esa entrega. El evento guardado no se reescribe nunca: la proyección se hace al entregar.
Cambia la versión de un endpoint con
PUT /v1/webhook_endpoints/{webhook_endpoint} cuando tu receptor entienda el
vocabulario nuevo. Consulta Webhooks.
MCP
El servidor MCP no tiene versiones y siempre habla el contrato más reciente:
- Nueva tool
issue_invoice(invoices:write), el espejo dePOST /v1/invoices/{invoice}/issue. mark_invoice_as_sentregistra ahora una entrega manual. Sobre un borrador devuelveinvoice_cannot_be_marked_as_senty remite aissue_invoiceosend_invoice.search_invoicesaceptaissued(ysentcomo su alias) y el filtrois_sent;bulk_change_invoice_statusyschedule_invoiceaceptan los valores nuevos.create_recurring_invoice,update_recurring_invoiceycreate_recurring_invoice_from_invoiceaceptangeneration_mode.- Toda tool que devuelve una factura usa el vocabulario nuevo.
Si un agente usaba mark_invoice_as_sent para emitir facturas, cámbialo a
issue_invoice.
Cómo adoptarla
- Acepta
issuedallí donde leas elstatusde una factura, y lee el envío deis_sent,sent_atysent_via. - Sustituye la emisión mediante
mark-sentporPOST /v1/invoices/{invoice}/issue, que funciona en todas las versiones. - Envía
Factuarea-Version: 2026-10-01, o fíjala en la clave, y ejecuta tus pruebas contra el sandbox. - Suscribe tus endpoints de webhook a
invoice.issuedy, cuando te convenga, ainvoice.marked_senteinvoice.unsent; después pasa cada endpoint a la versión de payload2026-10-01.
Nuevos endpoints1
| Endpoint | Descripción |
|---|---|
POST/v1/invoices/{invoice}/issue | Emite una factura |