Versionado
Política de versionado plano /v1 con la cabecera Factuarea-Version. Compromisos de estabilidad y deprecación.
La API de Factuarea sigue una política de URL con versionado plano (/v1)
combinada con una cabecera de fecha opcional para una evolución sin cambios
incompatibles. El compromiso es claro: una vez publicada, /v1 se mantiene
estable. Los cambios incompatibles requieren /v2.
Versión en la URL
https://api.factuarea.com/v1/...v1 es nuestra primera versión pública (mayo de 2026). No hay versiones
anteriores accesibles.
Cuando se diseñe /v2:
/v1y/v2coexisten durante al menos 12 meses.- Las rutas de
/v1no cambian en esa ventana (ni payloads, ni status codes, ni campos, ni semántica). - Avisos por email a los desarrolladores con keys activas, banner en la documentación, cabeceras en las respuestas (ver más abajo).
Cabecera Factuarea-Version
Factuarea-Version: 2026-06-01El date-versioning funciona al estilo de Stripe. Hay un registro de
versiones soportadas (fechas YYYY-MM-DD): 2026-06-01, 2026-09-01 y
2026-10-01. La predeterminada es 2026-06-01, que no es la última. La
versión que aplica a una petición — la versión efectiva — se resuelve en
este orden:
- La cabecera de petición
Factuarea-Version, si la envías. - Si no, la versión fijada en tu API key (se establece al crear la key; null significa que no hay versión fijada).
- Si no, la versión predeterminada,
2026-06-01.
La versión efectiva se devuelve en cada respuesta en la cabecera
Factuarea-Version, así siempre sabes qué versión por fecha sirvió tu
petición.
Factuarea-Version: 2026-06-01Fijar una versión (por cabecera o en la key) congela el comportamiento
del subconjunto de endpoints que reciben mejoras incrementales sin
cambios incompatibles (nuevos campos en la respuesta, nuevos parámetros
opcionales). Sin cabecera ni fijación, obtienes la versión predeterminada,
2026-06-01. Cada fecha más reciente es opcional e incluye los cambios de las
fechas anteriores.
Optar por 2026-09-01 cambia dos cosas, y ninguna más:
Cambio en 2026-09-01 | Qué obtienes en 2026-06-01 |
|---|---|
Las respuestas de borrado masivo usan la forma transversal de éxito parcial {total, successful, failed, failures[{id, error_code, error_message}]}. | La forma anterior {object: "bulk_delete_result", deleted, failed[{id, reason}]}. |
Los errores de los gates de cobro anteriores a la categoría llevan error.type: "payment_required_error": payment_method_required, employee_seat_payment_method_required y employee_seat_charge_failed. seat_charge_failed y gestoria_plan_required se reclasificaron igual; la ventana de rotura única los retiró y los sustituyó por los códigos del NIF adicional additional_nif_charge_failed y additional_nif_plan_required, que llevan payment_required_error en todas las versiones, así que no tienen un type anterior al que volver. | error.type: "invalid_request_error" en los tres que siguen existiendo, exactamente como antes. |
La reclasificación del error no toca error.code, error.subcode ni
el estado HTTP — son 402 con el mismo código en todas las versiones. Si
ramificas por code (que es lo que recomendamos), no cambia nada para ti
en ningún caso. addon_required y los códigos del NIF adicional son
posteriores y llevan siempre payment_required_error.
Vocabulario de facturas en 2026-10-01
2026-10-01 separa la emisión de una factura de su entrega al cliente.
Cambia el contrato de facturas, y nada más:
Cambio en 2026-10-01 | Qué obtienes en 2026-06-01 y 2026-09-01 |
|---|---|
Una factura emitida tiene status: "issued". | status: "sent". |
issued_at lleva el instante de emisión; sent_at, la primera entrega al cliente, o null. | Sin issued_at; sent_at lleva el instante de emisión. |
is_sent y sent_via (email o manual) describen la entrega. | No aparecen. |
scheduled_action usa issue para «emitir sin enviar». | draft, su nombre anterior. |
GET /v1/companies/{company}/invoices/statuses lista issued, y by_status en GET /v1/companies/{company}/invoices/stats usa la clave issued. | sent en la misma posición y como clave. |
POST /v1/companies/{company}/invoices/{invoice}/mark-sent registra una entrega manual y rechaza un borrador con 422 invoice_cannot_be_marked_as_sent. | Emite un borrador sin enviarlo por correo. |
La versión se aplica a todo objeto factura de cualquier respuesta, incluidas
las conversiones, las ejecuciones de facturas recurrentes, GET /v1/companies/{company}/events y
las entregas de webhook listadas. Algunas partes están disponibles en todas
las versiones porque son aditivas o alias de entrada:
POST /v1/companies/{company}/invoices/{invoice}/issue, el filtro is_sent, generation_mode en
las facturas recurrentes, y status=sent, new_status: "sent" y
scheduled_action: "draft" como alias de issued e issue. Consulta la
publicación de Novedades.
Versiones de payload de los webhooks
Las entregas de webhook siguen el api_version de cada endpoint, no la
cabecera de la petición. Las versiones de payload admitidas son 2026-05-22, 2026-10-01 y
2026-10-05. Los endpoints que existían antes de esa versión quedaron fijados
a 2026-05-22 y reciben los snapshots de factura con el vocabulario anterior.
Un endpoint creado sin api_version queda fijado al crearse: sin cabecera ni
versión fijada en la clave, o desde la aplicación, se queda en 2026-05-22; si
la petición usa la versión REST 2026-10-01, toma la versión de payload más
reciente (2026-10-05). Para recibir el vocabulario nuevo, créalo con
Factuarea-Version: 2026-10-01 o con "api_version": "2026-10-01". Consulta
Webhooks.
Errores
La cabecera se valida contra el registro:
- Valor mal formado (que no sea
YYYY-MM-DD, p. ej.2026-05o15/05/2026) →400 parameter_invalid_formatconparam: "Factuarea-Version". - Bien formado pero no soportado (una fecha válida que no está en el
registro) →
400 unsupported_api_versionconparam: "Factuarea-Version".
Omitir la cabecera nunca es un error — cae a la fijación de la key o a la última versión.
¿Qué es un cambio incompatible?
Consideramos incompatible (prohibido en /v1):
- Renombrar / eliminar campos de la respuesta JSON.
- Cambiar el tipo de un campo (
string→int). - Cambiar el
type/codede un envoltorio de error existente. - Cambiar status codes (p. ej. devolver
201donde antes era200). - Convertir en obligatorio un campo de la petición que antes era opcional.
- Cambiar el formato de un identificador (UUID v7 sigue siendo UUID v7).
- Eliminar un endpoint sin un reemplazo documentado y una ventana de migración.
- Cambiar la semántica de la máquina de estados de los documentos.
Consideramos no incompatible (permitido sin una nueva versión):
- Añadir campos nuevos en las respuestas.
- Añadir parámetros opcionales en las peticiones.
- Añadir endpoints nuevos.
- Relajar restricciones (subir un límite, aceptar más formatos).
- Añadir valores de enum nuevos a campos que no sean críticos para las máquinas de estados del lado del cliente.
- Mejorar los mensajes de error (cambia
message, notype/code). - Reclasificar el
typede un envelope de error existente detrás de una versión por fecha: las keys fijadas a una fecha anterior siguen recibiendo eltypeprevio tal cual, ycode/subcode/estado no se mueven. Así se recategorizaron los errores de cobro en2026-09-01. Hacerlo sin versión por fecha es el caso incompatible que aparece arriba. - Renombrar un valor o cambiar el significado de un campo detrás de una
versión por fecha, como hace
2026-10-01con el estado de las facturas: las fechas anteriores conservan el contrato previo y los alias de entrada mantienen funcionando las peticiones existentes.
Política de deprecación
Cuando un endpoint o campo se marca como deprecado dentro de /v1 (p. ej. un
alias heredado reemplazado por una versión canónica):
- Aviso por email a los desarrolladores con keys activas afectadas.
- Banner en
docs.factuarea.comcon el changelog. - Cabeceras en cada respuesta del endpoint deprecado durante al menos
12 meses antes de su retirada (que solo ocurre en
/v2):
Deprecation: true
Sunset: Wed, 15 May 2027 00:00:00 GMT
Link: <https://docs.factuarea.com/changelog#v1-deprecations>; rel="deprecation"
Link: <https://docs.factuarea.com/guides/migration-from-holded>; rel="alternate"- En
/v1el endpoint sigue funcionando hasta el lanzamiento de/v2. Las cabeceras avisan. - En
/v2el endpoint se retira / reemplaza. La ventana entre el primer aviso y/v2es ≥ 12 meses.
Migración entre versiones
Cada migración (v1 → v2) viene acompañada de:
- Una guía dedicada en
docs.factuarea.com/guides/migration-v1-v2. - Mapeo campo a campo y endpoint a endpoint.
- Recomendaciones operativas (mantener ambas keys, escritura dual durante la transición).
- Webhooks: los eventos antiguos conservan su forma; los eventos nuevos viven en su propia versión declarada en el payload.
Changelog
Cada cambio de /v1 (campo nuevo, deprecación, evento nuevo, corrección de
validación) se publica en Changelog con etiquetas:
feature— campo / endpoint / evento nuevo.fix— corrección de un bug.deprecation— campo o endpoint marcado como obsoleto (todavía activo en/v1).breaking— solo aparece en/v2, nunca dentro de/v1.security— corrección con implicaciones de seguridad. Léela primero.
Suscríbete al feed RSS en https://docs.factuarea.com/changelog.rss
o sigue @factuarea en X para los anuncios.
Compromiso de estabilidad
Una integración construida hoy contra /v1 seguirá funcionando en /v1
durante al menos 24 meses desde hoy, sin tocar tu código.
Ventana de soporte para v1 → mínimo 12 meses tras el lanzamiento de v2.
Esa es la garantía. Cualquier excepción se comunicará con plazos generosos.