Exchange (FX / Conversión de Monedas)
Sistema de cotización y conversión de divisas para obtener tasas en tiempo real y ejecutar movimientos transfronterizos.
Todos los endpoints requieren autenticación con Authorization: Bearer [TOKEN] y x-api-key.
Visión General
¿Qué es Exchange?
El módulo Exchange en Colurs permite:
- Obtener cotizaciones FX entre pares de monedas
- Ejecutar movimientos transfronterizos con dispersión automática a cuentas bancarias
- Calcular tasas de cambio con comisiones personalizadas por usuario
Comportamiento
- Síncrono: Creación y consulta de cotizaciones (respuesta inmediata)
- Asíncrono: Ejecución de movimientos transfronterizos (confirmación vía webhook)
Los webhooks notifican los cambios de estado del movimiento: initiated, processing, completed, rejected, failed, returned, canceled.
Monedas Soportadas
Pares disponibles
El sistema soporta 25 pares de monedas en formato origen/destino (ej: usd/cop, cop/usd).
| Moneda Origen | Monedas Destino |
|---|---|
| USD | COP, MXN, PEN, CLP |
| COP | USD, MXN, PEN, CLP |
| MXN | COP, USD, PEN, CLP |
| PEN | USD, MXN, COP, CLP |
| CLP | USD, MXN, PEN, COP |
Restricciones
- Monto mínimo: 50 USD o equivalente en la moneda origen
- Horarios: Por defecto solo en horario hábil (lunes–viernes). Con
off_market: truese permite operar 24/7
Flujo General
Obtener cotización FX
Solicita una cotización con POST /v2/exchange/quotes/. Válida 3 minutos.
(Opcional) Previsualizar
Consulta el detalle con GET /v2/exchange/quotes/{quote_uuid}/ o .../preview/.
Obtener cuenta bancaria
Usa GET /list_third_party_banks/?country=CO (o el país correspondiente) para el destino.
Iniciar movimiento
Ejecuta con POST /v2/exchange/initiate/ usando la cotización y la cuenta bancaria.
Recibir confirmación
El sistema notifica por webhook cuando el movimiento está completed y se realiza la dispersión automática.
Cotizaciones
Solicitar cotización FX
Obtiene una cotización válida por 3 minutos. Solo la cotización más reciente puede usarse para iniciar un movimiento.
Endpoint
POST /v2/exchange/quotes/Headers
Authorization: Bearer [ACCESS_TOKEN]
Content-Type: application/json
x-api-key: [API_KEY]Request
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
currency_pair | string | ✅ | Par de monedas (ej: usd/cop) |
source_amount | decimal | Condicional | Monto en moneda origen |
destination_amount | decimal | Condicional | Monto en moneda destino |
type | string | ❌ | static_quote (default) o rolling_quote |
off_market | boolean | ❌ | Permitir operación 24/7 (default: false) |
Debe enviarse exactamente uno de source_amount o destination_amount.
Respuesta exitosa (201)
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"cobre_quote_id": "qt_abc123",
"quote_type": "static_quote",
"currency_pair": "usd/cop",
"source_currency": "usd",
"destination_currency": "cop",
"source_amount": 100.00,
"destination_amount": 407731.25,
"fx_rate": 4077.3125,
"colurs_fx": 4036.2344,
"fees_breakdown": {
"spread": 0.0050
},
"status": "pending",
"is_last_quote": true,
"off_market": false,
"is_valid": true,
"is_expired": false,
"valid_until": "2026-02-03T10:03:00Z",
"created_at": "2026-02-03T10:00:00Z"
}La cotización expira en 3 minutos. Solo la más reciente del par puede usarse para iniciar un movimiento.
Errores posibles
| Código | Causa |
|---|---|
400 | Monto mínimo no cumplido ($50 USD o equivalente) |
400 | Ambos source_amount y destination_amount enviados |
400 | Mercado cerrado (fuera de horario y off_market=false) |
400 | Par de monedas no configurado |
502 | Error al procesar la cotización |
Obtener cotización por UUID
Consulta los detalles de una cotización por su UUID.
Endpoint
GET /v2/exchange/quotes/{quote_uuid}/Headers
Authorization: Bearer [ACCESS_TOKEN]
x-api-key: [API_KEY]
Accept: application/jsonRespuesta (200)
Mismo formato que la creación de cotización.
Errores
| Código | Causa |
|---|---|
404 | Cotización no encontrada |
Listar cotizaciones
Lista las cotizaciones del usuario.
Endpoint
GET /v2/exchange/quotes/list/Parámetros query
| Parámetro | Tipo | Default | Descripción |
|---|---|---|---|
include_expired | boolean | false | Incluir cotizaciones expiradas |
limit | int | 10 (max 50) | Número de resultados |
Respuesta (200)
Array de objetos con el mismo formato que una cotización individual.
Última cotización válida
Obtiene la última cotización válida (no expirada, no usada) para un par.
Endpoint
GET /v2/exchange/quotes/last/?currency_pair=usd/copParámetros query
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
currency_pair | string | ✅ | Par de monedas (ej: usd/cop) |
Respuesta (200)
Objeto de cotización o 404 si no hay cotización válida.
Pares de monedas disponibles
Lista todos los pares de monedas soportados.
Endpoint
GET /v2/exchange/currency-pairs/Headers
Authorization: Bearer [ACCESS_TOKEN]
x-api-key: [API_KEY]
Accept: application/jsonRespuesta (200)
{
"currency_pairs": [
"usd/cop", "usd/mxn", "usd/pen", "usd/clp",
"cop/usd", "cop/mxn", "cop/pen", "cop/clp",
"mxn/cop", "mxn/usd", "mxn/pen", "mxn/clp",
"pen/usd", "pen/mxn", "pen/cop", "pen/clp",
"clp/usd", "clp/mxn", "clp/pen", "clp/cop"
]
}Movimientos Transfronterizos
Iniciar movimiento
Crea un movimiento transfronterizo usando una cotización FX válida. Al completarse, el sistema realiza la dispersión automática a la cuenta bancaria indicada.
Endpoint
POST /v2/exchange/initiate/Headers
Authorization: Bearer [ACCESS_TOKEN]
Content-Type: application/json
x-api-key: [API_KEY]Request
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
quote_id | UUID | ✅ | UUID de la cotización válida |
source_account_id | string | ✅ | ID de cuenta origen |
destination_account_id | string | ✅ | ID de cuenta destino |
bank_account_id | int | ✅ | ID de cuenta bancaria del usuario (ThirdPartyBankAccount) |
destination_description | string | ❌ | Descripción del movimiento |
external_id | string | ❌ | ID externo para tracking |
Requisitos de la cotización: debe estar vigente, pertenecer al usuario, no haber sido usada y ser la más reciente del par.
Respuesta exitosa (201)
{
"sale_crypto_id": "123",
"quote_id": "456"
}Errores posibles
| Código | Mensaje / Causa |
|---|---|
400 | La cotización ha expirado |
400 | La cotización ya fue utilizada |
400 | Solo se puede usar la cotización más reciente |
404 | Cotización no encontrada |
502 | Error al procesar el movimiento |
Ejecutar dispersión manual
Para casos especiales, permite crear una dispersión manual asociada a un movimiento transfronterizo.
Endpoint
POST /v2/exchange/execute/Headers
Authorization: Bearer [ACCESS_TOKEN]
Content-Type: application/json
x-api-key: [API_KEY]Uso interno o casos especiales. El flujo estándar realiza la dispersión automática al completarse el movimiento.
Estados del Movimiento
| Estado | Descripción |
|---|---|
initiated | Movimiento iniciado |
processing | En proceso |
completed | Completado → se crea dispersión automática |
rejected | Rechazado |
failed | Fallido |
returned | Devuelto |
canceled | Cancelado |
Webhooks
El sistema envía notificaciones de cambio de estado para movimientos transfronterizos. Debes configurar una URL en tu integración para recibir estos eventos.
Eventos soportados
initiated— Movimiento iniciadoprocessing— En procesocompleted— Completado (dispersión automática)rejected— Rechazadofailed— Fallidoreturned— Devueltocanceled— Cancelado
Seguridad
- Se verifica la firma del webhook mediante el header correspondiente.
- Solo se procesan eventos de tipo movimiento transfronterizo.
Configura la URL de webhook y el secreto de firma en tu cuenta Colurs para recibir las notificaciones.