Cuentas Conectadas

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ó:

$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.

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:

TipoDocumentos
individualtax_registration_document, id_card_image, id_card_image_back
businesstax_registration_document, company_patent, commercial_patent, company_representative_document, company_representative_id, company_representative_id_back
non_profittax_registration_document, articles_of_incorporation, company_representative_document, company_representative_id, company_representative_id_back

Ejemplo: cuenta individual

$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.

$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

$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:

$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:

$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:

$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í.

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:

$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ámetroDescripción
X-ACCOUNT-IDEl ID de la cuenta hija conectada que va a recibir el pago
account_idAlias compatible en el body para X-ACCOUNT-ID
transfer_setupsOpcional. Configuración de distribución de fondos entre cuentas

Distribución de fondos

Puedes distribuir los fondos entre cuentas usando 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.
  • Si omites recipient_id, los fondos se transfieren a tu propia cuenta — útil para quedarte con una comisión cuando el checkout se crea a nombre de una cuenta conectada.
  • Usa purpose: "platform_commission" cuando esa transferencia sea una comisión que la cuenta hija paga a tu plataforma. Si omites purpose, Recurrente usa fund_split y no la incluye en facturación de comisiones.
  • 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.
1{
2 "items": [
3 {
4 "currency": "GTQ",
5 "amount_in_cents": 3000,
6 "name": "Producto ejemplo"
7 }
8 ],
9 "account_id": "ac_123456",
10 "transfer_setups": [
11 {
12 "amount_in_cents": 100,
13 "recipient_id": "ac_789012",
14 "purpose": "platform_commission"
15 }
16 ]
17}

Facturación diaria de comisiones

Puedes pedir que Recurrente emita un DTE diario por moneda para las transferencias marcadas como platform_commission 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:

$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:

$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:

$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:

$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 no se devuelven a la plataforma cuando el cobro se reembolsa. El reembolso y las disputas siguen las reglas normales de la cuenta conectada, y el DTE histórico permanece sin cambios.

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:

1{
2 "id": "a_con_123456",
3 "event_type": "account_connection.create",
4 "status": "active",
5 "api_version": "2024-04-24",
6 "created_at": "2026-06-17T18:00:00Z",
7 "live_mode": true,
8 "parent_account": {
9 "id": "ac_parent",
10 "status": "active",
11 "name": "Tu plataforma",
12 "account_type": "business",
13 "created_at": "2026-06-17T17:00:00Z",
14 "creator_name": "Ana Perez",
15 "creator_email": "ana@example.com",
16 "tax_id": "1234567",
17 "tax_name": "Tu Plataforma, S.A.",
18 "withdrawals_schedule": "daily",
19 "onboarding_completed": true
20 },
21 "child_account": {
22 "id": "ac_child",
23 "status": "active",
24 "name": "Comercio conectado",
25 "account_type": "business",
26 "created_at": "2026-06-17T18:00:00Z",
27 "creator_name": "Juan Perez",
28 "creator_email": "juan@example.com",
29 "tax_id": "7654321",
30 "tax_name": "Comercio Conectado, S.A.",
31 "withdrawals_schedule": "daily",
32 "onboarding_completed": true
33 }
34}

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.