# Facturar cuando cobras con tu propia pasarela

Facturar con UTILIA OS cuando cobras con tu propia pasarela: factura simplificada ya cobrada, devolución en tu pasarela y rectificativa.

Si tu aplicación cobra con su propia cuenta de Stripe (o con otra
pasarela) y usa UTILIA OS solo para facturar, el recorrido es más corto:
no hacen falta tarjetas guardadas, autorizaciones ni el aplicativo Pagos
con tarjeta. Basta con **Finanzas**.

**Venta cobrada fuera y devolución posterior**

1. **Cobras en tu pasarela** (Tu pasarela): El cliente paga 39,99 € y obtienes el identificador del cobro (pi\_...).
2. [**Emites la factura ya cobrada**](https://os.utilia.ai/docs/developers/api/invoices#una-factura-que-ya-cobraste-con-tu-pasarela) (POST /invoices): Simplificada, con el precio cerrado y el bloque payment.
3. **Devuelves el dinero en tu pasarela** (Tu pasarela): Obtienes el identificador de la devolución (re\_...).
4. [**Emites la rectificativa**](https://os.utilia.ai/docs/developers/api/invoice-rectifications) (POST /invoices/:id/rectifications): Con la causa y el bloque refund. UTILIA OS decide el código legal.
5. [**Recibes los avisos**](https://os.utilia.ai/docs/developers/webhooks/events) (Tu servidor): INVOICE_CREATED, INVOICE_PAID, INVOICE_RECTIFIED e INVOICE_REFUNDED.

_UTILIA OS documenta lo que tu pasarela ya hizo: nunca mueve tu dinero._

Permisos de la aplicación: `crm:invoices:write` y `crm:invoices:issue`
para emitir, `crm:invoices:send` si UTILIA OS envía los correos, y
`crm:invoices:rectify` para las rectificativas (lo concede un Super
Administrador, con un motivo).

> **Nota: Ventas a consumidores de otros países de la Unión**
>
> Si vendes servicios electrónicos a consumidores de otros Estados miembros
> (o, desde Canarias, Ceuta o Melilla, también a consumidores de la
> península y Baleares), esas ventas pueden tener que llevar el IVA del país
> del consumidor por la ventanilla única del IVA. Esa forma de facturar está
> en «Próximamente».
> Las ventas que cobra una tienda de aplicaciones (App Store, Google Play)
> o cuyas condiciones fija la tienda son de la tienda, no tuyas: no las
> factures como ventas a consumidores.

## 1. Emitir la factura ya cobrada

Para una venta a un consumidor de hasta 400 €, emite una **simplificada**
con el precio que cobraste (`pricesIncludeTax: true`) y el bloque
`payment`. La factura nace cobrada y, si se envía, el cliente recibe un
solo correo con la plantilla de factura pagada.

```typescript
const factura = await sdk.invoices.create({
  type: 'SIMPLIFIED',
  user: { externalId: 'user_01HXYZ', email: 'ana@example.com' },
  taxSystem: 'IGIC',
  pricesIncludeTax: true,
  lines: [{ name: 'Plan Básico mensual', quantity: 1, unitPrice: 39.99, taxType: 'IGIC_7' }],
  payment: { method: 'CARD', reference: 'pi_3QabcDEF' },
  consumerResidence: { region: 'CANARIAS', evidence: 'País de la tarjeta: ES; código postal de facturación: 38' },
  idempotencyKey: 'pedido-4471',
});
// factura.totalAmount: 39.99 (base 37,37 más 2,62 de IGIC)
// factura.paymentRegistered: true
```

Si tu organización está en el régimen del pequeño empresario del IGIC
(REPEP), la línea va con `taxType: 'EXEMPT'` y sin causa: el total es
39,99 € sin cuota y la factura lleva «Exención franquicia fiscal». Los
detalles están en [Facturas](https://os.utilia.ai/docs/developers/api/invoices#régimen-del-pequeño-empresario-del-igic-repep).

Antes de la primera venta real, prueba ese mismo cuerpo con
`POST /external/v1/invoices/validate`, que no numera nada (ver
[Probar la facturación sin emitir facturas](https://os.utilia.ai/docs/developers/api/invoice-testing)).
La emisión puede tardar varios segundos: usa un tiempo de espera de al
menos 30 y, si se corta, repite con la misma clave. Si el cobro no se
pudiera registrar, la factura sigue emitida con `paymentRegistered:
false` y el correo retenido; regístralo con `mark-paid`. Lo que pasó con
el correo lo dice `emailDelivery`.

## 2. Devolver el dinero en tu pasarela

La devolución la haces tú, en tu cuenta. UTILIA OS no puede ni debe
mover ese dinero. Guarda el identificador de la devolución.

## 3. Emitir la rectificativa con la devolución

```typescript
const resultado = await sdk.invoices.rectifications.create(factura.id, {
  userId: 'user_01HXYZ',
  idempotencyKey: 'devolucion-pedido-4471',
  cause: 'REFUND',
  refund: { reference: 're_3QabcDEF' },
});
// resultado.rectification.rectificationCode: 'R5'
// resultado.rectification.totalAmount: -39.99
// resultado.originalInvoice.status: 'RECTIFIED'
// resultado.refund.source: 'EXTERNAL_GATEWAY'
```

Para una devolución parcial, añade `amount` con el importe devuelto,
impuestos incluidos. La clave de idempotencia es obligatoria: si la
respuesta trae `operationStatus: 'review_required'`, repite la misma
llamada con la misma clave para terminarla. Un contracargo se rectifica
igual, con `cause: 'CHARGEBACK'`, **solo si la venta queda sin efecto**.

Antes de pedirla, puedes comprobarla con el mismo cuerpo en
`POST /external/v1/invoices/:id/rectifications/validate`, que no numera
ni registra nada. Si la respuesta es `409 RECTIFICATION_NOT_ALLOWED` con
`retryable: true` (la factura todavía se está emitiendo o su PDF se está
preparando), repítela igual pasados `retryAfterSeconds`. Un correo o un
cobro de la emisión que no salieron no la impiden. Y registra cada
devolución por una sola vía: si tu equipo ya la anotó a mano en la
ficha de la factura con la misma referencia, la API responde
`409 REFUND_REFERENCE_ALREADY_USED`. Ver
[Cuándo se puede rectificar](https://os.utilia.ai/docs/developers/api/invoice-rectifications#cuándo-se-puede-rectificar).

## 4. Recibir los avisos

| Aviso | Cuándo |
| - | - |
| `INVOICE_CREATED` | Se emite la factura. `invoice.type` dice si es `SIMPLIFIED`. |
| `INVOICE_PAID` | Queda cobrada con el bloque `payment`. `payment.source` es `manual`. |
| `INVOICE_RECTIFICATION_CREATED` e `INVOICE_RECTIFIED` | Se crea y se emite la rectificativa. |
| `INVOICE_REFUNDED` | Se registra la devolución, con `refund.source: "EXTERNAL_GATEWAY"`. |

Todos llegan solo a tu aplicación.
