---
title: "Crear Beneficiaries"
method: POST
path: "/payouts-beneficiary"
tags: ["Beneficiaries"]
---

# Crear Beneficiaries

`POST /payouts-beneficiary`

## Request

- Base URL: `https://api.trytoku.com`
- URL: `https://api.trytoku.com/payouts-beneficiary`
- Auth: API key in header `x-api-key`

Crea varios Beneficiaries y sus Beneficiary Accounts en una sola solicitud.

Se usa para cargar de una vez el padrón de destinatarios de pago de la Organization. Cada fila se procesa por separado, así que una fila inválida no bota el resto: la respuesta informa por separado las creadas (`beneficiaries_created`, `accounts_created`), las omitidas (`beneficiaries_omitted`, `accounts_omitted`) y las fallidas (`beneficiaries_errors`, `accounts_errors`), cada una con su código estable.

Una fila cuyo `external_id` ya existe se reporta como omisión, no como error, y el registro existente queda intacto: reenviar la misma carga no duplica nada.

Todas las filas de una llamada comparten el `id_beneficiary_batch` que devuelve la respuesta. La creación además dispara, en segundo plano, la verificación bancaria de las cuentas nuevas y la inicialización de sus flujos de aprobación, por lo que las cuentas nacen en `approval_flows_status: INITIALIZING` y su verificación queda pendiente.

**Límite de tasa:** 1000 solicitudes por hora. Al superarlo, la API responde `429`. Ver [Límites de tasa](/reference/limites-de-tasa).

## Headers

- `x-user-email` string, nullable: Correo del usuario autenticado que crea el Beneficiary, reenviado por la webapp. Opcional: las integraciones por API key no lo envían.

## Request body

- BeneficiariesRequest
  - `beneficiaries` object[], required: Filas de Beneficiaries que se quieren crear. Cada una lleva sus datos de identidad y, opcionalmente, la lista `accounts` con sus Beneficiary Accounts.

## Response `201`

Resumen de la carga: filas creadas, omitidas y fallidas, con el id del lote.

- CreateBeneficiariesResponse: Resultado de una carga masiva de Beneficiaries, fila por fila.
  - `accounts_created` union[]
    - union
      - BeneficiaryAccount
        - `_id` string
        - `approval_flows_status` 'INITIALIZING' | 'APPROVED' | 'REJECTED' | 'PENDING' | 'SKIPPED': Aggregated approval status for a ``BeneficiaryAccount``. ``INITIALIZING`` is a transient state set at creation time. Downstream consumers must treat ``INITIALIZING`` as blocking (same gating as ``PENDING``/``REJECTED``).
        - `beneficiary` union, required
          - object
            - `collection` string, required
            - `id` string, required
          - object
        - `beneficiary_name` string, required
        - `country_code` 'CL' | 'MX' | 'BR', required: País, en código [ISO 3166-1 alfa-2](https://es.wikipedia.org/wiki/ISO_3166-1_alfa-2). Se limita a los países donde Toku opera: `CL` (Chile), `MX` (México) y `BR` (Brasil). El país determina qué medios de pago y qué productos de cobro están disponibles.
        - `created_at` string, nullable
        - `currency_code` 'CLP' | 'CLF' | 'MXN' | 'BRL' | 'USD', required: Moneda, en código [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html). Cubre las monedas de los países donde Toku opera —`CLP` (peso chileno), `MXN` (peso mexicano) y `BRL` (real)— más `USD` y `CLF`, la Unidad de Fomento chilena. La moneda determina cuántos decimales admiten los montos: `CLP` no admite decimales, `MXN`, `BRL` y `USD` admiten dos, y `CLF` cuatro.
        - `deleted_at` string, nullable
        - `details` BeneficiaryAccountDetails, required: Where the money goes. A ``CASH_ACCOUNT`` pays the beneficiary in cash, so it has no bank account behind it and carries neither ``bank_code`` nor ``account_number``; every other type carries both. ``BeneficiaryAccountDetailsIn`` enforces that at creation.
          - `account_number` string, nullable
          - `bank_code` string, nullable
          - `tokenized_account_number` string, nullable
          - `type` 'BANK_ACCOUNT' | 'CASH_ACCOUNT' | 'DEBIT_CARD' | 'CIE_AGREEMENT' | 'INTERNATIONAL_ACCOUNT' | 'BBVA_ACCOUNT' | 'CHECKING_ACCOUNT' | 'VISTA_ACCOUNT' | 'SAVINGS_ACCOUNT', required: Tipo de la cuenta de destino de un Beneficiary Account. Qué valores se aceptan depende del país de la cuenta: en Chile, `CHECKING_ACCOUNT` (cuenta corriente), `VISTA_ACCOUNT` (cuenta vista) y `SAVINGS_ACCOUNT` (cuenta de ahorro); en México, `BANK_ACCOUNT`, cuyo número de cuenta es una CLABE de 18 dígitos; `CIE_AGREEMENT`, un convenio CIE de BBVA de 7 dígitos; `INTERNATIONAL_ACCOUNT`, una cuenta internacional de 20 a 30 dígitos cuyo `bank_code` es el código ABA del banco, de 9 a 11 dígitos; `BBVA_ACCOUNT`, una cuenta BBVA de 10 u 11 dígitos; y `CASH_ACCOUNT` (cuenta de efectivo), que paga al beneficiario en efectivo y por eso no tiene cuenta bancaria de destino. `DEBIT_CARD` quedó como valor heredado y hoy se rechaza en los dos países.
        - `external_id` string, required
        - `gateway_references` object: Identifier this account already holds on each payout gateway, keyed by gateway name (the OXXO Pay customer of a cash account is the first one). A reference here is what freezes the beneficiary's email: the gateway keeps the email its customer was created with. The key is a plain string rather than an enum because this service is deliberately gateway-agnostic, and an enum would leave an account written by a gateway it does not know yet unreadable for every consumer, not only for cashout.
        - `id_beneficiary` string, uuid, required
        - `id_beneficiary_account` string, uuid
        - `organization_id` string, required
        - `supporting_documents` SupportingDocument[]
          - `content_type` string, nullable
          - `filename` string, required
          - `gs_path` string, required
          - `uploaded_at` string, date-time
        - `updated_at` string, nullable
        - `verification` BeneficiaryAccountVerification
          - `invalid_reason` string, nullable
          - `received_at` string, nullable
          - `requested_at` string, nullable
          - `status` 'PROCESSING' | 'VALIDATED' | 'INVALID' | 'PENDING_VERIFICATION': Estado de la verificación bancaria de un Beneficiary Account. La cuenta nace en `PENDING_VERIFICATION`, queda en `PROCESSING` mientras se espera el resultado, y termina en `VALIDATED`, que la habilita para recibir pagos, o en `INVALID`, que la deja rechazada. Editar los datos bancarios la devuelve a `PENDING_VERIFICATION` y reinicia el ciclo. La verificación automática hoy corre solo en México; en Chile la cuenta se queda en `PENDING_VERIFICATION` hasta que un operador la aprueba o rechaza.
          - `status_log` VerificationStatusLog[]
            - `from_status` 'PROCESSING' | 'VALIDATED' | 'INVALID' | 'PENDING_VERIFICATION', required: Estado de la verificación bancaria de un Beneficiary Account. La cuenta nace en `PENDING_VERIFICATION`, queda en `PROCESSING` mientras se espera el resultado, y termina en `VALIDATED`, que la habilita para recibir pagos, o en `INVALID`, que la deja rechazada. Editar los datos bancarios la devuelve a `PENDING_VERIFICATION` y reinicia el ciclo. La verificación automática hoy corre solo en México; en Chile la cuenta se queda en `PENDING_VERIFICATION` hasta que un operador la aprueba o rechaza.
            - `operator_email` string, nullable: Email of the operator who triggered a manual status override; null for automatic transitions.
            - `source` 'AUTOMATIC_VCC' | 'MANUAL_OVERRIDE' | 'MANUAL_RETRY' | 'VERIFICATION_SKIPPED' | 'NO_BANK_ACCOUNT_TO_VERIFY' | 'API': Qué originó un cambio de estado de la verificación. Queda registrado en cada entrada de `VerificationStatusLog`, de modo que toda cuenta `VALIDATED` es atribuible: `AUTOMATIC_VCC` es que la verificación de titularidad la aprobó, `MANUAL_OVERRIDE` que la aprobó un operador, `MANUAL_RETRY` que un operador pidió volver a correr la verificación sobre una cuenta rechazada —la cuenta vuelve a `PENDING_VERIFICATION`, no queda aprobada—, `VERIFICATION_SKIPPED` que la Organization está configurada para omitir la verificación —es decir, que nadie revisó la cuenta—, `NO_BANK_ACCOUNT_TO_VERIFY` que no había nada que revisar, porque la cuenta no tiene cuenta bancaria de destino, como la cuenta de efectivo, y `API` que la Organization cambió el estado desde su integración, sin un operador de Toku. `VERIFICATION_SKIPPED` y `NO_BANK_ACCOUNT_TO_VERIFY` se distinguen a propósito: una Organization que renunció a un control que sí le aplicaba no es el mismo hecho, para una auditoría, que una cuenta a la que ese control nunca le aplicó. Las entradas escritas antes de que existiera este campo no traen valor.
            - `timestamp` string, date-time
            - `to_status` 'PROCESSING' | 'VALIDATED' | 'INVALID' | 'PENDING_VERIFICATION', required: Estado de la verificación bancaria de un Beneficiary Account. La cuenta nace en `PENDING_VERIFICATION`, queda en `PROCESSING` mientras se espera el resultado, y termina en `VALIDATED`, que la habilita para recibir pagos, o en `INVALID`, que la deja rechazada. Editar los datos bancarios la devuelve a `PENDING_VERIFICATION` y reinicia el ciclo. La verificación automática hoy corre solo en México; en Chile la cuenta se queda en `PENDING_VERIFICATION` hasta que un operador la aprueba o rechaza.
          - `vcc_fetch_results_identity` VccFetchResultsIdentity: VCC fetch-results snapshot (voucher_information + customer_data_validation scores).
            - `account_holder_name` string, nullable: From VCC voucher_information.receiver_name.
            - `account_holder_rfc` string, nullable: From VCC voucher_information.curp.
            - `receiver_name_match_score` integer, nullable: From VCC customer_data_validation.receiver_name_match_score.
            - `rfc_match_score` integer, nullable: From VCC customer_data_validation.rfc_match_score.
          - `verification_id` integer, nullable
          - `verification_request_id` integer, nullable
          - `voucher_url` PayoutsBeneficiaryServiceVoucherURL: VCC voucher URLs cached on the account once verification completes (DB-layer type).
            - `pdf` string, required
            - `xml` string, required
      - BeneficiaryAccountTokenized: Projection returned by bulk creation when the organization has tokenization enabled. ``tokenized_account_number`` is null when the account has nothing to tokenize — a cash account has no account number — or when the encryption failed for that row. The whole response is built in one comprehension, so requiring it here sinks the entire upload over a single account.
        - `external_id` string, required
        - `id_beneficiary` string, uuid, required
        - `id_beneficiary_account` string, uuid, required
        - `tokenized_account_number` string, nullable
  - `accounts_created_count` integer, required
  - `accounts_errors` AccountCreationError[]
    - `beneficiary_external_id` string, nullable: external_id of the beneficiary the account belongs to.
    - `code` 'VALIDATION_ERROR' | 'PERSISTENCE_ERROR', required: Machine-readable reason a row could not be created during bulk creation. Stable identifiers meant to be mapped to localized copy by API/UI consumers (e.g. the webapp translates the code; the API exposes both code and message). The ``message`` carried alongside each error is the human-readable English fallback for consumers without a translation layer. Duplicates are not errors: a row whose natural key already exists is reported as an omission (see ``BulkCreationOmissionCode``), never here.
    - `external_id` string, nullable: external_id of the rejected account row.
    - `message` string, required: Texto en inglés de la falla; respaldo si no traduces el `code`.
  - `accounts_failed_count` integer
  - `accounts_omitted` AccountOmission[]
    - `beneficiary_external_id` string, nullable: external_id of the beneficiary the account belongs to.
    - `code` 'ALREADY_EXISTS': Machine-readable reason a row was skipped during bulk creation. An omission is informational, not an error: the row matched an existing record (same natural key) and was intentionally left untouched.
    - `external_id` string, nullable: external_id of the skipped account row.
    - `message` string, required: Texto en inglés de por qué se omitió la fila; respaldo si no traduces el `code`.
  - `accounts_omitted_count` integer
  - `beneficiaries_created` Beneficiary[]
    - `_id` string
    - `country_code` 'CL' | 'MX' | 'BR', required: País, en código [ISO 3166-1 alfa-2](https://es.wikipedia.org/wiki/ISO_3166-1_alfa-2). Se limita a los países donde Toku opera: `CL` (Chile), `MX` (México) y `BR` (Brasil). El país determina qué medios de pago y qué productos de cobro están disponibles.
    - `created_at` string, nullable
    - `created_by` string, nullable
    - `deleted_at` string, nullable
    - `email` string, nullable
    - `external_id` string, required
    - `id_beneficiary` string, uuid
    - `id_beneficiary_batch` string, uuid, required
    - `identity_document` IdentityDocument
      - `number` string, required
      - `type` 'CURP' | 'RFC' | 'RUT' | 'TAX_ID', required: Tipos de documento con que se identifica a un Beneficiary. Cada uno corresponde a un país: `RUT` es el rol único tributario chileno y solo se acepta en Chile; `RFC` es el registro tributario mexicano, `CURP` la clave de registro poblacional y `TAX_ID` el registro tributario genérico para un Beneficiary sin RFC, y los tres solo se aceptan en México.
    - `metadata` object
    - `name` string, required
    - `organization_id` string, required
    - `phone` string, nullable
    - `types` BeneficiaryType[]
    - `updated_at` string, nullable
  - `beneficiaries_created_count` integer, required: Cantidad de Beneficiaries creados.
  - `beneficiaries_errors` BeneficiaryCreationError[]
    - `code` 'VALIDATION_ERROR' | 'PERSISTENCE_ERROR', required: Machine-readable reason a row could not be created during bulk creation. Stable identifiers meant to be mapped to localized copy by API/UI consumers (e.g. the webapp translates the code; the API exposes both code and message). The ``message`` carried alongside each error is the human-readable English fallback for consumers without a translation layer. Duplicates are not errors: a row whose natural key already exists is reported as an omission (see ``BulkCreationOmissionCode``), never here.
    - `external_id` string, nullable: external_id of the rejected beneficiary row.
    - `message` string, required: Texto en inglés de la falla; respaldo si no traduces el `code`.
  - `beneficiaries_failed_count` integer, required: Cantidad de Beneficiaries que no se pudieron crear.
  - `beneficiaries_omitted` BeneficiaryOmission[]
    - `code` 'ALREADY_EXISTS': Machine-readable reason a row was skipped during bulk creation. An omission is informational, not an error: the row matched an existing record (same natural key) and was intentionally left untouched.
    - `external_id` string, nullable: external_id of the skipped beneficiary row.
    - `message` string, required: Texto en inglés de por qué se omitió la fila; respaldo si no traduces el `code`.
  - `beneficiaries_omitted_count` integer, required: Cantidad de Beneficiaries omitidos por existir previamente.
  - `id_beneficiary_batch` string, uuid, required: Identificador del lote que agrupa todo lo creado en esta llamada.

## Other responses

- `422`: El cuerpo de la solicitud no cumple el formato esperado.
- `500`: Error inesperado al procesar la solicitud.

## Changes

- **2026-11-03** `a6ef070075b1`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/trytoku/apis/toku-api/changes/payouts-beneficiary/post.md)

---

[API](https://skmtc.dev/trytoku/apis/toku-api.md) - [All operations](https://skmtc.dev/trytoku/apis/toku-api/llms.txt) - [OpenAPI document](https://skmtc.dev/trytoku/apis/toku-api/revisions/a6ef070075b1?raw)
