> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.recurrente.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.recurrente.com/_mcp/server.

# Cuentas Conectadas

> Cobra en nombre de otras cuentas de Recurrente

Si estás construyendo una plataforma o un marketplace, y quieres:

* Cobrar en nombre de alguien más, o
* Compartir los ingresos de las ventas con otras cuentas

La funcionalidad de Cuentas Conectadas es para ti.

Con Cuentas Conectadas puedes **realizar cobros en nombre de otras cuentas utilizando tus propias Llaves API**, sin necesidad de acceder ni utilizar las llaves API de esas cuentas.

## Dos formas de conectar cuentas

Puedes trabajar con Cuentas Conectadas de dos formas:

1. Crear y administrar una cuenta conectada nueva desde tu plataforma. Este es el flujo recomendado cuando tu plataforma hace el onboarding del comercio, administra sus datos y configura su cuenta bancaria.
2. Conectar una cuenta de Recurrente existente. Este flujo sirve cuando el comercio ya usa Recurrente y solo quiere autorizar a tu plataforma para cobrar en su nombre.

Ambos caminos terminan con una cuenta hija conectada a tu cuenta. Usa el ID de esa hija en `X-ACCOUNT-ID` para trabajar con sus recursos. Los endpoints que ya reciben `account_id`, como checkouts y transferencias, conservan ese alias.

## Trabajar dentro de una cuenta conectada

Envía tu propia llave de plataforma junto con `X-ACCOUNT-ID`. El request queda limitado a los recursos que pertenecen a esa hija, pero no se filtra por quién los creó:

```bash
curl https://app.recurrente.com/api/checkouts \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -H "X-ACCOUNT-ID: ac_123456"

curl https://app.recurrente.com/api/intents \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -H "X-ACCOUNT-ID: ac_123456"
```

Así, la plataforma puede consultar tanto los checkouts e intents que creó en nombre de la hija como los que la hija creó con sus propias llaves. La hija también ve todos sus propios recursos sin enviar el header. Una plataforma no puede seleccionar cuentas no conectadas ni cuentas conectadas solamente a través de una hija.

## Tipos de cuenta admitidos

Tanto la plataforma como la cuenta existente del destinatario pueden ser personales o comerciales. Conecta una cuenta personal existente con el enlace de invitación de **Configuración → Cuentas conectadas**: su administrador selecciona esa cuenta y confirma la conexión, sin compartir llaves API ni crear una cuenta comercial.

El valor `account_type: individual` de `POST /connected_accounts` corresponde a una cuenta **comercial individual**, no a una cuenta personal. Los tipos de creación de ese endpoint no cambian; para cuentas personales existentes usa la invitación. La verificación, los límites de procesamiento y las restricciones para mover dinero siguen vigentes. Admitir un tipo de cuenta es distinto de aprobar el caso de uso de la plataforma.

## Crear y conectar una cuenta por API

Puedes crear una cuenta conectada administrada por tu plataforma con `POST /api/connected_accounts`. Recurrente crea la cuenta hija, la conecta a tu cuenta, valida los documentos requeridos y marca el onboarding como completado.

Si ya existe una cuenta conectada para el mismo `email`, Recurrente reutiliza esa cuenta y actualiza los datos enviados. El `tax_id` y `tax_name` se extraen automáticamente del RTU enviado en `verification[tax_registration_document]`; no necesitas enviarlos en el request.

## Documentos requeridos

Cada tipo de cuenta requiere distintos archivos en `verification`:

| Tipo         | Documentos                                                                                                                                                           |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `individual` | `tax_registration_document`, `id_card_image`, `id_card_image_back`                                                                                                   |
| `business`   | `tax_registration_document`, `company_patent`, `commercial_patent`, `company_representative_document`, `company_representative_id`, `company_representative_id_back` |
| `non_profit` | `tax_registration_document`, `articles_of_incorporation`, `company_representative_document`, `company_representative_id`, `company_representative_id_back`           |

## Ejemplo: cuenta individual

```bash
curl -X POST https://app.recurrente.com/api/connected_accounts \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -F "email=ana@example.com" \
  -F "full_name=Ana Perez" \
  -F "phone_number=+50255555555" \
  -F "name=Ana Perez" \
  -F "account_type=individual" \
  -F "withdrawals_schedule=daily" \
  -F "verification[tax_registration_document]=@/ruta/ana-rtu.pdf" \
  -F "verification[id_card_image]=@/ruta/ana-dpi-frente.jpg" \
  -F "verification[id_card_image_back]=@/ruta/ana-dpi-reverso.jpg"
```

## Ejemplo: cuenta de empresa

Puedes enviar `bank_account` en el mismo request para configurar la cuenta bancaria externa que recibirá retiros. Usa `GET /api/banks` para ver los valores válidos de `bank_name`.

La cuenta bancaria pasa por las mismas validaciones del formulario de la app. Primero se valida el formato por banco, moneda y tipo; luego se consulta al banco mediante Nexa. Si confirma un nombre válido, ese nombre reemplaza `holder_name`. Si el banco reporta la cuenta como comprometida, el request falla con `400` y `errors.number` sin crear la cuenta conectada.

Si Nexa no responde, el banco no está soportado o se alcanza el límite de 20 consultas por cuenta Recurrente en 24 horas, se guarda el nombre enviado sin confirmar. Si el banco no encuentra la cuenta, enviar `holder_name` también permite guardarla sin confirmar, igual que en el formulario. Sandbox no hace consultas bancarias. Reenviar un destino ya guardado no vuelve a consultarlo.

Al crear una cuenta conectada nueva, la consulta usa el presupuesto de la cuenta padre. La respuesta se conserva durante una hora aunque falle la creación, para reutilizarla en los reintentos. Si la cuenta conectada ya existe, se usa su propio presupuesto.

**Banrural:** `checking` es monetaria y `savings` es ahorro. En GTQ, monetaria admite prefijos `0` o `3` (10 o 14 dígitos), y ahorro admite `0` o `4` (10, 13 o 14 dígitos). Una cuenta que empieza con `4` enviada como `checking` seguirá recibiendo el error de formato antes de consultar Nexa; usa el tipo que corresponda a la cuenta real. `GET /api/banks` lista bancos, no sus reglas de formato.

```bash
curl -X POST https://app.recurrente.com/api/connected_accounts \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -F "email=owner@restaurant.example" \
  -F "full_name=Ana Perez" \
  -F "phone_number=+50255555555" \
  -F "name=Acme Restaurant" \
  -F "account_type=business" \
  -F "withdrawals_schedule=daily" \
  -F "verification[tax_registration_document]=@/ruta/acme-rtu.pdf" \
  -F "verification[company_patent]=@/ruta/patente-sociedad.pdf" \
  -F "verification[commercial_patent]=@/ruta/patente-comercio.pdf" \
  -F "verification[company_representative_document]=@/ruta/representacion-legal.pdf" \
  -F "verification[company_representative_id]=@/ruta/representante-dpi-frente.jpg" \
  -F "verification[company_representative_id_back]=@/ruta/representante-dpi-reverso.jpg" \
  -F "bank_account[holder_name]=Acme Restaurant, S.A." \
  -F "bank_account[number]=1234567890" \
  -F "bank_account[bank_name]=Banco Industrial" \
  -F "bank_account[currency]=GTQ" \
  -F "bank_account[account_type]=checking" \
  -F "bank_account[is_preferred]=true"
```

## Ejemplo: organización sin fines de lucro

```bash
curl -X POST https://app.recurrente.com/api/connected_accounts \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -F "email=admin@fundacion.example" \
  -F "full_name=Luis Garcia" \
  -F "phone_number=+50255555556" \
  -F "name=Fundacion Ejemplo" \
  -F "account_type=non_profit" \
  -F "withdrawals_schedule=weekly" \
  -F "verification[tax_registration_document]=@/ruta/fundacion-rtu.pdf" \
  -F "verification[articles_of_incorporation]=@/ruta/acta-constitutiva.pdf" \
  -F "verification[company_representative_document]=@/ruta/representacion-legal.pdf" \
  -F "verification[company_representative_id]=@/ruta/representante-dpi-frente.jpg" \
  -F "verification[company_representative_id_back]=@/ruta/representante-dpi-reverso.jpg"
```

## Actualizar una cuenta conectada

Puedes actualizar el nombre público y la frecuencia de retiros de una cuenta conectada:

```bash
curl -X PATCH https://app.recurrente.com/api/connected_accounts/ac_123456 \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Restaurant Zona 10",
    "withdrawals_schedule": "weekly"
  }'
```

## Administrar cuentas bancarias

Para agregar otra cuenta bancaria externa a una cuenta conectada:

```bash
curl -X POST https://app.recurrente.com/api/connected_accounts/ac_123456/bank_accounts \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -H "Content-Type: application/json" \
  -d '{
    "holder_name": "Acme Restaurant, S.A.",
    "number": "1234567890",
    "bank_name": "Banco Industrial",
    "currency": "GTQ",
    "account_type": "checking",
    "is_preferred": true
  }'
```

Para cambiar la cuenta bancaria predeterminada, actualiza la cuenta bancaria deseada con `is_preferred: true`:

```bash
curl -X PATCH https://app.recurrente.com/api/connected_accounts/ac_123456/bank_accounts/ba_123456 \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -H "Content-Type: application/json" \
  -d '{ "is_preferred": true }'
```

Para remover una cuenta bancaria, usa `DELETE`. Recurrente la archiva y deja de mostrarla en la API.

## Conectar una cuenta existente

Si el comercio ya tiene una cuenta de Recurrente, no necesitas crear otra cuenta por API. Conecta las dos cuentas desde el UI de Recurrente siguiendo [las instrucciones aquí](https://ayuda.recurrente.com/es/articles/9185861-cuentas-conectadas-como-cobrar-en-nombre-de-otra-cuenta).

## Crear un checkout para una cuenta conectada

Una vez conectadas las cuentas, crea checkouts en nombre de la cuenta hija usando `X-ACCOUNT-ID`. `account_id` en el body sigue funcionando como alias compatible:

```bash
curl -X POST https://app.recurrente.com/api/checkouts \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -H "X-ACCOUNT-ID: ac_123456" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "currency": "GTQ",
        "amount_in_cents": 3000,
        "name": "Producto ejemplo"
      }
    ]
  }'
```

| Parámetro                                            | Descripción                                                |
| ---------------------------------------------------- | ---------------------------------------------------------- |
| `X-ACCOUNT-ID`                                       | El ID de la cuenta hija conectada que va a recibir el pago |
| `account_id`                                         | Alias compatible en el body para `X-ACCOUNT-ID`            |
| `application_fee_amount` / `application_fee_percent` | Opcional. Comisión que la cuenta hija paga a tu plataforma |
| `transfer_setups`                                    | Opcional. Enruta fondos a otras cuentas de Recurrente      |

## Comisión de plataforma (application fee)

Para quedarte con una comisión sobre el cobro de una cuenta conectada, envía `application_fee_amount` (pagos únicos, en centavos) o `application_fee_percent` (suscripciones, porcentaje del total de cada factura, 0–100 con hasta 2 decimales) al crear el checkout a nombre de la cuenta hija:

```json
{
  "items": [
    {
      "currency": "GTQ",
      "amount_in_cents": 3000,
      "name": "Producto ejemplo"
    }
  ],
  "account_id": "ac_123456",
  "application_fee_amount": 100
}
```

Cuando el cobro se completa, Recurrente transfiere la comisión del balance de la cuenta hija al de tu plataforma. En suscripciones la comisión se transfiere en cada cobro exitoso mientras la suscripción esté activa. La comisión puede llegar hasta el monto neto disponible después de fees, FEL e IVA, se puede revertir al reembolsar con `refund_application_fee`, y se incluye en la facturación diaria de comisiones cuando la conexión la tiene habilitada.

El checkout serializa la comisión de vuelta como `application_fee_amount` / `application_fee_percent`, además del detalle completo en `transfer_setups` (la comisión aparece ahí con `purpose: "platform_commission"`).

> **Note**
>
> Antes de existir `application_fee_amount` / `application_fee_percent`, la comisión se declaraba a mano como un elemento de `transfer_setups` con `purpose: "platform_commission"`. Esa forma se sigue aceptando por compatibilidad y se comporta idéntico, pero no se puede combinar con los parámetros nuevos en el mismo checkout.

## Distribución de fondos

Para enrutar fondos a otras cuentas (modelo destino: tu cuenta es el comercio de registro y envías parte del neto a una cuenta conectada), usa `transfer_setups`. Cada elemento define una transferencia que Recurrente ejecuta automáticamente cuando el cobro se completa exitosamente:

* `recipient_id` es el ID de la cuenta de **Recurrente** que recibe los fondos (ej. `ac_789012`) — no es una cuenta bancaria. Los fondos se acreditan al balance de Recurrente de esa cuenta, y de ahí siguen su flujo normal de retiros.
* En **pagos únicos** envía `amount_in_cents`: un monto fijo que se transfiere una sola vez. Puede llegar hasta el monto neto disponible después de fees, FEL e IVA.
* En **suscripciones** envía `amount_percent`: un porcentaje del total de cada factura (0–100, hasta 2 decimales), que se transfiere en cada cobro exitoso mientras la suscripción esté activa. Al crear el checkout validamos que el porcentaje quepa en el monto neto después de fees, FEL e IVA. Si la suscripción se cancela, las transferencias recurrentes se cancelan con ella.

```json
{
  "items": [
    {
      "currency": "GTQ",
      "amount_in_cents": 3000,
      "name": "Producto ejemplo"
    }
  ],
  "transfer_setups": [
    {
      "amount_in_cents": 2500,
      "recipient_id": "ac_789012"
    }
  ]
}
```

## Facturación diaria de comisiones

Puedes pedir que Recurrente emita un DTE diario por moneda para las comisiones de plataforma (application fee) que cada cuenta conectada paga a tu plataforma. Tu plataforma tiene una configuración general (`daily` o `none`) y cada conexión puede reemplazarla. Solo cubre transferencias live completadas después de `enabled_at`; no clasifica ni factura transferencias históricas.

Para habilitarla, usa una API key live. Tu plataforma debe tener INFILE/FEL listo y la cuenta conectada debe tener NIT y nombre fiscal verificados:

```bash
curl -X PUT https://app.recurrente.com/api/connected_accounts/ac_123456/commission_invoicing \
  -H "X-SECRET-KEY: tu_llave_live" \
  -H "Content-Type: application/json" \
  -d '{ "mode": "daily" }'
```

Recurrente procesa días cerrados en `America/Guatemala` de forma asíncrona. Cada documento suma exactamente las comisiones completadas de un día y moneda; no vuelve a mover el principal. Puedes consultar los documentos y reconciliar cada línea con su transferencia:

```bash
curl https://app.recurrente.com/api/connected_accounts/ac_123456/commission_invoices \
  -H "X-SECRET-KEY: tu_llave_live"

curl https://app.recurrente.com/api/connected_accounts/ac_123456/commission_invoices/pci_ab12cd34 \
  -H "X-SECRET-KEY: tu_llave_live"
```

El detalle expone `transfer_setup_id`, `transfer_id`, `source_id`, `source_type` y `completed_at`. Los webhooks `partner_commission_invoice.issued` y `partner_commission_invoice.failed` indican el resultado; `failed` solo se envía cuando ya no corresponde otro reintento automático.

Enviar `{ "mode": "none" }` define un override que cierra el intervalo. Enviar `{ "mode": "default" }` elimina el override y vuelve a heredar la configuración general. Recurrente todavía drena las comisiones completadas antes de `disabled_at`, y conserva todos los documentos y líneas existentes. La plataforma emisora puede seguir consultando ese historial aun después de desconectar la cuenta; la configuración sí requiere una conexión activa.

## La plataforma paga las comisiones del cobro

El equivalente de `defaults.responsibilities.fees_collector = application` de Stripe es `fees_collector: "application"`. Para un checkout live que tu plataforma crea a nombre de una cuenta conectada, Recurrente acredita a la cuenta conectada sin descontarle las comisiones de procesamiento y de Recurrente, y debita esas comisiones del balance de tu plataforma en el mismo momento. La cuenta conectada todavía paga su propia retención y fee de FEL. Aplica solo a cobros en GTQ o USD; en otras monedas la cuenta conectada paga sus comisiones normalmente.

Configura una conexión con una API key live. Tu plataforma necesita NIT y nombre fiscal verificados:

```bash
curl -X PUT https://app.recurrente.com/api/connected_accounts/ac_123456/fee_collection \
  -H "X-SECRET-KEY: tu_llave_live" \
  -H "Content-Type: application/json" \
  -d '{ "fees_collector": "application" }'
```

Usa `recurrente` para que la cuenta conectada pague normalmente, o `default` para eliminar el override e heredar la configuración general de tu plataforma. La responsabilidad queda guardada en cada cobro pagado; cambiarla no modifica cobros anteriores.

Recurrente emite un DTE diario por moneda a tu plataforma con todas las comisiones que asumió ese día, incluso si provienen de varias cuentas conectadas:

```bash
curl https://app.recurrente.com/api/connected_account_fee_invoices \
  -H "X-SECRET-KEY: tu_llave_live"

curl https://app.recurrente.com/api/connected_account_fee_invoices/cafi_ab12cd34 \
  -H "X-SECRET-KEY: tu_llave_live"
```

El detalle incluye `connected_account_id`, `intent_id`, `payment_id`, `processor_fee_in_cents`, `recurrente_fee_in_cents` y `paid_at`. Los webhooks `connected_account_fee_invoice.issued` y `connected_account_fee_invoice.failed` indican el resultado fiscal. Emitir el DTE no vuelve a mover dinero.

Las comisiones de procesamiento y de Recurrente no se devuelven a la plataforma cuando el cobro se reembolsa. El DTE histórico de esas comisiones permanece sin cambios.

## Reembolsar cobros de una cuenta conectada

La plataforma puede reembolsar un payment intent de una cuenta hija con su propia API key. Envía `refund_application_fee: true` si también quieres regresar a la cuenta hija las comisiones de plataforma de ese cobro:

```bash
curl -X POST https://app.recurrente.com/api/refunds \
  -H "X-SECRET-KEY: tu_llave_secreta" \
  -H "X-ACCOUNT-ID: ac_123456" \
  -H "Content-Type: application/json" \
  -d '{
    "payment_intent_id": "pa_ab12cd34",
    "refund_application_fee": true
  }'
```

El valor predeterminado es `false`. El parámetro solo afecta la comisión de plataforma (las transferencias con `purpose: "platform_commission"`, incluidas las creadas con `application_fee_amount` / `application_fee_percent`); las distribuciones de fondos completadas permanecen con sus destinatarios. Tanto la cuenta hija como la plataforma pueden enviarlo, pero la API key de una plataforma debe permitir movimientos de dinero.

Recurrente reserva el balance y revierte las comisiones antes de pedir el reembolso al procesador. La solicitud falla antes de esa llamada si la plataforma ya gastó la comisión o si la cuenta hija no puede cubrir el reembolso completo. Los transfer setups únicos que todavía estén pendientes se cancelan; en suscripciones solo se afecta el fulfillment de la factura reembolsada y la plantilla de los siguientes cobros permanece activa.

Si una comisión ya pertenece a un DTE diario, Recurrente permite el reembolso cuando todas las líneas de ese documento corresponden al mismo pago y anula el DTE después de que el procesador confirma el refund. Si el documento también incluye comisiones de otros pagos, la solicitud falla para no anular su cobertura fiscal. Un error al anular el DTE después del refund se reporta para seguimiento operativo y no deshace el reembolso confirmado.

La respuesta incluye `refund_application_fee` y `transfer_adjustments`. Cada reverso aparece como un nuevo transfer enlazado por `reversal_of_id` y `refund_id`; el transfer original nunca se edita ni se elimina. Si el procesador rechaza el reembolso, Recurrente crea movimientos compensatorios y restaura los transfer setups. Una solicitud concurrente para el mismo reembolso recibe `202` y no llama al procesador dos veces.

Si el resultado del procesador queda indeterminado, el refund permanece `pending` con `failure_reason: "provider_outcome_unknown"`. Recurrente conserva la reserva y los movimientos, no reintenta automáticamente y un POST posterior responde `422` con el `refund_id`; consulta ese refund y contacta a soporte para reconciliarlo antes de intentar otra operación. Esta primera versión solo permite reembolsos completos, y un reembolso exitoso que afectó transfer setups no se puede anular posteriormente.

## Webhooks

Cuando una cuenta hija se conecta a tu cuenta, Recurrente envía un webhook `account_connection.create` a tu cuenta. El payload incluye la conexión y las dos cuentas:

```json
{
  "id": "a_con_123456",
  "event_type": "account_connection.create",
  "status": "active",
  "api_version": "2024-04-24",
  "created_at": "2026-06-17T18:00:00Z",
  "live_mode": true,
  "parent_account": {
    "id": "ac_parent",
    "status": "active",
    "name": "Tu plataforma",
    "account_type": "business",
    "created_at": "2026-06-17T17:00:00Z",
    "creator_name": "Ana Perez",
    "creator_email": "ana@example.com",
    "tax_id": "1234567",
    "tax_name": "Tu Plataforma, S.A.",
    "withdrawals_schedule": "daily",
    "onboarding_completed": true
  },
  "child_account": {
    "id": "ac_child",
    "status": "active",
    "name": "Comercio conectado",
    "account_type": "business",
    "created_at": "2026-06-17T18:00:00Z",
    "creator_name": "Juan Perez",
    "creator_email": "juan@example.com",
    "tax_id": "7654321",
    "tax_name": "Comercio Conectado, S.A.",
    "withdrawals_schedule": "daily",
    "onboarding_completed": true
  }
}
```

Cuando ocurren eventos en una cuenta hija, recibirás webhooks con los parámetros adicionales:

* `connected: true` indica que el evento fue generado por una cuenta conectada
* `account_id: "ac_123456"` es el ID de la cuenta que generó el evento

Con estos campos puedes identificar y procesar eventos de cuentas conectadas por separado.