Integraciones

KYC y rampas fiat con Dynerox

On ramp y off ramp entre MXN y USDC sobre Stellar. Accesly integra Dynerox como proveedor de KYC y rails bancarios via SPEI. México first, expansión a otros países LATAM en roadmap del proveedor.

Qué hace Dynerox

Dynerox es la capa que conecta el mundo bancario mexicano con Stellar. Se encarga de:

Accesly no toca directamente el dinero fiat ni los datos KYC. Actuamos como orquestador: el usuario completa KYC en un flow hosteado por Dynerox (auth.dynerox.com), y nosotros solo recibimos webhooks de status.

Flujo end to end del usuario

  1. Usuario tiene wallet Accesly creada. Quiere cargar fondos.
  2. App abre <AddFundsFlow /> del kit. El componente consulta useKyc().
  3. Si KYC status es not-started, el flow pide datos: nombre, apellidos, CURP, fecha de nacimiento, teléfono, CLABE.
  4. SDK llama fiat.registerBankAccount(...). Backend crea el user en Dynerox via POST /v1/public/users, valida la CLABE via GET /v1/public/banks/clabe/{id}, guarda el dyneroxUserId en el user_fragments.
  5. SDK llama fiat.startOnRamp({ amount, currency: "MXN" }). Backend crea una route Dynerox de MXN via SPEI hacia USDC via Stellar, apuntando a la wallet address del user.
  6. Response incluye authorizationUrl. El flow abre este URL en un modal / redirect. El usuario completa liveness check y autoriza la operación en Dynerox.
  7. Dynerox devuelve al usuario una CLABE virtual + monto exacto para transferir. Usuario abre su banco y hace SPEI.
  8. Cuando SPEI llega, Dynerox ejecuta on chain: manda USDC del hot wallet de Dynerox a la Stellar wallet del user.
  9. Webhook route.status_update llega al backend Accesly. Actualizamos el status en DDB.
  10. El componente del kit polea useKyc y detecta que la route completó. Muestra el nuevo balance USDC en la wallet.

Requisitos del usuario final

DatoFormatoNotas
CURP 18 caracteres alfanuméricos Solo México. Valida contra base RENAPO durante el KYC.
CLABE 18 dígitos Cuenta bancaria mexicana. Validada contra el catálogo de bancos autorizados.
Nombre completo Nombre + apellido paterno + apellido materno Tiene que matchear el CURP.
Fecha de nacimiento YYYY-MM-DD Se cruza con CURP. Usuario tiene que ser mayor de 18.
Teléfono +52 formato E.164 Se usa para SMS de verificación durante liveness.
Liveness check Selfie + video Se hace en el flow hosteado de Dynerox, en device del user.
i
Solo México por ahora

Dynerox actualmente exige CURP (Clave Única de Registro de Población), documento oficial mexicano. Para usuarios en otros países LATAM el flow fiat queda deshabilitado con mensaje "Onramp solo disponible en México actualmente". Los usuarios pueden fondear via transferencia externa USDC o XLM desde otro exchange.

Estados de una route

Cada operación on ramp / off ramp pasa por estos estados:

EstadoSignificado
pending_identity Route creada. Falta que el user complete KYC en Dynerox.
pending_authorization KYC completado. Falta autorización del user en la UI de Dynerox (typically una firma o confirmación explícita).
active Route activa. Backend está esperando el settlement bancario o on chain.
inactive Route cancelada o expirada.

Webhooks de Dynerox

Backend Accesly recibe webhooks de Dynerox en POST /webhooks/dynerox. Los eventos que procesamos:

Cada webhook incluye una firma HMAC en el header. Verificamos la firma con el secret que Dynerox nos devolvió al registrar el webhook.

!
Falta evento de settlement final

Dynerox actualmente no dispara un webhook cuando la operación on chain se ejecuta (por ejemplo cuando el USDC llega al Stellar wallet del user). El backend Accesly complementa con un poll cada 30 segundos de las routes en active para actualizar el estado. Estamos en conversaciones con Dynerox para agregar el evento nativo.

API keys

Dynerox emite dos tipos de keys:

Las keys se guardan en AWS Secrets Manager y el backend las rutea según appConfig.network. Los integradores no ven ni configuran las keys de Dynerox: son de Accesly con Dynerox.

Uso desde el SDK

Hook useKyc

import { useKyc } from '@accesly/react';

const { status, authorizationUrl, refetch } = useKyc();

// status: 'not-started' | 'pending_identity' | 'pending_authorization' | 'active' | 'inactive'

Componente AddFundsFlow

Componente del kit que orquesta KYC + on ramp en un solo flow.

import { AddFundsFlow } from '@accesly/react/kit';

<AddFundsFlow
  onDone={() => navigate('/wallet')}
  defaultAmount={"500"}
/>

El componente detecta si el user tiene KYC. Si no, muestra formulario de registro. Si sí, muestra input de monto y dispara la route.

Llamadas directas

Para casos custom donde querés control fino:

const { fiat } = useAccesly();

// Registrar bank account + KYC data
await fiat.registerBankAccount({
  clabe: '012180011201000123',
  firstName: 'Luis',
  paternalLastName: 'Perez',
  maternalLastName: 'Sanchez',
  holderCurp: 'PESL800101HDFRRS01',
  birthDate: '1980-01-01',
  phone: '+525512345678',
});

// Crear route MXN → USDC
const route = await fiat.startOnRamp({
  amount: '500',
  currency: 'MXN',
});

// Abrir authorizationUrl en nueva tab
window.open(route.authorizationUrl, '_blank');

Off ramp: retiro a CLABE

El flow inverso: retirar USDC del wallet Stellar a la CLABE registrada.

const route = await fiat.startOffRamp({
  amount: '20',
  asset: 'USDC',
  bankAccountId: '<dyneroxBankAccountId>',
});

Requisito: user ya tiene KYC active y por lo menos una CLABE registrada. Backend maneja la parte on chain (Stellar tx que manda USDC al hot wallet de Dynerox) y Dynerox se encarga del SPEI outbound al CLABE del user.

Consideraciones regulatorias

Onboarding como integrador

Para habilitar KYC + fiat en tu app:

  1. Contactanos en acceslyoficial@gmail.com con "Habilitar fiat en app X".
  2. Firmamos partnership terms con vos como integrador (necesario porque Dynerox exige KYB del integrador además del KYC del end user).
  3. Habilitamos appConfig.kyc.provider = "dynerox" en tu app.
  4. Deployás versión actualizada del SDK con <AddFundsFlow />.
  5. Testing end to end con montos chicos en sandbox antes de switch a prod.

Siguientes pasos