Auto-facturación con Stripe
Emite facturas automáticamente desde los cobros de Stripe Connect — captura de NIF en el Checkout, umbral de factura simplificada, exigir NIF y qué cobros se derivan a revisión manual.
Cuando conectas Stripe mediante Stripe Connect, Factuarea puede emitir una
factura automáticamente por cada cobro exitoso: el cobro se convierte en una
factura con status: sent, se da de alta en VeriFactu y se le registra un
Payment. El flujo es idempotente de extremo a extremo, así que un webhook
reentregado nunca produce una factura duplicada.
Lo alimentan dos flujos:
- Flujo A — un cobro que paga una factura de Factuarea ya existente (una Checkout Session que Factuarea creó desde un enlace de pago). La factura ya existe; el cobro la marca como pagada.
- Flujo B — un cobro espontáneo sin factura previa (un Payment Link que el comercio creó en su propio Dashboard de Stripe, o cualquier otro cobro de Connect). Factuarea crea la factura a partir del cobro.
La configuración se lee y escribe a través de los endpoints v1 a nivel de empresa:
- Obtener la configuración de auto-facturación
(
stripe_autoinvoicing:read). - Actualizar la configuración de auto-facturación
(
stripe_autoinvoicing:write). - Listar cobros auto-facturados
(
stripe_autoinvoicing:read). - Listar rectificativas auto-facturadas
(
stripe_autoinvoicing:read).
Si gestionas varias tiendas con cuentas de Stripe distintas, cada cuenta tiene su propia serie y su propia configuración — consulta Varias tiendas.
La auto-facturación está limitada por el módulo de integración con Stripe de
tu plan y viene desactivada por defecto — actívala explícitamente con
enabled: true.
Qué expone la API de Stripe. Configuración de auto-facturación a nivel de empresa (una comodidad heredada del modelo de tienda única — la fuente de verdad real es la configuración por cuenta conectada, ver Varias tiendas), cuentas conectadas, cobros auto-facturados, rectificativas y payouts para la conciliación bancaria.
Varias tiendas
Un negocio puede operar varias "tiendas" o líneas (una tienda física + un curso
online) con cuentas de Stripe distintas (Stripe Connect) y querer numeración
de facturas independiente para cada una (TIENDA-2026-…, CURSOS-2026-…).
Factuarea modela cada cuenta de Stripe que conectas como una cuenta conectada:
cada Account Link que completas añade una cuenta — nunca sobrescribe la
anterior — y los cobros de cada cuenta se enrutan a la serie y la configuración
de esa cuenta.
Cada cuenta conectada lleva:
- una serie (
series_id) usada para las facturas auto-creadas a partir de sus cobros —nullsignifica que se usa la serie de facturas por defecto de la empresa. Debe ser una serie de facturas completas (invoice_kind: complete), el propósito que numera lasF1; - su propia configuración de auto-facturación (
autoinvoicing_enabled,simplified_threshold_cents,require_nif,refunds_enabled,subscription_autoinvoicing_enabled) — toda regla fiscal de esta página aplica por cuenta.
Cuando llega un webhook, Factuarea resuelve la cuenta de Stripe (acct_xxx) a su
cuenta conectada y emite la factura en la serie de esa cuenta, con la política
fiscal de esa cuenta — de modo que dos tiendas producen facturas en dos series de
numeración separadas y correctas.
Las cuentas nuevas nacen seguras
Una cuenta recién conectada no hereda la configuración de otra cuenta: nace con los mismos valores por defecto seguros que un alta nueva — auto-facturación desactivada, umbral 400 €, "exigir NIF" desactivado, devoluciones activas, suscripciones desactivadas — y sin serie (cae en la serie por defecto de la empresa hasta que le asignes una). Configúrala explícitamente antes de que emita nada.
Endpoints v1 por cuenta
Gestiona las cuentas bajo el recurso connected-accounts (mismos scopes
stripe_autoinvoicing:read|write; la identidad es el id de la cuenta, un UUID v7):
- Listar cuentas conectadas
(
stripe_autoinvoicing:read). - Obtener una cuenta conectada
(
stripe_autoinvoicing:read). - Actualizar una cuenta conectada
— nombre,
series_id(envíanullpara limpiarla) y la configuración por cuenta (stripe_autoinvoicing:write). - Desconectar una cuenta conectada
(
stripe_autoinvoicing:write).
# Asignar la serie CURSOS y activar la auto-facturación en una tienda
curl -X PATCH https://api.factuarea.com/v1/companies/{company}/connected-accounts/0192f3a4-… \
-H "Authorization: Bearer fact_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0192f3a4-…" \
-d '{
"series_id": "0192aaaa-…",
"autoinvoicing_enabled": true
}'Desconectar una cuenta conserva sus facturas ya emitidas y su histórico; los
webhooks posteriores se registran sin procesar. Referenciar el id de una
cuenta que pertenece a otra empresa devuelve 404 (connected_account_not_found)
— el aislamiento multi-tenant nunca filtra la existencia.
El endpoint a nivel de empresa mientras tienes una tienda
Los endpoints de configuración
a nivel de empresa de arriba siguen válidos mientras tienes exactamente una
cuenta conectada: el GET devuelve la configuración efectiva de esa única cuenta
y el PATCH hace de proxy hacia ella (escribe en la configuración de la cuenta,
nunca una copia duplicada a nivel de empresa).
En cuanto conectas una segunda cuenta, la configuración a nivel de empresa ya
no puede responder a "¿qué cuenta?". Tanto el GET como el PATCH devuelven
entonces 422 (per_account_config_required, mensaje en español) apuntándote a
los endpoints por cuenta — Factuarea nunca escribe en dos sitios, así que no hay
divergencia entre una configuración a nivel de empresa y las cuentas.
Una sola fuente de verdad. La configuración por cuenta es el único lugar
donde viven los ajustes. El endpoint a nivel de empresa es una comodidad que hace
de proxy a la cuenta única; nunca guarda una copia separada, de modo que leer y
escribir siempre coinciden. Con dos o más cuentas, usa connected-accounts/{account}
directamente.
Conectar una cuenta de Stripe que ya tienes
Factuarea ofrece dos formas de conectar Stripe, y eliges entre ellas al conectar una cuenta:
| Método | Cuándo usarlo | Qué ocurre |
|---|---|---|
Cuenta existente (stripe_app) | Ya cobras con tu propia cuenta de Stripe y quieres conservarla | Instalas la Stripe App de Factuarea desde Stripe y la autorizas con OAuth 2.0. No se crea ninguna cuenta nueva y no tienes que mover nada |
Cuenta nueva (account_links) | Todavía no tienes una cuenta de Stripe | Factuarea crea una cuenta Standard y te guía por el alta de Stripe (Account Links) |
Sin una elección explícita el método es account_links, el flujo de siempre. Cada
cuenta conectada informa en connection_method del método con el que se vinculó,
de modo que los dos tipos pueden convivir en una misma empresa.
Instalar la Stripe App
- En Factuarea, conecta una cuenta de Stripe y elige la opción de cuenta existente.
- Stripe te pide instalar la app de Factuarea en la cuenta que elijas y aprobar sus permisos.
- De vuelta en Factuarea, la cuenta aparece como cuenta conectada con
connection_method: stripe_appyauthorization_status: authorized. Como toda cuenta nueva, su auto-facturación está desactivada hasta que la configures.
La app solo pide lo que la integración lee: eventos, cobros, payment intents, sesiones de Checkout, clientes, facturas, payouts, transacciones de saldo y disputas. Su único permiso de escritura es crear sesiones de Checkout, que Factuarea usa para los enlaces de pago de tus facturas.
Estado de autorización y reautorizar
Cada cuenta conectada expone authorization_status:
| Valor | Significado |
|---|---|
authorized | Factuarea puede llamar a Stripe en nombre de la cuenta |
reauthorization_required | Stripe ya no acepta la autorización (revocada o caducada). Los eventos que necesitan la API de Stripe esperan en la bandeja como stripe_authorization_required y se avisa a tus administradores |
revoked | La cuenta se desconectó o la app se desinstaló |
Factuarea renueva el acceso de cada cuenta automáticamente, y una tarea diaria renueva las cuentas sin actividad, de modo que la autorización no caduca solo porque pase un tiempo sin cobros. Los eventos que no necesitan la API de Stripe, como una devolución, se siguen procesando mientras una reautorización está pendiente.
Para reautorizar, repite la conexión con la opción de cuenta existente en la
misma empresa. La cuenta conserva su id, nombre, serie, configuración y reglas,
vuelve a authorized, y puedes reprocesar
los eventos que estaban esperando.
Desinstalar o desconectar
- Desinstalar la app en Stripe desconecta la cuenta en Factuarea: se borran sus
tokens, su
authorization_statuspasa arevokedy se avisa a tus administradores (stripe_app_uninstalleden la bandeja). Las facturas y el histórico se conservan, y los eventos posteriores de esa cuenta se registran sin procesarse. - Desconectar desde Factuarea (Desconectar una cuenta conectada) hace lo mismo por tu parte. La app sigue instalada en Stripe hasta que la desinstales desde tu Dashboard de Stripe.
Una cuenta, una empresa
Una cuenta de Stripe solo puede estar activa en una empresa a la vez:
- Conectar una cuenta que está activa en otra empresa se rechaza con
409(stripe_account_linked_elsewhere). El mensaje no revela qué empresa la tiene y no se guarda nada. - Volver a conectar una cuenta que ya está activa en tu empresa renueva sus
credenciales, su método y su estado de autorización sin duplicarla: conserva su
id, nombre, serie, configuración y reglas. - Cuando una cuenta se desconecta, otra empresa puede conectarla.
- Los webhooks se enrutan a la empresa que tiene la cuenta activa.
Autorizar una cuenta desde una segunda empresa puede invalidar el acceso que
Stripe había emitido a la primera. En ese caso, la cuenta de la primera empresa
pasa a reauthorization_required y se avisa a sus administradores.
Factura ordinaria o simplificada
Una factura española necesita el NIF del destinatario para emitirse como factura ordinaria (F1). Un cobro B2C sin NIF es justo el caso que la normativa resuelve con una factura simplificada (F2). Factuarea decide cuál emitir a partir de los datos que trae el cobro más tu política fiscal:
| Situación | Factura emitida |
|---|---|
| Se captura un NIF válido en el Checkout, o el cliente resuelto ya tiene un NIF en su ficha | Ordinaria (F1) |
| Sin NIF, total del cobro igual o por debajo del umbral y "exigir NIF" desactivado | Simplificada (F2) |
| Sin NIF y (total por encima del umbral o "exigir NIF" activado) | Revisión manual — no se auto-emite ninguna factura |
Un NIF capturado se valida contra el formato español (NIF/NIE/CIF). Un NIF con formato no válido cuenta como sin NIF, así que nunca se emite una F1 con datos basura.
Los cobros derivados a revisión manual no se pierden: quedan registrados en el log de la integración para que emitas la factura a mano. La auto-facturación continúa con el resto — un cobro en revisión nunca hace fallar el webhook. Todos aparecen listados en la bandeja de eventos de integración, que es donde ves qué le pasó a cada uno.
El tope legal absoluto de una factura simplificada es de 3.000 €, garantizado por el propio dominio de facturación: un cobro sin NIF por encima de 3.000 € siempre va a revisión manual, sea cual sea el umbral configurado.
Capturar el NIF en el Checkout
Para que un cliente que sí tiene NIF pueda aportarlo, las Checkout Sessions que
crea Factuarea (Flujo A) activan la recogida del identificador fiscal de
Stripe. El cliente puede introducir su es_cif/eu_vat al pagar, y ese NIF
encamina hacia la F1.
El NIF también se lee de cualquier checkout.session.completed entrante:
- de
customer_details.tax_ids(el campo estándar de Stripe), y - de los campos personalizados de los Payment Links que el comercio construye
en su propio Dashboard de Stripe — Factuarea busca un campo cuya clave parezca
un identificador fiscal (
nif,dni,cif,vat,tax).
Un cobro que llega solo como payment_intent.succeeded (sin Checkout) no trae
ningún NIF capturado, pero aún puede ser una F1 si el cliente se resuelve por
email y ya tiene un NIF en su ficha.
El umbral
simplified_threshold_cents es el importe en céntimos igual o por debajo del
cual un cobro sin NIF se auto-emite como factura simplificada. Su valor por
defecto es 40000 (400 €) y acepta cualquier valor en el rango [0, 300000]
(0–3.000 €).
Un valor por defecto conservador de 400 € es deliberado: el tope de 3.000 € solo es legal en sectores tasados concretos, y Factuarea no conoce tu sector — sube el umbral únicamente si tu actividad lo permite.
curl -X PATCH https://api.factuarea.com/v1/companies/{company}/stripe-autoinvoicing/config \
-H "Authorization: Bearer fact_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0192f3a4-…" \
-d '{
"enabled": true,
"simplified_threshold_cents": 100000,
"require_nif": false
}'Ambos campos fiscales son opcionales: si omites simplified_threshold_cents o
require_nif, se conservan sus valores actuales. Un umbral fuera del rango
devuelve 422 (validation_error).
Facturas simplificadas hasta 3.000 €. El art. 4.2.e del Real Decreto
1619/2012 permite la factura simplificada hasta 3.000 € (IVA incluido) en
determinados servicios, entre ellos la restauración. El umbral por defecto sigue
en 400 € porque Factuarea no conoce tu actividad: sube simplified_threshold_cents
solo después de confirmar con tu asesor que tu actividad está cubierta.
Exigir un NIF
require_nif (por defecto false) tiene dos efectos coherentes:
- En las Checkout Sessions que crea Factuarea, el identificador fiscal se marca
como obligatorio (
if_supported), de modo que se le solicita al cliente. - En la decisión de arriba, veta la F2: un cobro sin NIF va a revisión manual en lugar de convertirse en factura simplificada.
Actívalo cuando tu empresa no quiera nunca facturas simplificadas automáticas: cada cobro pasa entonces a tener NIF (F1) o a esperarte en revisión manual.
Las facturas auto-emitidas son fiscalmente reales e irreversibles (se crea
el registro de Alta de VeriFactu). Valida tu política fiscal primero con una
clave fact_test_: en el sandbox el registro de VeriFactu
se crea localmente y nunca se transmite a la AEAT, así que puedes ejercitar la
decisión F1/F2/revisión sin riesgo antes de pasar a producción.
El evento saliente
Cada factura auto-creada — F1 o F2 — emite el evento
invoice.auto_created y un
evento payment.received. En una factura simplificada el payload lleva
client_id: null (sin destinatario), de modo que un receptor de webhooks puede
distinguir la F1 de la F2.
Desglose real de IVA con Stripe Tax
Si usas Stripe Tax, cada cobro ya trae el desglose fiscal real por línea — el tipo, la base imponible y, cuando aplica, la causa por la que una línea está exenta o sujeta a inversión del sujeto pasivo. Factuarea espeja ese desglose en la factura en lugar de aplanarlo todo a un único tipo por defecto.
El webhook del Checkout no incluye las líneas, así que Factuarea hace una segunda llamada de solo lectura a la API en tu nombre para recuperarlas con sus impuestos, y mapea cada línea:
| Dato de Stripe Tax | Línea de la factura |
|---|---|
rate.percentage | el tipo de IVA de la línea (vat_rate), tal cual — nunca se recalcula |
taxable_amount | la base imponible de la línea (precio unitario = base ÷ cantidad) |
taxability_reason zero_rated / product_exempt / customer_exempt | línea exenta al 0 % |
taxability_reason reverse_charge | línea con inversión del sujeto pasivo (ISP) al 0 % |
Así, un cobro con IVA mixto (p. ej. 21 % de consultoría + 10 % de un libro) se convierte en una factura con dos líneas reales, cada una a su tipo, y el desglose multi-IVA llega hasta el registro de VeriFactu.
El IVA nunca se recalcula — Stripe ya lo calculó, y recalcularlo introduciría desviaciones de céntimos. Factuarea toma el tipo y la base imponible directamente de Stripe Tax.
Cuando no hay Stripe Tax (no lo has activado en tu cuenta de Stripe) no cambia nada: cada línea recurre al IVA por defecto de tu empresa, igual que antes. Una empresa sin IVA por defecto configurado recurre al 0 % — nunca a un 21 % fantasma.
Líneas reales
Cuando un cobro trae varias líneas (varios productos o conceptos), aparecen como líneas reales e independientes en la factura — cada una con su descripción, cantidad y precio — en lugar de colapsarse en una sola. Son líneas libres (no enlazadas a tu catálogo de productos).
Esto es ortogonal al tipo de factura: la decisión F1/F2 de arriba elige el tipo, el mapeo de líneas elige las líneas — tanto una factura ordinaria como una simplificada obtienen las mismas líneas reales.
Un cobro que llega solo como payment_intent.succeeded (sin Checkout Session,
por lo que no hay líneas recuperables), o un cobro cuya recuperación de líneas
falla tras los reintentos, sigue produciendo una factura: recurre a una sola
línea con el IVA por defecto. La factura nunca se pierde por un detalle no
esencial.
Antes de emitir, Factuarea valida el total: el total derivado de las líneas
espejadas (suma de subtotal + IVA por línea, en EUR) debe coincidir con el
importe realmente cobrado, dentro de una pequeña tolerancia de redondeo (±1
céntimo por línea, mínimo ±0,05 €). Si no coincide, el cobro se deriva a
revisión manual (total_mismatch) en lugar de emitir una factura cuyo total
diverja del cobro real — el webhook responde correctamente igualmente.
Concepto de los cobros sin Checkout
Un cobro que llega sin sesión de Checkout no tiene líneas que espejar, así que la factura lleva una sola línea. Su descripción es la primera de estas que exista:
- el
conceptde la regla de tratamiento que coincidió; - la descripción del PaymentIntent;
- el concepto por defecto de la cuenta,
default_line_concept; - el texto genérico,
Cobro Stripe pi_….
El texto se corta a 255 caracteres. Fija el concepto por defecto de una cuenta con
Actualizar una cuenta conectada
(stripe_autoinvoicing:write), de 1 a 255 caracteres; null lo borra:
curl -X PATCH https://api.factuarea.com/v1/companies/{company}/connected-accounts/0192f3a4-… \
-H "Authorization: Bearer fact_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0192f3a4-…" \
-d '{ "default_line_concept": "Reserva online" }'default_line_concept, connection_method y authorization_status forman parte
de cada cuenta conectada en Listar
y Obtener una cuenta conectada.
Nota y vencimiento de las facturas automáticas
Cada factura que Factuarea emite automáticamente desde una cuenta conectada puede llevar una nota que configuras una vez por cuenta, invoice_note: hasta 500 caracteres, sin espacios sobrantes, que se escribe en las notas de cada factura. Por defecto es null y entonces las facturas salen sin nota.
Fíjala con Actualizar una cuenta conectada (stripe_autoinvoicing:write). Si omites invoice_note se queda como está, una cadena vacía o null la quita y un texto la asigna; un texto de más de 500 caracteres devuelve 422 parameter_invalid_value con param invoice_note:
curl -X PATCH https://api.factuarea.com/v1/companies/{company}/connected-accounts/0192f3a4-… \
-H "Authorization: Bearer fact_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0192f3a4-…" \
-d '{ "invoice_note": "Pagado online con tarjeta. Gracias por tu compra." }'Si el cobro fue en otra moneda, la línea con la conversión a EUR y el tipo del BCE se añade a la nota. invoice_note forma parte de cada cuenta conectada en Listar y Obtener una cuenta conectada, y la tool MCP update_stripe_connected_account la acepta.
Las facturas automáticas toman el vencimiento por defecto de cualquier factura: 30 días desde la fecha de emisión.
Envía cada factura a quien paga
Cada cuenta conectada puede además enviar por email cada factura que Factuarea emite automáticamente a la dirección que llega con el cobro de Stripe, es decir, a la persona que pagó: email_invoice_to_payer, false por defecto. Factuarea toma la dirección del Checkout (customer_details.email), de la factura de Stripe de una suscripción (customer_email) o del propio cobro (receipt_email), y envía la factura con la plantilla de tu empresa, su PDF adjunto y sin botón de pago, porque ya está cobrada.
La dirección es solo dónde se entrega la factura: no se guarda en ella. Una factura simplificada sigue siendo simplificada, sin destinatario; cuando el cobro identifica al cliente, la factura completa se emite a su nombre como siempre y se envía también a la dirección del cobro.
Actívala con Actualizar una cuenta conectada (stripe_autoinvoicing:write). Si la omites se queda como está, y un valor que no sea booleano devuelve 422 parameter_invalid_value con param email_invoice_to_payer:
curl -X PATCH https://api.factuarea.com/v1/companies/{company}/connected-accounts/0192f3a4-… \
-H "Authorization: Bearer fact_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0192f3a4-…" \
-d '{ "email_invoice_to_payer": true }'El envío nunca deshace la factura ni el cobro, y nunca hace fallar el webhook. Si un cobro no trae email, o el envío se rechaza, la factura se emite y se cobra igualmente, y el resultado queda en los eventos de la integración: autoinvoice.email_requested, autoinvoice.email_skipped (el cobro no trae un email válido) o autoinvoice.email_failed (el envío se rechazó, por ejemplo porque la identidad de remitente de tu empresa aún no está verificada). La opción forma parte de cada cuenta conectada en Listar y Obtener una cuenta conectada, y la tool MCP update_stripe_connected_account la acepta.
Cobros en otra moneda
Un cobro en una moneda distinta del EUR ya no se descarta. Factuarea lo convierte a EUR usando el tipo de cambio de referencia del Banco Central Europeo (BCE) de la fecha de pago y emite la factura en euros — base, IVA y total, y el registro de VeriFactu/AEAT, todo en EUR (Art. 12.1 RD 1619/2012: la cuota de IVA debe consignarse en euros).
- Un cobro en EUR pasa intacto.
- Un cobro ≠EUR con tipo disponible se convierte; la traza de la conversión — importe y moneda originales, tipo BCE y fecha del tipo — se escribe en las notas de la factura y en el registro de integración para auditoría fiscal.
- Un cobro en una moneda sin tipo BCE disponible no se auto-factura: se
deriva a revisión manual y el webhook responde correctamente igualmente.
Factuarea nunca inventa un tipo. La entrada aparece en la
bandeja como
unsupported_currency, aparcada: en cuanto se publique el tipo oficial de esa fecha, reprocesar el evento emite la factura.
Los tipos del BCE se cachean a diario (sin tabla de base de datos adicional), así que varios cobros ≠EUR del mismo día comparten una sola consulta del tipo.
Emitir la factura en la moneda original (opción B) queda intencionadamente fuera de alcance — Factuarea siempre convierte a EUR (opción A).
Cobros que no se facturan: reglas de tratamiento
No todo cobro es una operación sujeta. Una penalización cobrada en una tarjeta, o la venta de un vale regalo canjeable por cualquier servicio, puede no ser una operación que facturar en el momento del pago. Cada cuenta conectada tiene sus propias reglas de tratamiento, que deciden qué ocurre con un cobro espontáneo, el que no paga una factura que ya tuvieras en Factuarea:
- Facturarlo, opcionalmente con su propio concepto y tipo de IVA.
- No facturarlo, indicando un motivo de una lista cerrada. No se crea factura,
Paymentni registro de VeriFactu; el cobro queda en el listado de cobros no facturados.
Las reglas se evalúan por orden de position y decide la primera que
coincide. Si ninguna coincide, el cobro se factura como se describe en el resto
de esta página.
Condiciones
condition.type | Coincide cuando | Límites |
|---|---|---|
metadata_equals | El cobro tiene la metadata key con ese value | key de 1 a 40 caracteres, exacta; value de 1 a 500, comparado sin distinguir mayúsculas ni espacios en los extremos |
description_contains | Alguna descripción del cobro contiene el texto | value de 2 a 255 caracteres, sin distinguir mayúsculas ni acentos |
payment_link | El cobro se pagó con ese Payment Link | value con la forma plink_… |
La metadata es la del PaymentIntent fusionada con la de la sesión de Checkout o la de la factura de Stripe (gana esta última si una clave se repite). Las descripciones que se comparan son la del PaymentIntent, las de las líneas del Checkout, y las de la factura de Stripe y sus líneas.
Resultados
outcome | Campos | Efecto |
|---|---|---|
invoice | concept (opcional, de 1 a 255 caracteres); vat_rate (opcional, un tipo de IVA de venta existente) | La factura se emite como siempre, con ese concepto y ese IVA. Las líneas que traen desglose de Stripe Tax lo conservan |
do_not_invoice | non_invoice_reason (obligatorio); concept y vat_rate no se admiten | El cobro se registra y no se factura |
Los valores de non_invoice_reason son indemnity_not_subject,
multipurpose_voucher e invoiced_elsewhere (el cobro ya se factura en otro
sistema). Una combinación que incumple estas reglas responde 422
(charge_rule_invalid, con el campo en error.param), y una cuenta admite hasta
50 reglas (charge_rule_limit_reached).
Las reglas nunca se aplican al cobro que paga una factura creada en Factuarea
(el que lleva metadata.factuarea_invoice) ni a los ciclos de suscripción.
Ejemplos y su base normativa
Confirma cada plantilla con tu asesor. Factuarea no decide si un cobro está sujeto a IVA: una regla aplica el tratamiento que configuras, y revisarlo es responsabilidad del obligado tributario. Las referencias siguientes explican el criterio; no son un asesoramiento para tu caso concreto.
Penalización por cancelar o no presentarse, sin anticipo previo. La consulta vinculante de la Dirección General de Tributos (DGT) V0839-20 considera que el cargo en la tarjeta por cancelar fuera de plazo o no presentarse, sin anticipo previo, tiene naturaleza indemnizatoria, por lo que no hay operación sujeta al IVA. Se apoya en el art. 78.Tres.1º LIVA: las indemnizaciones que, por su naturaleza y función, no sean contraprestación de una operación sujeta no forman parte de la base imponible. Si el cliente había pagado un anticipo que retienes, el tratamiento es distinto y se corrige con una rectificativa manual.
{
"condition": { "type": "metadata_equals", "key": "type", "value": "penalty" },
"outcome": "do_not_invoice",
"non_invoice_reason": "indemnity_not_subject"
}Vale univalente. Cuando el servicio y su tipo de IVA se conocen al vender el vale, su venta ya es la operación sujeta y se factura al tipo de ese servicio (Resolución de la DGT de 28-12-2018, BOE-A-2018-18094).
{
"condition": { "type": "description_contains", "value": "vale regalo" },
"outcome": "invoice",
"concept": "Vale regalo",
"vat_rate": 10
}Vale polivalente. Cuando todavía no se conoce el servicio o el tipo, su venta
no está sujeta al IVA y el impuesto se devenga al canjearlo (misma Resolución,
apartado tercero). Los cobros excluidos así conservan su motivo
multipurpose_voucher.
{
"condition": { "type": "payment_link", "value": "plink_1Pabc2DEFghi3JKL" },
"outcome": "do_not_invoice",
"non_invoice_reason": "multipurpose_voucher"
}En la aplicación, estas tres vienen como plantillas, cada una con su base normativa y el recordatorio de confirmarlo con tu asesor.
Gestionar las reglas
Seis operaciones bajo connected-accounts/{account}, con los scopes
stripe_autoinvoicing:read (los listados) y stripe_autoinvoicing:write (el
resto). El id de una regla es un UUID v7, y una regla o una cuenta de otra
empresa responde 404 (charge_rule_not_found, connected_account_not_found).
| Operación | Endpoint | Scope | Tool MCP |
|---|---|---|---|
| Listar las reglas | GET /v1/companies/{company}/connected-accounts/{account}/charge-rules | stripe_autoinvoicing:read | list_stripe_charge_rules |
| Crear una regla | POST /v1/companies/{company}/connected-accounts/{account}/charge-rules | stripe_autoinvoicing:write | create_stripe_charge_rule |
| Reordenar las reglas | PUT /v1/companies/{company}/connected-accounts/{account}/charge-rules/order | stripe_autoinvoicing:write | reorder_stripe_charge_rules |
| Actualizar una regla | PUT /v1/companies/{company}/connected-accounts/{account}/charge-rules/{rule} | stripe_autoinvoicing:write | update_stripe_charge_rule |
| Eliminar una regla | DELETE /v1/companies/{company}/connected-accounts/{account}/charge-rules/{rule} | stripe_autoinvoicing:write | delete_stripe_charge_rule |
| Listar los cobros no facturados | GET /v1/companies/{company}/connected-accounts/{account}/non-invoiced-charges | stripe_autoinvoicing:read | list_stripe_non_invoiced_charges |
- Crear responde
201con la regla, colocada al final de la lista. - Actualizar es un
PUTcompleto: vuelve a enviarcondition,outcome,concept,vat_rateynon_invoice_reason, y no cambia laposition. - Reordenar recibe todos los
idde las reglas de la cuenta en el nuevo orden:{ "rule_ids": ["…", "…"] }. Una lista incompleta, repetida o con un id que no es de la cuenta responde422(charge_rule_invalid) y no cambia nada. - Eliminar responde
204. Los cobros que había excluido conservan su registro.
{
"id": "0192f3a4-7b2c-7c1d-9e8f-1a2b3c4d5e6f",
"object": "charge_rule",
"position": 1,
"condition": { "type": "metadata_equals", "key": "type", "value": "penalty" },
"outcome": "do_not_invoice",
"non_invoice_reason": "indemnity_not_subject",
"concept": null,
"vat_rate": null,
"created_at": "2026-10-07T09:30:00+00:00",
"updated_at": "2026-10-07T09:30:00+00:00"
}Cobros no facturados
Cada cobro que excluye una regla queda registrado una sola vez, sea cual sea el
número de eventos que Stripe envíe por él. El listado se pagina por cursor
(limit de 1 a 100, 25 por defecto, starting_after y ending_before), del más
reciente al más antiguo, y se puede acotar a un periodo con occurred_from y
occurred_to (YYYY-MM-DD, ambos incluidos, según la fecha del cobro):
{
"data": [
{
"id": "0192f3b8-1e4a-7f20-8c3d-5e6f7a8b9c0d",
"object": "non_invoiced_charge",
"connected_account_id": "0192e7c2-4d5e-7f3b-a012-3c4d5e6f7081",
"transaction_id": "pi_3PenaltyAbC",
"amount": 30.0,
"refunded_amount": 10.0,
"net_amount": 20.0,
"currency": "EUR",
"description": "Penalización por no presentarse",
"reason": "indemnity_not_subject",
"charge_rule_id": "0192f3a4-7b2c-7c1d-9e8f-1a2b3c4d5e6f",
"occurred_at": "2026-10-07T20:15:00+00:00",
"refunded_at": "2026-10-08T09:02:00+00:00"
}
],
"has_more": false,
"next_cursor": null
}amount, refunded_amount y net_amount van en unidades mayores de la divisa del cobro (currency), con la escala decimal que Stripe usa para esa divisa (3.000 JPY es 3000, 30,00 EUR es 30). charge_rule_id es null cuando la regla que excluyó el cobro se eliminó
después. La bandeja muestra cada uno
de estos eventos como excluded_by_charge_rule.
- Una devolución de un cobro no facturado no crea rectificativa ni va a
revisión manual: se registra como
refund_of_non_invoiced_chargey se suma alrefunded_amountdel cobro (devoluciones completadas y pendientes), con la fecha de la última enrefunded_at.net_amountes lo que se queda el comercio:amountmenosrefunded_amount. Si una devolución pendiente acaba fallando o se cancela, se vuelve a restar. - En el envío trimestral, el
ZIP
y el email a la gestoría
añaden
cobros_sin_factura_Q{quarter}_{year}.csvcon los cobros del trimestre y las devoluciones hechas en él: cada devolución cuenta en el trimestre en que ocurre, como línea negativa cuando el cobro es de un trimestre anterior. Envíainclude_non_invoiced_charges: falsepara dejar fuera el fichero. - Una disputa de un cobro no facturado no anula ningún cobro.
Devoluciones y facturas rectificativas
Una factura emitida es fiscalmente irreversible — nunca se borra ni se anula
una vez pagada. La única forma legal de deshacerla es una factura rectificativa.
Por eso, cuando Stripe devuelve un cobro que Factuarea facturó, Factuarea cierra
el ciclo fiscal por ti: el webhook charge.refunded genera automáticamente una
factura rectificativa enlazada (con su propio registro R de VeriFactu), sin
rectificar a mano.
Lo controla refunds_enabled (por defecto true). Solo actúa mientras la
auto-facturación está activada — el gating es enabled && refunds_enabled. Una
empresa que nunca activó la auto-facturación no ve ningún cambio.
| Devolución | Rectificativa emitida |
|---|---|
Total (refunded: true) | Una rectificativa total que refleja toda la factura original como líneas negativas |
Parcial (amount_refunded < amount) | Una rectificativa partial con una única línea negativa por el importe devuelto, al tipo impositivo de la línea original |
La rectificativa se emite siempre por diferencias (AEAT TipoRectificativa: I),
porque una devolución es un abono con importes negativos. Lleva el motivo de
corrección devolucion; si la original es una factura simplificada (F2), la
rectificativa se emite como R5 automáticamente.
Cada documento se numera en una serie de su propio propósito: la rectificativa va a la
serie de rectificativas por defecto de la empresa (R-2026-001…; RS para una R5), y
una factura simplificada autofacturada, a la serie de simplificadas por defecto, no a la
serie de la cuenta. Cualquiera de ellas se crea en el momento si la empresa no tiene
ninguna.
La factura original se localiza por dos caminos — por el metadato
factuarea_invoice del cobro (Flujo A) o por el UUID determinista derivado del
payment_intent (Flujo B) — así que las devoluciones de cobros emitidos antes
de que existiera esta función también se rectifican.
La idempotencia es por devolución individual. Stripe reenvía
charge.refunded con el amount_refunded acumulado, pero Factuarea se basa
en el id de cada devolución individual (re_xxx): cada una produce como
máximo una rectificativa. Un evento reentregado, o una segunda devolución
parcial, nunca abonan por duplicado. Una devolución cuya factura original no se
pueda localizar, que no esté en un estado rectificable (sent/paid) o que ya
esté rectificada queda registrada en la
bandeja para revisión manual — nunca hace
fallar el webhook.
Cada rectificativa automática emite el evento
invoice.corrective_auto_created
(que lleva la rectificativa, la factura original, el refund_id de origen y el
provider), y puedes listarlas con
Listar rectificativas auto-facturadas.
Para recibir devoluciones debes habilitar el evento charge.refunded en el
endpoint de webhook de Connect en el Dashboard de Stripe. Como con la
auto-facturación, valida el flujo primero con una clave fact_test_: en el
sandbox el registro R de VeriFactu se crea localmente y
nunca se transmite a la AEAT.
Desactivarlo aparca las devoluciones, no las descarta. Con
refunds_enabled: false, cada devolución queda registrada en la
bandeja como
refund_autoinvoicing_disabled y se conserva, cifrada, 30 días. Dentro de
esa ventana elige una de las dos salidas, nunca las dos: vuelve a poner
refunds_enabled en true y
reprocesa el evento, o emite la
rectificativa a mano. Hacer ambas cosas deja la devolución con dos
rectificativas, cada una numerada en su serie y dada de alta en VeriFactu — la
idempotencia del reproceso solo reconoce las rectificativas emitidas por esa
misma vía automática, así que una hecha a mano no lo frena. Pasados los 30 días
el contenido se purga y emitirla a mano es la única salida que queda.
Ciclos de suscripción
Si cobras con Stripe Billing en tu cuenta conectada — suscripciones recurrentes mensuales o anuales — Factuarea puede emitir una factura automáticamente por cada ciclo cobrado. Cada renovación que cobra Stripe produce su propia factura conforme a VeriFactu, espejando el desglose real (líneas, periodo, impuestos) que Stripe ya calculó, igual que los cobros únicos.
Es un toggle separado, subscription_autoinvoicing_enabled (por defecto
false), por encima del flag general enabled. Ambos deben estar activos para
que un ciclo se facture — activar solo las suscripciones no hace nada mientras la
auto-facturación está globalmente desactivada.
curl -X PATCH https://api.factuarea.com/v1/companies/{company}/stripe-autoinvoicing/config \
-H "Authorization: Bearer fact_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0192f3a4-…" \
-d '{
"enabled": true,
"subscription_autoinvoicing_enabled": true
}'Qué ciclos se facturan
Factuarea factura el ciclo de facturación estándar y deriva el resto a revisión
o lo ignora, según el billing_reason de Stripe:
billing_reason | Qué hace Factuarea |
|---|---|
subscription_create (primer ciclo) | Se factura |
subscription_cycle (cada renovación) | Se factura |
subscription_update, subscription_threshold (prorrateos standalone) | Revisión manual — se registra en el log de la integración, no se auto-factura |
manual, quote_accept | Se factura desde invoice.paid, con las líneas reales de la factura de Stripe — consulta Facturas sueltas de Stripe |
upcoming, otros | Se ignora con un log informativo |
- Los trials no facturan. Un ciclo cuyo
invoice.totales 0 € (un periodo de prueba, o un ciclo cubierto íntegramente por crédito) no emite factura; el primer cobro real tras el trial se factura con normalidad. - Los prorrateos standalone (un upgrade/downgrade cobrado por su cuenta, fuera
del ciclo regular) no se auto-facturan hoy — van a revisión manual para que
decidas. Aparecen en la
bandeja como
subscription_proration_review, que es accionable pero no reprocesable: elbilling_reasonnunca cambia, así que la factura hay que emitirla a mano. El ciclo regular siguiente se factura como siempre. - La decisión F1/F2 es la misma. El NIF del destinatario se lee de los
customer_tax_idsde la invoice (más la ficha del cliente resuelto); con NIF el ciclo es una factura ordinaria (F1), sin él e igual o por debajo del umbral una simplificada (F2), y sin él por encima del umbral (o con "exigir NIF" activado) va a revisión manual — idéntico a las reglas de la sección de decisión. Se aplican el mismo espejo de líneas/IVA de Stripe Tax, la conversión a EUR y la validación de total.
Cada ciclo es su propia factura
Un ciclo de suscripción se convierte en una factura suelta — no crea ni
toca ninguna factura recurrente de Factuarea. Las dos son independientes:
Stripe lleva la cadencia y cada invoice.paid produce una factura.
Evita la doble facturación. Si ya modelas la suscripción del mismo cliente como una factura recurrente manual en Factuarea, activar la auto-facturación de suscripciones para esa suscripción de Stripe producirá dos facturas por periodo — una de tu plantilla recurrente y otra del ciclo de Stripe. Elige una sola fuente por cliente: detén la factura recurrente manual o deja este toggle desactivado para esas suscripciones.
El evento saliente
Una factura de ciclo de suscripción emite un evento distinto,
invoice.subscription_auto_created
(además de payment.received), de modo que un receptor de webhooks puede
distinguir los ciclos de suscripción de los cobros únicos. Un cobro único sigue
emitiendo invoice.auto_created como antes. El listado de cobros auto-facturados
(Listar cobros auto-facturados)
expone el contexto de suscripción (subscription_id, stripe_invoice_id,
period_start, period_end) para los cobros de ciclo (null para cobros únicos),
y un filtro opcional origin (subscription/oneshot).
Ese mismo contexto viaja también en la propia factura, como claves de metadata de sistema por las que puedes filtrar los listados. En Metadata y conciliación tienes la tabla completa —qué claves se escriben siempre y cuáles se omiten cuando no aplican— y dos recetas listas para usar: todas las facturas de una suscripción, y las facturas de un único periodo de facturación.
La idempotencia es por ciclo de facturación. Factuarea se basa en cada id de
invoice de Stripe (in_xxx): un evento reentregado, o un segundo evento del
mismo ciclo, produce como máximo una factura.
Un ciclo que llegó con el toggle apagado todavía se puede facturar — durante 30
días. No se descarta en silencio: queda registrado en la
bandeja como
subscription_autoinvoicing_disabled, con su contenido guardado cifrado. Activa
subscription_autoinvoicing_enabled (y enabled) y
reprocesa el evento dentro de esa
ventana, y se emite la factura real del ciclo — con su número de serie y su
registro VeriFactu, igual que si se hubiera facturado en su momento. Pasados los
30 días el contenido se purga, la fila permanece y la única salida es emitir la
factura a mano. Los ciclos cobrados antes de que tu endpoint de Connect empezara
a enviar invoice.paid nunca llegaron a Factuarea, así que ahí no hay nada que
reprocesar.
Para recibir los ciclos de suscripción debes habilitar el evento
invoice.paid en el endpoint de webhook de Connect en el Dashboard de
Stripe. Como siempre, valida el flujo primero con una clave fact_test_: en el
sandbox el registro de Alta de VeriFactu se crea localmente
y nunca se transmite a la AEAT.
Facturas sueltas de Stripe
Una factura que creas en Stripe a mano (manual) o que sale de un presupuesto
aceptado (quote_accept) se factura desde su evento invoice.paid, con sus
líneas reales, siempre que la cuenta tenga la auto-facturación activada. Si no,
espera en la bandeja como
autoinvoicing_disabled, aparcada, para que puedas reprocesarla.
- El cobro se identifica por el PaymentIntent que pagó la factura (el id de la factura cuando no hay), de modo que la factura de Factuarea es la misma que se habría emitido a partir del propio pago.
- Se aplican las reglas de tratamiento, con la descripción y las líneas de la factura de Stripe.
- La decisión F1/F2, la conversión a EUR y la validación del total son las mismas que en cualquier cobro.
Un cobro, una factura
Un mismo cobro puede llegar a Factuarea por varios eventos. Factuarea reconoce a qué pertenece cada pago, así que nunca produce dos facturas:
- El PaymentIntent de una sesión de Checkout se factura con los datos de la sesión (líneas, NIF, metadata y Payment Link), llegue antes el evento que llegue.
- El PaymentIntent de una factura creada en Stripe o de un ciclo de
suscripción no se factura como cobro espontáneo: queda en la bandeja como
handled_by_stripe_invoice, y su factura sale deinvoice.paid. - Un evento reentregado, o un segundo evento del mismo cobro, produce como máximo una factura.
Valores por defecto de un vistazo
| Campo | Por defecto | Efecto del valor por defecto |
|---|---|---|
enabled | false | Auto-facturación desactivada — no se emite nada hasta que la actives |
simplified_threshold_cents | 40000 (400 €) | Los cobros sin NIF de hasta 400 € se convierten en F2 |
require_nif | false | Se permiten facturas simplificadas; el identificador fiscal se ofrece pero no se exige |
refunds_enabled | true | Una devolución de Stripe genera una factura rectificativa automática (mientras la auto-facturación está activada) |
subscription_autoinvoicing_enabled | false | Los ciclos de suscripción de Stripe no se auto-facturan hasta que lo actives (requiere también enabled) |
invoice_note | null | Las facturas automáticas salen sin nota (solo llevan, si el cobro fue en otra moneda, la conversión a EUR) |
Con estos valores por defecto, el único cambio de comportamiento una vez activada
la auto-facturación es que un cobro sin NIF de hasta 400 € se convierte en factura
simplificada en lugar de esperar en revisión, y una devolución genera su factura
rectificativa automáticamente. Los cobros con NIF se comportan exactamente igual
que antes. Los ciclos de suscripción quedan desactivados hasta que optes por ellos
con subscription_autoinvoicing_enabled.