Exchange (FX / Currency Conversion)
Currency quotation and conversion system to get real-time rates and execute cross-border movements.
All endpoints require authentication with Authorization: Bearer [TOKEN] and x-api-key.
Overview
What is Exchange?
The Exchange module in Colurs allows you to:
- Get FX quotes between currency pairs
- Execute cross-border movements with automatic disbursement to bank accounts
- Calculate exchange rates with per-user custom fees
Behavior
- Synchronous: Creating and querying quotes (immediate response)
- Asynchronous: Executing cross-border movements (confirmation via webhook)
Webhooks notify movement status changes: initiated, processing, completed, rejected, failed, returned, canceled.
Supported Currencies
Available pairs
The system supports 25 currency pairs in source/destination format (e.g. usd/cop, cop/usd).
| Source Currency | Destination Currencies |
|---|---|
| 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 |
Restrictions
- Minimum amount: 50 USD or equivalent in source currency
- Trading hours: By default only on business hours (Mon–Fri). With
off_market: trueyou can operate 24/7
General Flow
Get FX quote
Request a quote with POST /v2/exchange/quotes/. Valid for 3 minutes.
(Optional) Preview
Check details with GET /v2/exchange/quotes/{quote_uuid}/ or .../preview/.
Get bank account
Use GET /list_third_party_banks/?country=CO (or the relevant country) for the destination.
Initiate movement
Execute with POST /v2/exchange/initiate/ using the quote and bank account.
Receive confirmation
The system notifies via webhook when the movement is completed and automatic disbursement is made.
Quotes
Request FX quote
Returns a quote valid for 3 minutes. Only the most recent quote can be used to start a movement.
Endpoint
POST /v2/exchange/quotes/Headers
Authorization: Bearer [ACCESS_TOKEN]
Content-Type: application/json
x-api-key: [API_KEY]Request
| Field | Type | Required | Description |
|---|---|---|---|
currency_pair | string | ✅ | Currency pair (e.g. usd/cop) |
source_amount | decimal | Conditional | Amount in source currency |
destination_amount | decimal | Conditional | Amount in destination currency |
type | string | ❌ | static_quote (default) or rolling_quote |
off_market | boolean | ❌ | Allow 24/7 operation (default: false) |
Exactly one of source_amount or destination_amount must be sent.
Success response (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"
}The quote expires in 3 minutes. Only the most recent quote for the pair can be used to start a movement.
Possible errors
| Code | Cause |
|---|---|
400 | Minimum amount not met ($50 USD or equivalent) |
400 | Both source_amount and destination_amount sent |
400 | Market closed (outside hours and off_market=false) |
400 | Currency pair not configured |
502 | Error processing the quote |
Get quote by UUID
Retrieves the details of a quote by its UUID.
Endpoint
GET /v2/exchange/quotes/{quote_uuid}/Headers
Authorization: Bearer [ACCESS_TOKEN]
x-api-key: [API_KEY]
Accept: application/jsonResponse (200)
Same format as quote creation.
Errors
| Code | Cause |
|---|---|
404 | Quote not found |
List quotes
Lists the user’s quotes.
Endpoint
GET /v2/exchange/quotes/list/Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
include_expired | boolean | false | Include expired quotes |
limit | int | 10 (max 50) | Number of results |
Response (200)
Array of objects in the same format as a single quote.
Last valid quote
Returns the last valid (non-expired, unused) quote for a pair.
Endpoint
GET /v2/exchange/quotes/last/?currency_pair=usd/copQuery parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
currency_pair | string | ✅ | Currency pair (e.g. usd/cop) |
Response (200)
Quote object or 404 if no valid quote exists.
Available currency pairs
Lists all supported currency pairs.
Endpoint
GET /v2/exchange/currency-pairs/Headers
Authorization: Bearer [ACCESS_TOKEN]
x-api-key: [API_KEY]
Accept: application/jsonResponse (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"
]
}Cross-Border Movements
Initiate movement
Creates a cross-border movement using a valid FX quote. On completion, the system performs automatic disbursement to the specified bank account.
Endpoint
POST /v2/exchange/initiate/Headers
Authorization: Bearer [ACCESS_TOKEN]
Content-Type: application/json
x-api-key: [API_KEY]Request
| Field | Type | Required | Description |
|---|---|---|---|
quote_id | UUID | ✅ | UUID of the valid quote |
source_account_id | string | ✅ | Source account ID |
destination_account_id | string | ✅ | Destination account ID |
bank_account_id | int | ✅ | User bank account ID (ThirdPartyBankAccount) |
destination_description | string | ❌ | Movement description |
external_id | string | ❌ | External ID for tracking |
Quote requirements: must be valid, belong to the user, not previously used, and be the most recent for the pair.
Success response (201)
{
"sale_crypto_id": "123",
"quote_id": "456"
}Possible errors
| Code | Message / Cause |
|---|---|
400 | Quote has expired |
400 | Quote already used |
400 | Only the most recent quote can be used |
404 | Quote not found |
502 | Error processing the movement |
Execute manual disbursement
For special cases, allows creating a manual disbursement for a cross-border movement.
Endpoint
POST /v2/exchange/execute/Headers
Authorization: Bearer [ACCESS_TOKEN]
Content-Type: application/json
x-api-key: [API_KEY]Internal use or special cases. The standard flow performs automatic disbursement when the movement completes.
Movement States
| State | Description |
|---|---|
initiated | Movement started |
processing | In progress |
completed | Completed → automatic disbursement is created |
rejected | Rejected |
failed | Failed |
returned | Returned |
canceled | Canceled |
Webhooks
The system sends status change notifications for cross-border movements. You must configure a URL in your integration to receive these events.
Supported events
initiated— Movement startedprocessing— In progresscompleted— Completed (automatic disbursement)rejected— Rejectedfailed— Failedreturned— Returnedcanceled— Canceled
Security
- Webhook signature is verified via the corresponding header.
- Only cross-border movement events are processed.
Configure the webhook URL and signing secret in your Colurs account to receive notifications.