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 CurrencyDestination Currencies
USDCOP, MXN, PEN, CLP
COPUSD, MXN, PEN, CLP
MXNCOP, USD, PEN, CLP
PENUSD, MXN, COP, CLP
CLPUSD, 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: true you 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

FieldTypeRequiredDescription
currency_pairstringCurrency pair (e.g. usd/cop)
source_amountdecimalConditionalAmount in source currency
destination_amountdecimalConditionalAmount in destination currency
typestringstatic_quote (default) or rolling_quote
off_marketbooleanAllow 24/7 operation (default: false)

Exactly one of source_amount or destination_amount must be sent.

Success response (201)

201 CREATED
{
  "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

CodeCause
400Minimum amount not met ($50 USD or equivalent)
400Both source_amount and destination_amount sent
400Market closed (outside hours and off_market=false)
400Currency pair not configured
502Error 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/json

Response (200)

Same format as quote creation.

Errors

CodeCause
404Quote not found

List quotes

Lists the user’s quotes.

Endpoint

GET /v2/exchange/quotes/list/

Query parameters

ParameterTypeDefaultDescription
include_expiredbooleanfalseInclude expired quotes
limitint10 (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/cop

Query parameters

ParameterTypeRequiredDescription
currency_pairstringCurrency 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/json

Response (200)

200 OK
{
  "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

FieldTypeRequiredDescription
quote_idUUIDUUID of the valid quote
source_account_idstringSource account ID
destination_account_idstringDestination account ID
bank_account_idintUser bank account ID (ThirdPartyBankAccount)
destination_descriptionstringMovement description
external_idstringExternal 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)

201 CREATED
{
  "sale_crypto_id": "123",
  "quote_id": "456"
}

Possible errors

CodeMessage / Cause
400Quote has expired
400Quote already used
400Only the most recent quote can be used
404Quote not found
502Error 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

StateDescription
initiatedMovement started
processingIn progress
completedCompleted → automatic disbursement is created
rejectedRejected
failedFailed
returnedReturned
canceledCanceled

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 started
  • processing — In progress
  • completed — Completed (automatic disbursement)
  • rejected — Rejected
  • failed — Failed
  • returned — Returned
  • canceled — 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.