VizumVizumDocumentación de la API
v1 · open.vizum.mx

API de Vizum

Conecta tu ERP, tesorería o plataforma con Vizum para consultar saldos, dar de alta beneficiarios y crear pagos nacionales e internacionales sin entrar al panel.

La API es REST sobre HTTPS, recibe y devuelve JSON, y es un espejo del panel de Vizum: lo que tu sistema hace por API es exactamente lo que tu equipo puede hacer en el panel, con los mismos permisos, las mismas comisiones y la misma revisión.

Cuentas y saldosTus razones sociales, sus wallets por moneda y el saldo de cada una.
BeneficiariosConsulta qué datos pide cada país y moneda, y da de alta o corrige a quién le pagas.
PagosCotiza comisiones y tipo de cambio, crea pagos y sigue su estatus hasta que se liquidan.

Antes de empezar

  • Todo pago pasa por la revisión de Vizum. Crear un pago lo deja en pending; Vizum lo revisa y lo envía. Igual que en el panel, un cliente no puede ejecutar el envío por su cuenta.
  • El tipo de cambio es indicativo. No existe una cotización con folio ni vencimiento: el pago toma el tipo de cambio vigente al crearse. Ver Montos y tipo de cambio.
  • Toda escritura lleva Idempotency-Key. Es obligatorio. Ver Idempotencia.

Ambientes

Hay dos ambientes, cada uno con sus propias llaves. Una llave de pruebas no funciona en producción ni al revés.

AmbienteURL baseUso
Pruebashttps://dev.open.vizum.mx/v1Integración y pruebas. No mueve dinero real.
Producciónhttps://open.vizum.mx/v1Operación real.

Todas las rutas de esta documentación son relativas a la URL base. Por ejemplo, GET /accounts es GET https://open.vizum.mx/v1/accounts.

Llama a la API desde tu servidor. No pongas tu llave en código que corra en el navegador de tus usuarios: quien la vea puede operar con ella.

Autenticación

Cada llamada se autentica con una llave de API en el header X-Api-Key. Las llaves empiezan con vzk_.

curl
curl https://open.vizum.mx/v1/accounts \
  -H "X-Api-Key: vzk_tu_llave"

Crear una llave

Vizum habilita la API por cuenta. Si en Configuración → API y Webhooks la sección API keys dice Próximamente, tu cuenta todavía no la tiene: pídele a tu ejecutivo de Vizum que la active.

  1. Entra al panel de Vizum y ve a Configuración → API y Webhooks → API keys.
  2. Ponle un nombre, elige sus alcances y, si quieres, las IPs desde las que va a funcionar y una vigencia en días (hasta 3,650).
  3. Copia la llave. Se muestra una sola vez: Vizum guarda sólo su huella y después únicamente ve sus primeros caracteres. Si la pierdes, revócala y crea otra.

La llave actúa a nombre del usuario que la creó: alcanza las mismas cuentas que ese usuario y nunca más permisos que los que tiene en el panel. Si el usuario deja de estar activo, sus llaves dejan de funcionar.

Alcances

Cada llave lleva una lista de alcances. Una ruta exige un alcance concreto, y leer no habilita escribir: una llave de sólo lectura no puede mover dinero ni cambiar a quién se le paga.

AlcancePermite
accounts:readListar cuentas.
wallets:readListar wallets y saldos.
exchange-rate:readConsultar tipos de cambio.
beneficiaries:readListar beneficiarios.
transactions:readListar y consultar pagos, calcular comisiones.
beneficiaries:createConsultar requisitos por corredor y crear beneficiarios. escritura
beneficiaries:updateEditar beneficiarios. escritura
transactions:createCrear pagos. escritura
transactions:sendFondear un pago diferido. escritura

Para escribir no basta el alcance de la llave: el usuario dueño de la llave también tiene que tener ese permiso en la cuenta, igual que en el panel.

Restricción por IP

Puedes limitar una llave a una lista de hasta 50 IPs o rangos CIDR (por ejemplo 203.0.113.10 o 203.0.113.0/24). Una lista vacía significa sin restricción. La lista se puede cambiar desde el panel sin volver a emitir la llave. Recomendamos usarla siempre en producción.

Respuestas de autenticación

EstatusCuándo
401Falta la llave, no existe, está revocada o vencida, o la llamada viene de una IP no permitida. Siempre con el mismo mensaje, Missing or invalid API key, para no revelar cuál de los casos es.
403 SCOPE_DENIEDLa llave no tiene el alcance que pide la ruta. El campo scope dice cuál falta.
403 PERMISSION_DENIEDLa llave tiene el alcance, pero su usuario no tiene ese permiso en esa cuenta.
403 ACCOUNT_NOT_AVAILABLELa cuenta no es alcanzable con esta llave, o no está activa.

Guía rápida: tu primer pago

El flujo completo, de la llave al pago, usando el ambiente de pruebas.

  1. Encuentra tu cuenta. GET /accounts devuelve tus razones sociales. Guarda el id de la que va a pagar.
  2. Elige la wallet de origen. GET /accounts/{accountId}/wallets te da las wallets de esa cuenta, su moneda y su saldo.
  3. Pregunta qué datos pide el corredor. POST /accounts/{accountId}/beneficiary-requirements con país, moneda y tipo de entidad. Dibuja tu formulario con lo que regrese; no supongas campos.
  4. Da de alta al beneficiario. POST /accounts/{accountId}/beneficiaries con esos datos en details. Si registration viene en ready, ya le puedes pagar.
  5. Cotiza. GET /accounts/{accountId}/exchange-rates para el tipo de cambio indicativo y POST /accounts/{accountId}/transactions/calculate-fee para las comisiones.
  6. Crea el pago. POST /accounts/{accountId}/transactions con un Idempotency-Key nuevo. Queda en pending, esperando la revisión de Vizum.
  7. Si es diferido, fondéalo. Un pago con isPayLater: true no debita la wallet hasta que llamas POST .../pay-now.
  8. Sigue su estatus. Consulta GET /transactions/{transactionId} hasta que llegue a un estatus final. Su línea de tiempo viene en events.
bash
# 1. Tu cuenta
curl https://dev.open.vizum.mx/v1/accounts -H "X-Api-Key: $VIZUM_KEY"

# 2. Sus wallets
curl https://dev.open.vizum.mx/v1/accounts/$ACCOUNT_ID/wallets -H "X-Api-Key: $VIZUM_KEY"

# 6. El pago (una llave de idempotencia nueva por pago)
curl -X POST https://dev.open.vizum.mx/v1/accounts/$ACCOUNT_ID/transactions \
  -H "X-Api-Key: $VIZUM_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "walletId": "'$WALLET_ID'",
    "beneficiaryId": "'$BENEFICIARY_ID'",
    "sourceCurrencyCode": "MXN",
    "sourceAmount": "15000.00",
    "concept": "Factura 1042"
  }'

Idempotencia

Toda escritura (crear o editar beneficiario, crear pago, fondear pago diferido) exige el header Idempotency-Key. Sin él la API responde 400 IDEMPOTENCY_KEY_REQUIRED y no ejecuta nada.

Genera un valor único por operación (un UUID sirve, hasta 255 caracteres) y repite el mismo valor si reintentas. Así, si tu sistema reintenta por un timeout sin saber si el pago se creó, el reintento no crea un segundo pago.

SituaciónRespuesta
Llave nuevaSe ejecuta la operación.
Misma llave, mismo cuerpo, operación terminadaSe devuelve la respuesta original sin volver a ejecutar, con el header Idempotent-Replay: true.
Misma llave, mismo cuerpo, operación en curso409 IDEMPOTENCY_KEY_IN_FLIGHT. No se ejecutó de nuevo; consulta el estado antes de reintentar.
Misma llave, cuerpo distinto409 IDEMPOTENCY_KEY_REUSED. Usa una llave nueva por operación.
Llave de más de 255 caracteres400 IDEMPOTENCY_KEY_TOO_LONG.

Si la operación falla (por ejemplo, un dato inválido), la llave se libera: corriges y reintentas con la misma. Las llaves se aíslan por cuenta y por endpoint, y el orden de los campos del JSON no importa.

Las consultas que usan POST sólo porque llevan cuerpo (beneficiary-requirements y calculate-fee) no escriben nada y no piden la llave.

Límites de uso

Cada llave tiene un presupuesto de 120 llamadas por minuto. El límite es por cliente, no por IP. Cada respuesta trae el estado de tu presupuesto:

headers
x-ratelimit-limit-whitelabel: 120
x-ratelimit-remaining-whitelabel: 119
x-ratelimit-reset-whitelabel: 60

Al agotarlo la API responde 429. Espera los segundos que indica x-ratelimit-reset-whitelabel antes de reintentar.

Cada respuesta trae también x-request-id. Inclúyelo si nos escribes a soporte por una llamada concreta.

Paginación

Las listas de beneficiarios y de pagos son paginadas, del más reciente al más antiguo.

ParámetroDescripción
pageentero, desde 1Página a devolver. Por omisión, 1.
limitentero, 1 a 100Elementos por página. Por omisión, 30.
respuesta
{
  "data": [ ... ],
  "total": 57,
  "page": 1,
  "limit": 30,
  "totalPages": 2
}

Un parámetro que la ruta no reconoce se rechaza con 400 en vez de ignorarse.

Errores

Los errores usan los códigos HTTP estándar y un cuerpo JSON. Siempre traen statusCode, message, requestId, path y timestamp, salvo el 404 de una ruta que no existe, que sólo trae statusCode y message. Según el error, traen además uno de estos identificadores estables, que es en lo que debe basarse tu código:

  • reason: errores de acceso, idempotencia y validación de la API (por ejemplo SCOPE_DENIED), a veces con campos extra como scope o accountId.
  • code y userMessage: errores de negocio al operar (saldo, beneficiario, pago). userMessage está pensado para mostrarse a tu usuario.
403 · reason
{
  "statusCode": 403,
  "message": "Esa cuenta no está disponible para esta credencial. Si es una razón social tuya, cada cuenta se habilita por separado: revisa que su onboarding esté completo y que la cuenta esté activa.",
  "reason": "ACCOUNT_NOT_AVAILABLE",
  "accountId": "0a0a0a0a-0000-4000-8000-000000000000",
  "requestId": "66c567eb-ed6e-424d-8c28-d0eca9986385",
  "path": "/api/v1/whitelabel/accounts/0a0a0a0a-0000-4000-8000-000000000000/wallets",
  "timestamp": "2026-10-27T10:48:02.855Z"
}
422 · code · ejemplo
{
  "statusCode": 422,
  "code": "TRANSACTION_NOT_PROCESSABLE",
  "message": "No se pudo procesar esta operación con los datos enviados. Verifica los datos o intenta de nuevo más tarde.",
  "userMessage": "No se pudo procesar esta operación con los datos enviados. Verifica los datos o intenta de nuevo más tarde.",
  "requestId": "…",
  "path": "…",
  "timestamp": "…"
}

Cuando la validación del cuerpo o de los parámetros falla, message es una lista con cada problema, por ejemplo ["property foo should not exist"].

Códigos HTTP

EstatusSignificado
200 201Éxito. 201 cuando se creó un beneficiario o un pago.
400Cuerpo o parámetros inválidos, identificador que no es UUID, o falta Idempotency-Key.
401Llave ausente, inválida, revocada, vencida o desde una IP no permitida.
403Sin alcance, sin permiso, o cuenta no disponible.
404El recurso no existe o no es tuyo (son la misma respuesta), la ruta no existe, o el corredor no está disponible.
409Conflicto de idempotencia.
422La operación no se pudo procesar con los datos enviados.
429Se agotó el límite por minuto.
500Error nuestro. Puedes reintentar; en escrituras, con la misma Idempotency-Key.

Identificadores de error de la API

IdentificadorEstatusQué hacer
SCOPE_DENIED403Agrega el alcance indicado en scope a la llave, o usa otra.
PERMISSION_DENIED403Pide a un administrador de la cuenta que le dé ese permiso al usuario dueño de la llave.
ACCOUNT_NOT_AVAILABLE403Revisa el accountId, que su onboarding esté completo y que la cuenta esté activa.
IDEMPOTENCY_KEY_REQUIRED400Manda el header Idempotency-Key.
IDEMPOTENCY_KEY_TOO_LONG400Usa una llave de hasta 255 caracteres.
IDEMPOTENCY_KEY_IN_FLIGHT409Consulta el estado antes de reintentar.
IDEMPOTENCY_KEY_REUSED409Usa una llave nueva para una operación nueva.
AMOUNT_ANCHOR_AMBIGUOUS400Manda sourceAmount o targetAmount, no los dos.
CORRIDOR_NOT_AVAILABLE404Todavía no se puede pagar a ese país en esa moneda para ese tipo de entidad.

Estatus de un pago

EstatusSignificado
pendingCreado y esperando la revisión de Vizum. Si no es diferido, la wallet ya se debitó.
fundedPago diferido ya fondeado con pay-now; espera la revisión de Vizum.
in_progressAprobado y en camino al banco del beneficiario.
awaiting_fundsEn proceso; los fondos todavía no se han liquidado.
filledLiquidado. A partir de aquí el pago tiene su folio en publicId. final
rejectedRechazado en la revisión. final
failedNo se pudo completar. final
canceledCancelado. final
expiredVenció sin completarse; por ejemplo, un pago diferido que no se fondeó a tiempo. final
returnedEl banco del beneficiario devolvió el pago. final
refundedReembolsado. final

La API no envía notificaciones de cambio de estatus: consulta GET /transactions/{transactionId} periódicamente mientras el pago no esté en un estatus final. Un intervalo de uno o dos minutos sobra; respeta los límites de uso.

Montos y tipo de cambio

  • Los montos son cadenas, no números: "15000.00". Así no se pierden centavos en montos grandes. Mándalos igual.
  • Monedas en ISO 4217 (MXN, USD, EUR) y países en ISO 3166-1 alfa-2 (MX, US).
  • Fechas en ISO 8601, UTC.
  • Un pago se ancla por un solo lado. Manda sourceAmount (lo que sale de tu wallet) o targetAmount (lo que le llega al beneficiario). El otro lo calcula Vizum con el tipo de cambio del momento.
  • El tipo de cambio es indicativo. indicativeRate ya incluye el margen de tu cuenta y es el que se aplicaría si creas el pago en ese momento. validUntil es la vigencia del dato en caché, no un precio garantizado. Si necesitas certeza del monto que sale, ancla el pago con sourceAmount.
  • null significa "no aplica" o "no hay dato", nunca cero. Una comisión en null no es una comisión de cero pesos.

Versionado

La versión va en la ruta: /v1. Dentro de una versión sólo hacemos cambios compatibles: agregar endpoints, agregar campos a las respuestas o agregar parámetros opcionales. Tu integración debe ignorar los campos que no conozca. Quitar o renombrar un campo, o cambiar su tipo, sólo ocurre en una versión nueva.

Listar cuentas

GET/accounts
Alcance: accounts:read

Las razones sociales que alcanza tu llave. Un mismo usuario puede operar varias cuentas, cada una con su RFC y sus wallets. Sólo aparecen las cuentas activas.

Respuesta

CampoDescripción
iduuidIdentificador de la cuenta. Es el accountId del resto de las rutas.
namestringRazón social.
rfcstring | nullRFC, o null si todavía no está capturado.
curl
curl https://open.vizum.mx/v1/accounts \
  -H "X-Api-Key: $VIZUM_KEY"
200
[
  {
    "id": "0196f2a1-4c3e-7b10-9d2a-5e8f1c0a7b21",
    "name": "EMPRESA EJEMPLO SA DE CV",
    "rfc": "EEJ200101AB1"
  }
]

Wallets de una cuenta

GET/accounts/{accountId}/wallets
Alcance: wallets:read

Las wallets de una cuenta, una por moneda o por cuenta bancaria, con su saldo.

Respuesta

CampoDescripción
iduuidIdentificador de la wallet. Es el walletId al crear un pago.
accountIduuidCuenta a la que pertenece.
namestringNombre de la wallet.
currencystringMoneda, ISO 4217.
balancestringSaldo disponible, en la moneda de la wallet.
accountNumberstringNúmero de cuenta para fondearla; en MXN, la CLABE.
curl
curl https://open.vizum.mx/v1/accounts/$ACCOUNT_ID/wallets \
  -H "X-Api-Key: $VIZUM_KEY"
200
[
  {
    "id": "0196f2a1-8e44-7c02-b1f3-2a6d9e4c0f58",
    "accountId": "0196f2a1-4c3e-7b10-9d2a-5e8f1c0a7b21",
    "name": "Principal MXN",
    "currency": "MXN",
    "balance": "250000.000000000000000000",
    "accountNumber": "646180000000000001"
  }
]

Todas las wallets

GET/wallets
Alcance: wallets:read

Las wallets de todas tus cuentas en una sola llamada, cada una con su accountId. Útil para conciliar el panorama completo sin pedir cuenta por cuenta. Misma forma que Wallets de una cuenta.

curl
curl https://open.vizum.mx/v1/wallets \
  -H "X-Api-Key: $VIZUM_KEY"

Tipos de cambio

GET/accounts/{accountId}/exchange-rates
Alcance: exchange-rate:read

Los tipos de cambio vigentes para la cuenta. Las llaves de rates tienen la forma DIVISA/BASE: USD/MXN es cuántos MXN cuesta un USD.

Indicativo. No es una cotización con folio. El pago toma el tipo de cambio vigente cuando se crea.

Respuesta

CampoDescripción
baseCurrencystringMoneda base de la cuenta.
rates[par].indicativeRatenumberTipo de cambio que se aplicaría a tu cuenta, con su margen incluido.
rates[par].spotnumber | nullTipo de cambio de referencia, sin margen.
rates[par].lastUpdatedfechaCuándo se actualizó.
rates[par].validUntilfechaVigencia del dato en caché. No es un precio garantizado.
curl
curl https://open.vizum.mx/v1/accounts/$ACCOUNT_ID/exchange-rates \
  -H "X-Api-Key: $VIZUM_KEY"
200
{
  "baseCurrency": "MXN",
  "rates": {
    "USD/MXN": {
      "indicativeRate": 19.15,
      "spot": 18.59,
      "lastUpdated": "2026-10-27T10:45:41.619Z",
      "validUntil": "2026-10-27T10:47:41.619Z"
    },
    "EUR/MXN": {
      "indicativeRate": 21.35,
      "spot": 20.72,
      "lastUpdated": "2026-10-27T10:45:41.619Z",
      "validUntil": "2026-10-27T10:47:41.619Z"
    }
  }
}

Listar beneficiarios

GET/beneficiaries
Alcance: beneficiaries:read

A quién le puedes pagar, con su país, moneda, banco y número de cuenta. Siempre la versión vigente de cada beneficiario. Paginada.

Parámetros de consulta

ParámetroDescripción
accountIduuid, opcionalSólo los beneficiarios de esa cuenta. Sin él, los de todas tus cuentas.
page, limitVer Paginación.

El objeto beneficiario

CampoDescripción
iduuidIdentificador. Es el beneficiaryId al crear un pago.
accountIduuidCuenta en la que está dado de alta.
namestring | nullNombre o razón social.
countrystring | nullPaís, ISO 3166-1 alfa-2.
currencystring | nullMoneda en la que recibe, ISO 4217.
bankstring | nullBanco.
accountNumberstring | nullCLABE, IBAN o número de cuenta.
railstring | nullRiel de pago: SPEI, SWIFT, ACH…
statusstringpending, active, inactive o rejected.
curl
curl "https://open.vizum.mx/v1/beneficiaries?accountId=$ACCOUNT_ID&limit=50" \
  -H "X-Api-Key: $VIZUM_KEY"
200 · ejemplo
{
  "data": [
    {
      "id": "01a2b3c4-0000-7000-8000-00000000b001",
      "accountId": "0196f2a1-4c3e-7b10-9d2a-5e8f1c0a7b21",
      "name": "Comercializadora del Norte SA de CV",
      "country": "MX",
      "currency": "MXN",
      "bank": "BANORTE",
      "accountNumber": "072180012345678901",
      "rail": "SPEI",
      "status": "active"
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 50,
  "totalPages": 1
}

Requisitos por corredor

POST/accounts/{accountId}/beneficiary-requirements
Alcance: beneficiaries:create

Qué datos hay que pedir para dar de alta a un beneficiario en un país y moneda. Es el mismo catálogo que usa el panel. Construye tu formulario con esta respuesta en vez de suponer campos: un alta con datos bancarios incompletos se crea, pero no se le puede pagar.

Es una consulta: no escribe nada y no lleva Idempotency-Key.

Cuerpo

CampoDescripción
countryCoderequeridostringPaís del beneficiario, ISO 3166-1 alfa-2.
currencyCoderequeridostringMoneda en la que recibe, ISO 4217.
entityTyperequeridostringindividual (persona física) o business (empresa).
railstring, opcionalSi ya elegiste un riel (SPEI, SWIFT, ACH…), acota los campos a los de ese riel.

Respuesta

CampoDescripción
fieldsTodos los campos. Cada uno con canonicalFieldId (la llave que va en details al crear el beneficiario), type (text, select, email, phone, date), label, required y, según el caso, placeholder, validation (regex, minLength, maxLength), options, defaultValue, order y groupId.
fieldGroupsLos mismos campos agrupados por sección (cuenta, titular, banco, domicilio…), en orden, para dibujar el formulario.
availableRailsRieles disponibles para el corredor.
defaultValuesValores sugeridos por campo.
metadataPaís, moneda y tipo de entidad consultados, y generatedAt.

Campos condicionales

Un campo puede traer showWhen (mostrarlo sólo si se cumple) o requiredWhen (exigirlo sólo si se cumple). Cada condición es { field, operator, value } con operator en equals, notEquals, in, notIn o matches, y puede anidar and u or. Varias condiciones en la lista se cumplen todas a la vez.

Si el corredor no está disponible: 404 CORRIDOR_NOT_AVAILABLE.

curl
curl -X POST https://open.vizum.mx/v1/accounts/$ACCOUNT_ID/beneficiary-requirements \
  -H "X-Api-Key: $VIZUM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "countryCode": "MX",
    "currencyCode": "MXN",
    "entityType": "business"
  }'
200 · recortado
{
  "fieldGroups": [ ... ],
  "fields": [
    {
      "canonicalFieldId": "businessName",
      "type": "text",
      "label": "Business Name",
      "placeholder": "e.g., Acme Corporation",
      "category": "accountHolder",
      "required": true,
      "validation": { "minLength": 2, "maxLength": 100 },
      "order": 13
    },
    {
      "canonicalFieldId": "clabeNumber",
      "type": "text",
      "required": true,
      "showWhen": [
        { "field": "countryCode", "operator": "equals", "value": "MX" }
      ],
      "validation": { "regex": "^\\d{18}$" },
      …
    },
    {
      "canonicalFieldId": "bankName",
      "type": "select",
      "required": true,
      "options": [
        { "value": "ABC CAPITAL", "label": "ABC CAPITAL" },
        …
      ],
      …
    }
  ],
  "availableRails": ["SPEI", "LOCAL", "SWIFT"],
  "metadata": {
    "countryCode": "MX",
    "currencyCode": "MXN",
    "entityType": "business",
    "generatedAt": "2026-10-27T10:49:21.407Z"
  },
  "defaultValues": {}
}

Crear beneficiario

POST/accounts/{accountId}/beneficiaries
Alcance: beneficiaries:create · Requiere Idempotency-Key

Da de alta a quién le vas a pagar, en la cuenta de la ruta. Pasa por las mismas validaciones que un alta desde el panel.

Cuerpo

CampoDescripción
countryCoderequeridostringPaís del beneficiario, ISO 3166-1 alfa-2.
currencyCoderequeridostringMoneda en la que recibe, ISO 4217.
entityTyperequeridostringindividual o business.
detailsrequeridoobjetoLos datos del beneficiario, con las llaves canonicalFieldId que devolvió Requisitos por corredor para ese país, moneda y tipo de entidad.

Respuesta 201

CampoDescripción
beneficiaryEl objeto beneficiario, igual que en la lista.
registrationstringready: ya se le puede pagar. pending: el alta se sigue procesando. partial: quedó dado de alta pero algunos de sus datos bancarios no se aceptaron; revísalos y corrígelos con Editar beneficiario.
curl
curl -X POST https://open.vizum.mx/v1/accounts/$ACCOUNT_ID/beneficiaries \
  -H "X-Api-Key: $VIZUM_KEY" \
  -H "Idempotency-Key: 6f1c9e2a-3b7d-4c55-9a10-2e8f4d7b1c03" \
  -H "Content-Type: application/json" \
  -d '{
    "countryCode": "MX",
    "currencyCode": "MXN",
    "entityType": "business",
    "details": {
      "currencyCode": "MXN",
      "businessName": "Comercializadora del Norte SA de CV",
      "rfc": "CNO150312AB4",
      "bankName": "BANORTE",
      "clabeNumber": "072180012345678901",
      "selectedRail": "SPEI"
    }
  }'
201 · ejemplo
{
  "beneficiary": {
    "id": "01a2b3c4-0000-7000-8000-00000000b001",
    "accountId": "0196f2a1-4c3e-7b10-9d2a-5e8f1c0a7b21",
    "name": "Comercializadora del Norte SA de CV",
    "country": "MX",
    "currency": "MXN",
    "bank": "BANORTE",
    "accountNumber": "072180012345678901",
    "rail": "SPEI",
    "status": "active"
  },
  "registration": "ready"
}

Editar beneficiario

PATCH/accounts/{accountId}/beneficiaries/{beneficiaryId}
Alcance: beneficiaries:update · Requiere Idempotency-Key

Corrige los datos de un beneficiario y vuelve a procesar su alta, que es lo que esperas al corregir una cuenta bancaria. La versión anterior queda en la bitácora del beneficiario.

details reemplaza todo. No se mezcla con lo que había: si mandas sólo el campo que cambió, se borran los demás. Manda el objeto completo con el cambio aplicado.

Cuerpo

CampoDescripción
detailsrequeridoobjetoLos datos completos del beneficiario.
changeReasonstring, opcionalMotivo del cambio, hasta 500 caracteres. Queda en la bitácora.

Respuesta 200

Misma forma que Crear beneficiario. Después de una edición, registration viene en pending mientras se procesa de nuevo.

curl
curl -X PATCH https://open.vizum.mx/v1/accounts/$ACCOUNT_ID/beneficiaries/$BENEFICIARY_ID \
  -H "X-Api-Key: $VIZUM_KEY" \
  -H "Idempotency-Key: 0b8e1d44-71f2-4a3c-8e6d-5c2a9f0e7b12" \
  -H "Content-Type: application/json" \
  -d '{
    "details": {
      "currencyCode": "MXN",
      "businessName": "Comercializadora del Norte SA de CV",
      "rfc": "CNO150312AB4",
      "bankName": "BBVA MEXICO",
      "clabeNumber": "012180001234567891",
      "selectedRail": "SPEI"
    },
    "changeReason": "Cambio de cuenta bancaria"
  }'

Calcular comisión

POST/accounts/{accountId}/transactions/calculate-fee
Alcance: transactions:read

Las comisiones de tu tarifario que aplicarían a un pago antes de crearlo. Son las mismas que se cobran al crearlo. Es una consulta: no lleva Idempotency-Key.

Cuerpo

CampoDescripción
amountrequeridostringMonto de origen.
currencyCoderequeridostringMoneda de origen, ISO 4217.
regionConditionrequeridostringPaís destino, ISO 3166-1 alfa-2 (por ejemplo US).
railstring, opcionalRiel del pago.
destinationClabestring, opcionalCLABE destino, para pagos nacionales.
isRefundboolean, opcionalSi es un reembolso.

Respuesta

applicableFees: lista de comisiones que aplican. Cada una trae fixedFeeAmount y fixedFeeCurrency, y las condiciones bajo las que aplica (regionCondition, rail, currencyCode, umbrales de monto). Una lista vacía significa que tu tarifario no tiene comisiones para ese pago.

curl
curl -X POST https://open.vizum.mx/v1/accounts/$ACCOUNT_ID/transactions/calculate-fee \
  -H "X-Api-Key: $VIZUM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "10000.00",
    "currencyCode": "MXN",
    "regionCondition": "US",
    "rail": "SWIFT"
  }'
200
{
  "applicableFees": []
}

Crear pago

POST/accounts/{accountId}/transactions
Alcance: transactions:create · Requiere Idempotency-Key

Crea un pago desde una wallet de la cuenta hacia un beneficiario. Queda en pending esperando la revisión de Vizum, igual que un pago creado en el panel. La wallet se debita al crearlo, salvo que sea diferido.

Cuerpo

CampoDescripción
walletIdrequeridouuidWallet de la que sale el dinero. Tiene que ser de esta cuenta y de la moneda sourceCurrencyCode.
beneficiaryIdrequeridouuidA quién se le paga.
sourceCurrencyCoderequeridostringMoneda de la wallet, ISO 4217.
sourceAmountstringLo que sale de la wallet. Manda éste o targetAmount, no los dos.
targetAmountstringLo que le llega al beneficiario. Manda éste o sourceAmount, no los dos.
targetCurrencyCodestring, opcionalMoneda en la que recibe el beneficiario.
railstring, opcionalRiel del pago, hasta 20 caracteres.
conceptstring, opcionalConcepto que ve el beneficiario, hasta 140 caracteres. En pagos nacionales por SPEI se valida un máximo de 20 caracteres al revisarlo.
clientCommentstring, opcionalNota interna para tu equipo, hasta 500 caracteres.
paymentReasonstring, opcionalCódigo de motivo del pago, cuando el destino lo requiere. Los valores válidos vienen en las options del campo paymentReason de Requisitos por corredor.
isPayLaterboolean, opcionalPago diferido: se crea sin debitar la wallet y se fondea después con pay-now. Sólo si tu cuenta tiene plazo configurado.

Respuesta 201

CampoDescripción
iduuidIdentificador del pago.
publicIdstring | nullFolio. null hasta que el pago se liquida.
accountId, walletId, beneficiaryIdLos de la solicitud.
statusstringpending. Ver Estatus de un pago.
sourceAmount, sourceCurrencyCode, targetAmount, targetCurrencyCodeMontos y monedas. El lado no anclado viene calculado cuando aplica; en un pago nacional en la misma moneda el destino va en null.
conceptstring | nullConcepto.
isPayLaterbooleanSi es diferido.
expiresAtfecha | nullHasta cuándo se puede fondear un pago diferido.
createdAtfechaCreación.
curl
curl -X POST https://open.vizum.mx/v1/accounts/$ACCOUNT_ID/transactions \
  -H "X-Api-Key: $VIZUM_KEY" \
  -H "Idempotency-Key: 3d5f7a91-0c2e-4b8d-a6f4-91e0c3b2d754" \
  -H "Content-Type: application/json" \
  -d '{
    "walletId": "0196f2a1-8e44-7c02-b1f3-2a6d9e4c0f58",
    "beneficiaryId": "01a2b3c4-0000-7000-8000-00000000b001",
    "sourceCurrencyCode": "MXN",
    "sourceAmount": "15000.00",
    "concept": "Factura 1042"
  }'
201 · ejemplo
{
  "id": "01a2b3c4-0000-7000-8000-00000000a001",
  "publicId": null,
  "accountId": "0196f2a1-4c3e-7b10-9d2a-5e8f1c0a7b21",
  "walletId": "0196f2a1-8e44-7c02-b1f3-2a6d9e4c0f58",
  "beneficiaryId": "01a2b3c4-0000-7000-8000-00000000b001",
  "status": "pending",
  "sourceAmount": "15000.00",
  "sourceCurrencyCode": "MXN",
  "targetAmount": null,
  "targetCurrencyCode": null,
  "concept": "Factura 1042",
  "isPayLater": false,
  "expiresAt": null,
  "createdAt": "2026-10-27T16:02:11.482Z"
}

Fondear pago diferido

POST/accounts/{accountId}/transactions/{transactionId}/pay-now
Alcance: transactions:send · Requiere Idempotency-Key

Debita la wallet para un pago creado con isPayLater: true y lo deja en funded, esperando la revisión de Vizum. Tiene que hacerse antes de su expiresAt. Sin cuerpo.

Respuesta 200

El pago, con la misma forma que Crear pago.

curl
curl -X POST https://open.vizum.mx/v1/accounts/$ACCOUNT_ID/transactions/$TRANSACTION_ID/pay-now \
  -H "X-Api-Key: $VIZUM_KEY" \
  -H "Idempotency-Key: 9a4c2e10-5f3b-4d7e-b1a8-6c0d2e9f4a31"

Listar pagos

GET/transactions
Alcance: transactions:read

Los pagos salientes de tus cuentas, del más reciente al más antiguo. Paginada.

Parámetros de consulta

ParámetroDescripción
accountIduuid, opcionalSólo los pagos de esa cuenta.
statusstring, opcionalSólo los pagos en ese estatus.
page, limitVer Paginación.

El objeto pago

CampoDescripción
iduuidIdentificador del pago.
accountIduuidCuenta que paga.
publicIdstring | nullFolio, asignado al liquidarse.
statusstringVer Estatus de un pago.
typestringmoney_out.
payLaterbooleanSi es diferido.
conceptstring | nullConcepto.
sourceAmount, sourceCurrencystring | nullLo que salió y en qué moneda.
targetAmount, targetCurrencystring | nullLo que llega y en qué moneda. null cuando no aplica, por ejemplo en un pago nacional en la misma moneda.
railstring | nullRiel del pago.
createdAtfechaCreación.
beneficiaryobjeto | nullEl objeto beneficiario.
curl
curl "https://open.vizum.mx/v1/transactions?status=pending&limit=20" \
  -H "X-Api-Key: $VIZUM_KEY"
200 · ejemplo
{
  "data": [
    {
      "id": "01a2b3c4-0000-7000-8000-00000000a001",
      "accountId": "0196f2a1-4c3e-7b10-9d2a-5e8f1c0a7b21",
      "publicId": null,
      "status": "pending",
      "type": "money_out",
      "payLater": false,
      "concept": "Factura 1042",
      "sourceAmount": "15000.00",
      "sourceCurrency": "MXN",
      "targetAmount": null,
      "targetCurrency": null,
      "rail": "SPEI",
      "createdAt": "2026-10-27T16:02:11.482Z",
      "beneficiary": { … }
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 20,
  "totalPages": 1
}

Detalle de un pago

GET/transactions/{transactionId}
Alcance: transactions:read

Un pago con su desglose y su línea de tiempo. Es la ruta para seguir el estatus de un pago. Si el pago no existe o no es de tus cuentas, la respuesta es la misma: 404.

Respuesta

El objeto pago más:

CampoDescripción
feestring | nullComisión total cobrada, en la moneda de origen. null si no hay comisión registrada.
ratestring | nullTipo de cambio aplicado: una unidad de sourceCurrency en targetCurrency.
eventslistaLínea de tiempo, de lo más antiguo a lo más reciente. Cada evento es { type, at }.

Tipos de evento

TipoSignificado
createdSe creó el pago.
updatedCambió el estatus o los datos del pago.
approvedVizum aprobó el pago.
rejectedVizum rechazó el pago.
money_inSe registró un movimiento de fondos del pago.
pay_later.fundedSe fondeó un pago diferido.
pay_later.extendedSe extendió el plazo de un pago diferido.
pay_later.reactivatedSe reactivó un pago diferido.
pay_later.cancelledSe canceló un pago diferido.
internal_transfer.completedSe completó una transferencia entre wallets.
curl
curl https://open.vizum.mx/v1/transactions/$TRANSACTION_ID \
  -H "X-Api-Key: $VIZUM_KEY"
200 · ejemplo
{
  "id": "01a2b3c4-0000-7000-8000-00000000a002",
  "accountId": "0196f2a1-4c3e-7b10-9d2a-5e8f1c0a7b21",
  "publicId": "VZM-2026-000123",
  "status": "filled",
  "type": "money_out",
  "payLater": false,
  "concept": "Factura 88",
  "sourceAmount": "19150.00",
  "sourceCurrency": "MXN",
  "targetAmount": "1000.00",
  "targetCurrency": "USD",
  "rail": "SWIFT",
  "createdAt": "2026-10-27T16:10:03.120Z",
  "beneficiary": { … },
  "fee": "350.00",
  "rate": "0.0522",
  "events": [
    { "type": "created",  "at": "2026-10-27T16:10:03.120Z" },
    { "type": "approved", "at": "2026-10-27T16:24:47.902Z" },
    { "type": "updated",  "at": "2026-10-27T17:02:15.331Z" }
  ]
}

¿Dudas con la integración? Escríbenos a soporte con el x-request-id de la llamada.