Factuarea API

Conciliar con la metadata de sistema

Las claves de metadata que Factuarea escribe en las facturas auto-emitidas desde un ciclo de suscripción de Stripe, y cómo usar el filtro de metadata para sacar todas las facturas de una suscripción o de un periodo de facturación.

Todos los documentos de Factuarea llevan un objeto metadata de forma libre en el que puedes escribir lo que necesites. En las facturas que Factuarea emite automáticamente desde un ciclo de suscripción de Stripe, la plataforma escribe además un puñado de claves de sistema que atan la factura al cobro del que nació: qué factura de Stripe, qué suscripción, qué periodo de facturación.

Esas claves son lo que hace posible la conciliación sin mantener tu propia tabla de correspondencias. Llevan escribiéndose desde hace tiempo; esta página es donde quedan documentadas.

Alcance: ciclos de suscripción. Estas claves las escribe el flujo que auto-emite una factura por un ciclo de suscripción cobrado (ver ciclos de suscripción). Los cobros sueltos auto-facturados desde charge.succeeded no las llevan hoy — para esos, correlaciona a través del listado de cobros auto-facturados, que expone los identificadores del lado del cobro.

Las claves de sistema

ClaveQué identificaFormatoPresencia
stripe_invoice_idLa factura de Stripe del ciclo cobradoId de Stripe, in_…Siempre
billing_reasonPor qué Stripe facturó ese cicloEl billing_reason crudo de Stripe — en la práctica subscription_create (primer ciclo) o subscription_cycle (cada renovación), los dos únicos que se auto-facturanSiempre
stripe_subscription_idLa suscripción a la que pertenece el cicloId de Stripe, sub_…Opcional — se omite cuando Stripe no envía id de suscripción
period_startPrimer día del periodo facturadoYYYY-MM-DD, UTCOpcional — se omite cuando falta el timestamp del periodo
period_endFin del periodo facturado, literal del period_end de Stripe — es el límite exclusivo, así que en un ciclo mensual es el primer día del periodo siguiente, no el último día de esteYYYY-MM-DD, UTCOpcional — se omite cuando falta el timestamp del periodo

Las claves opcionales no se materializan como nulas ni vacías: cuando el valor no aplica, la clave no se escribe. Es deliberado — una clave presente con valor vacío parecería una correlación que existe pero está en blanco, y cualquier código que la leyera tendría que distinguir «sin suscripción» de «suscripción desconocida». Comprueba la presencia de la clave, no su valor.

Son claves de sistema. No las escribas a mano. Son la correlación entre una factura de Factuarea y un objeto de Stripe, y las recetas de conciliación de abajo confían en ellas. Escribir tú mismo stripe_invoice_id en una factura que no viene al caso hace que esa factura aparezca en una conciliación a la que no pertenece, y nada lo va a señalar — metadata es de forma libre por diseño. Usa tus propias claves (erp_ref, project_code, …) para tus propias correlaciones.

Las claves se leen allí donde esté la factura: metadata forma parte del recurso de factura, y vuelve como un objeto JSON ({} cuando está vacío).

Filtrar por metadata

Ocho listados v1 aceptan un filtro metadata:

RecursoEndpoint
FacturasGET /v1/invoices
PresupuestosGET /v1/quotes
Facturas proformaGET /v1/proformas
AlbaranesGET /v1/delivery_notes
Facturas de compraGET /v1/purchase_invoices
Facturas recurrentesGET /v1/recurring_invoices
ProductosGET /v1/products
ProveedoresGET /v1/suppliers

La sintaxis es deepObject: metadata[clave]=valor, un parámetro de consulta por par.

  • Los pares se combinan con AND. Dos pares devuelven los documentos que cumplen los dos.
  • Coincidencia exacta en el valor; no hay coincidencia parcial ni por prefijo.
  • Hasta 50 pares por petición; a partir de ahí devuelve parameter_invalid_range.
  • Las claves deben encajar en [A-Za-z0-9_.-] y medir entre 1 y 64 caracteres; cualquier otra cosa devuelve parameter_invalid_enum.
  • El filtro queda fuera del contrato {operator, value} de los filtros de columna, así que no existe la forma metadata[clave][eq]. metadata[clave]=valor es toda la sintaxis.

Deja que curl codifique los corchetes. [ y ] son caracteres de glob para curl y caracteres reservados en una URL. Pasa los pares con -G --data-urlencode, como en las recetas de abajo, y curl los codifica correctamente. Pegar un ?metadata[clave]=valor crudo en un shell es de donde suele salir el «el filtro se está ignorando».

Receta: todas las facturas de una suscripción

La conciliación que necesitas cuando un cliente te pide todas las facturas de su plan, o cuando cierras el año de un suscriptor:

curl -G https://api.factuarea.com/v1/invoices \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  --data-urlencode "metadata[stripe_subscription_id]=sub_1QRstuVWXYZabcde" \
  --data-urlencode "limit=100"
{
  "data": [
    {
      "id": "0192f3a4-7b2c-7c1d-9e8f-1a2b3c4d5e6f",
      "object": "invoice",
      "number": "2026/0184",
      "total": "49.90",
      "currency": "EUR",
      "metadata": {
        "stripe_invoice_id": "in_1QRstuVWXYZabcde",
        "billing_reason": "subscription_cycle",
        "stripe_subscription_id": "sub_1QRstuVWXYZabcde",
        "period_start": "2026-07-01",
        "period_end": "2026-08-01"
      }
    }
  ],
  "has_more": false,
  "next_cursor": null
}

El listado se pagina por cursor como todos los demás: sigue leyendo mientras has_more valga true, devolviendo next_cursor en starting_after. Ver Paginación.

Receta: las facturas de un periodo de facturación

Dos pares, combinados con AND: la suscripción y el primer día del periodo. Es la consulta que responde a «¿se facturó el ciclo de julio?».

curl -G https://api.factuarea.com/v1/invoices \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  --data-urlencode "metadata[stripe_subscription_id]=sub_1QRstuVWXYZabcde" \
  --data-urlencode "metadata[period_start]=2026-07-01"

Como period_start y period_end son fechas exactas en UTC, filtra por el límite del periodo en lugar de por un rango — el valor de la metadata es el día que Stripe reporta para el ciclo, no un mes de calendario local. Para barrer un mes entero de ciclos de todas las suscripciones, quita el par de la suscripción y consulta metadata[period_start] a solas.

Filtra por period_start, no por period_end. period_end es el límite superior exclusivo de Stripe: el ciclo de julio de una suscripción mensual lleva period_start: 2026-07-01 y period_end: 2026-08-01. Consultar metadata[period_end]=2026-07-31 no devuelve nada, y ese resultado vacío se parece exactamente a un ciclo que nunca se facturó.

Un array data vacío para un periodo que esperabas facturado es una señal real, no un fallo del filtro. Es exactamente el caso que explica la bandeja de eventos de integración: ábrela filtrada por provider=stripe y status=skipped y el motivo de descarte tipado te dirá si el ciclo se saltó porque la auto-facturación estaba apagada, porque el ciclo no traía importe, o por otra cosa — y si puedes reprocesarlo.

En esta página