Factuarea APIDevelopers

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:

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 — null significa 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 las F1;
  • 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):

# 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étodoCuándo usarloQué ocurre
Cuenta existente (stripe_app)Ya cobras con tu propia cuenta de Stripe y quieres conservarlaInstalas 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 StripeFactuarea 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

  1. En Factuarea, conecta una cuenta de Stripe y elige la opción de cuenta existente.
  2. Stripe te pide instalar la app de Factuarea en la cuenta que elijas y aprobar sus permisos.
  3. De vuelta en Factuarea, la cuenta aparece como cuenta conectada con connection_method: stripe_app y authorization_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:

ValorSignificado
authorizedFactuarea puede llamar a Stripe en nombre de la cuenta
reauthorization_requiredStripe 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
revokedLa 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_status pasa a revoked y se avisa a tus administradores (stripe_app_uninstalled en 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ónFactura emitida
Se captura un NIF válido en el Checkout, o el cliente resuelto ya tiene un NIF en su fichaOrdinaria (F1)
Sin NIF, total del cobro igual o por debajo del umbral y "exigir NIF" desactivadoSimplificada (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 TaxLínea de la factura
rate.percentageel tipo de IVA de la línea (vat_rate), tal cual — nunca se recalcula
taxable_amountla base imponible de la línea (precio unitario = base ÷ cantidad)
taxability_reason zero_rated / product_exempt / customer_exemptlínea exenta al 0 %
taxability_reason reverse_chargelí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:

  1. el concept de la regla de tratamiento que coincidió;
  2. la descripción del PaymentIntent;
  3. el concepto por defecto de la cuenta, default_line_concept;
  4. 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, Payment ni 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.typeCoincide cuandoLímites
metadata_equalsEl cobro tiene la metadata key con ese valuekey de 1 a 40 caracteres, exacta; value de 1 a 500, comparado sin distinguir mayúsculas ni espacios en los extremos
description_containsAlguna descripción del cobro contiene el textovalue de 2 a 255 caracteres, sin distinguir mayúsculas ni acentos
payment_linkEl cobro se pagó con ese Payment Linkvalue 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

outcomeCamposEfecto
invoiceconcept (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_invoicenon_invoice_reason (obligatorio); concept y vat_rate no se admitenEl 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ónEndpointScopeTool MCP
Listar las reglasGET /v1/companies/{company}/connected-accounts/{account}/charge-rulesstripe_autoinvoicing:readlist_stripe_charge_rules
Crear una reglaPOST /v1/companies/{company}/connected-accounts/{account}/charge-rulesstripe_autoinvoicing:writecreate_stripe_charge_rule
Reordenar las reglasPUT /v1/companies/{company}/connected-accounts/{account}/charge-rules/orderstripe_autoinvoicing:writereorder_stripe_charge_rules
Actualizar una reglaPUT /v1/companies/{company}/connected-accounts/{account}/charge-rules/{rule}stripe_autoinvoicing:writeupdate_stripe_charge_rule
Eliminar una reglaDELETE /v1/companies/{company}/connected-accounts/{account}/charge-rules/{rule}stripe_autoinvoicing:writedelete_stripe_charge_rule
Listar los cobros no facturadosGET /v1/companies/{company}/connected-accounts/{account}/non-invoiced-chargesstripe_autoinvoicing:readlist_stripe_non_invoiced_charges
  • Crear responde 201 con la regla, colocada al final de la lista.
  • Actualizar es un PUT completo: vuelve a enviar condition, outcome, concept, vat_rate y non_invoice_reason, y no cambia la position.
  • Reordenar recibe todos los id de 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 responde 422 (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_charge y se suma al refunded_amount del cobro (devoluciones completadas y pendientes), con la fecha de la última en refunded_at. net_amount es lo que se queda el comercio: amount menos refunded_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}.csv con 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ía include_non_invoiced_charges: false para 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ónRectificativa 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_reasonQué 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_acceptSe factura desde invoice.paid, con las líneas reales de la factura de Stripe — consulta Facturas sueltas de Stripe
upcoming, otrosSe ignora con un log informativo
  • Los trials no facturan. Un ciclo cuyo invoice.total es 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: el billing_reason nunca 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_ids de 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 de invoice.paid.
  • Un evento reentregado, o un segundo evento del mismo cobro, produce como máximo una factura.

Valores por defecto de un vistazo

CampoPor defectoEfecto del valor por defecto
enabledfalseAuto-facturación desactivada — no se emite nada hasta que la actives
simplified_threshold_cents40000 (400 €)Los cobros sin NIF de hasta 400 € se convierten en F2
require_niffalseSe permiten facturas simplificadas; el identificador fiscal se ofrece pero no se exige
refunds_enabledtrueUna devolución de Stripe genera una factura rectificativa automática (mientras la auto-facturación está activada)
subscription_autoinvoicing_enabledfalseLos ciclos de suscripción de Stripe no se auto-facturan hasta que lo actives (requiere también enabled)
invoice_notenullLas 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.

En esta página

¿Te echamos una mano?Contactar con soporte