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:
- KYC: verificación de identidad usando CURP y datos personales. Cumple regulación mexicana AML/CFT.
- On ramp: usuario paga en MXN via SPEI a una CLABE de Dynerox, recibe USDC en su Stellar wallet.
- Off ramp: usuario transfiere USDC de su wallet, recibe MXN en su CLABE registrada.
- Screening: OFAC, UN sanctions y listas locales al momento de KYC.
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
- Usuario tiene wallet Accesly creada. Quiere cargar fondos.
- App abre
<AddFundsFlow />del kit. El componente consultauseKyc(). - Si KYC status es
not-started, el flow pide datos: nombre, apellidos, CURP, fecha de nacimiento, teléfono, CLABE. - SDK llama
fiat.registerBankAccount(...). Backend crea el user en Dynerox viaPOST /v1/public/users, valida la CLABE viaGET /v1/public/banks/clabe/{id}, guarda eldyneroxUserIden eluser_fragments. - SDK llama
fiat.startOnRamp({ amount, currency: "MXN" }). Backend crea una route Dynerox deMXN via SPEIhaciaUSDC via Stellar, apuntando a la wallet address del user. - Response incluye
authorizationUrl. El flow abre este URL en un modal / redirect. El usuario completa liveness check y autoriza la operación en Dynerox. - Dynerox devuelve al usuario una CLABE virtual + monto exacto para transferir. Usuario abre su banco y hace SPEI.
- Cuando SPEI llega, Dynerox ejecuta on chain: manda USDC del hot wallet de Dynerox a la Stellar wallet del user.
- Webhook
route.status_updatellega al backend Accesly. Actualizamos el status en DDB. - El componente del kit polea
useKycy detecta que la route completó. Muestra el nuevo balance USDC en la wallet.
Requisitos del usuario final
| Dato | Formato | Notas |
|---|---|---|
| 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. |
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:
| Estado | Significado |
|---|---|
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:
user.created: user KYC creado en Dynerox. GuardamosdyneroxUserId.user.updated: cambio en datos del user.kyc.completed: usuario pasó KYC. Habilita on ramp.route.status_update: cambio de estado de una route específica (poll assisted).
Cada webhook incluye una firma HMAC en el header. Verificamos la firma con el secret que Dynerox nos devolvió al registrar el webhook.
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:
sk_test_*: sandbox. Sin dinero real. Usada por apps testnet.sk_live_*: producción. Dinero real. Usada por apps mainnet.
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
- Retention de KYC: Dynerox guarda los datos KYC por 5 años post cierre de cuenta (AML/CFT México).
- Umbrales AML: transacciones sobre cierto monto disparan reportes automáticos. Los thresholds los administra Dynerox.
- Bloqueos por sanctions: si un usuario cae en lista OFAC / UN durante el KYC, la route se cancela y el usuario queda bloqueado en Dynerox.
- Chargebacks: SPEI no permite chargebacks. Una vez que el SPEI llega, la USDC está garantizada.
Onboarding como integrador
Para habilitar KYC + fiat en tu app:
- Contactanos en
acceslyoficial@gmail.comcon "Habilitar fiat en app X". - Firmamos partnership terms con vos como integrador (necesario porque Dynerox exige KYB del integrador además del KYC del end user).
- Habilitamos
appConfig.kyc.provider = "dynerox"en tu app. - Deployás versión actualizada del SDK con
<AddFundsFlow />. - Testing end to end con montos chicos en sandbox antes de switch a prod.
Siguientes pasos
- API Reference: endpoints de
/kyc/*y/onramp. - SDK Reference: hook
useKycy componente<AddFundsFlow />. - Networks: diferencia entre sandbox y prod de Dynerox.