Factuarea API
Conceptos clave

Importes y fechas

Cómo representa la API el dinero (EUR, dos decimales), las fechas (YYYY-MM-DD), los timestamps (ISO-8601) y la zona horaria Europe/Madrid usada para el reinicio de cuotas.

Cada valor monetario, de fecha y de hora de la API pública sigue un pequeño conjunto de convenciones fijas. Son las mismas en todos los recursos, así que en cuanto las gestionas en un sitio tu cliente funciona en todas partes.

Dinero

Los importes siempre van en euros (EUR) — el campo currency está presente en todos los documentos y es "EUR" en v1 (ISO 4217). Todavía no hay soporte multidivisa.

Los importes llevan dos decimales (precisión de céntimos). La representación canónica es un string decimal con exactamente dos decimales, al estilo Stripe:

{ "price": "1234.56" }

Algunos recursos emiten actualmente los importes como números JSON (floats) en lugar de strings decimales — por ejemplo el total, el subtotal o el unit_price de un documento vuelven como 1802.9, 968, 100. Escribe tu parser para que acepte tanto un string como un número en cualquier campo de dinero, y normalízalo a un tipo decimal fijo en tu lado (p. ej. Decimal en Python, un big-decimal o un entero de unidades menores en JS). Nunca guardes el dinero como un float binario en crudo.

Deja que la API calcule los totales

No redondees ni calcules por adelantado. Envía los datos en crudo de cada línea (quantity, unit_price, discount, el *_id del impuesto) y deja que la API derive el subtotal, el IVA, el recargo, la retención y el total general. El servidor es la única fuente de verdad para cada total — si redondeas los importes de línea por tu cuenta antes de enviarlos, tus cifras pueden divergir de lo que almacena la API.

El total de un documento sigue una sola fórmula en toda la API:

total = subtotal + total_vat + total_surcharge − total_retention

Si necesitas previsualizar el desglose antes de crear un documento — para un resumen de pedido, un carrito o para conciliar tus propias cifras — llama a POST /v1/taxes/calculate-totals con las líneas y lee el subtotal, el total_vat, el total_surcharge, el total_retention y el total calculados (importes en EUR), más un desglose por línea en el mismo orden:

{
  "subtotal": 250,
  "total_vat": 52.5,
  "total_surcharge": 0,
  "total_retention": 15,
  "total": 287.5,
  "lines": [
    { "subtotal": 100, "vat_amount": 21, "surcharge_amount": 0, "retention_amount": 0, "total": 121 }
  ]
}

El mismo desglose de impuestos por línea aplica a todos los documentos de venta, no solo a las facturas: presupuestos, proformas y albaranes también aceptan un retention_rate y un surcharge_rate por línea (retención de IRPF y recargo de equivalencia, 0–100), y su cabecera lleva los total_vat, total_surcharge y total_retention agregados. La misma fórmula se cumple en todas partes.

Céntimos en los informes fiscales. Los endpoints fiscales agregados (Modelo 303 / 347 vía /v1/tax_reports/*) devuelven sus importes como céntimos enteros, no como decimales de EUR — p. ej. una base imponible acumulada de 25000 significa 250.00 €. Esto está documentado campo a campo en la spec; trata las cifras de los informes fiscales como unidades menores y divide por 100 solo para mostrarlas.

Fechas

Las fechas de calendario (sin componente horario) usan YYYY-MM-DD — la forma de fecha completa ISO-8601 / RFC 3339. Esto cubre campos como issued_on, due_on, paid_on, valid_until, delivery_date, received_on, start_on y end_on:

{
  "issued_on": "2026-03-15",
  "due_on": "2026-04-14",
  "paid_on": "2026-03-20"
}

Envía las fechas en el mismo formato. Una fecha no tiene hora ni zona horaria — es el día de calendario tal como queda registrado para el documento.

Timestamps

Los campos de instante temporal (metadatos de auditoría y ciclo de vida como created_at, updated_at, signed_at, last_delivery_at) usan strings de fecha-hora ISO-8601 / RFC 3339 completos. La mayoría se emiten en UTC con un sufijo Z:

{ "created_at": "2026-05-15T10:34:21Z" }

Algunos timestamps llevan en su lugar un offset Europe/Madrid explícito (+01:00 en invierno, +02:00 en verano):

{ "created_at": "2026-04-15T10:31:05+02:00" }

Ambas formas son ISO-8601 válidas y denotan el mismo tipo de valor: un instante exacto. Parsea el offset — no asumas que el string siempre está en UTC. Un parser ISO-8601 en condiciones (Instant.parse, datetime.fromisoformat, new Date(...), Carbon::parse) gestiona Z y ±hh:mm de forma idéntica y normaliza al instante absoluto.

Zona horaria para las cuotas

La cuota mensual del rate limit se reinicia el día 1 de cada mes natural a las 00:00 Europe/Madrid (CET/CEST), no en UTC. La cuota por minuto es una ventana deslizante y la cabecera X-RateLimit-Reset es un UNIX timestamp (segundos desde el epoch, independiente de la zona horaria). Consulta Rate limits para la semántica completa de las ventanas.

Siempre que la API necesita una única referencia de calendario civil para un límite de negocio — periodos fiscales, el reinicio de la cuota mensual — esa referencia es Europe/Madrid.

Referencia rápida

ValorFormatoEjemplo
DineroEUR, dos decimales — string decimal (algunos campos emiten un número)"1234.56" / 1802.9
DivisaISO 4217, siempre EUR en v1"EUR"
Importes de informes fiscalesCéntimos enteros (unidades menores)25000 → 250.00 €
FechaYYYY-MM-DD (ISO-8601 fecha completa)"2026-03-15"
TimestampISO-8601 fecha-hora, normalmente UTC Z, a veces ±hh:mm"2026-05-15T10:34:21Z"
Calendario de cuotas / fiscalHora civil Europe/Madriddía 1, 00:00 CET/CEST

En esta página