Quotation Guide

Overview

Quotations provide real-time exchange rate calculations for cross-border payments. A quote includes the exchange rate, all applicable fees, and the exact amount the recipient will receive.

Create a Quote

Endpoint

POST /v1/quotations

Headers

HeaderRequiredDescription
AuthorizationYesBearer token from authentication
x-api-keyYesYour API key
Content-TypeYesMust be application/json

Request Body

{
  "base_currency": "USD",
  "quote_currency": "MXN",
  "amount": 1000.00,
  "amount_in_destination": false,
  "account_type": "SPEI",
  "network": "solana"
}

Request Fields

FieldTypeRequiredDescription
base_currencystringNoSource currency. Defaults to "USD". Valid: USD, USDC, USDT
quote_currencystringYesTarget currency (see supported currencies below)
amountnumberYesAmount to convert (must be positive)
amount_in_destinationbooleanNoIf true, amount is the destination amount. Defaults to false
account_typestringNoPayment rail. Defaults based on currency
networkstringNoBlockchain network for stablecoins (USDC/USDT only)

Example Request

curl -X POST https://api.balampay.com/v1/quotations \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "base_currency": "USD",
    "quote_currency": "MXN",
    "amount": 1000.00
  }'

Response

{
  "data": {
    "quote_id": "550e8400-e29b-41d4-a716-446655440000",
    "base_amount": 1000.00,
    "base_currency": "USD",
    "quote_amount": 19110.00,
    "quote_currency": "MXN",
    "account_type": "SPEI",
    "rate": 19.80,
    "kira_rate": 19.62,
    "expiration_ts": "2026-02-03T12:15:00.000Z",
    "status": "ACTIVE",
    "fees": {
      "base_fees": {
        "fixed_fee": 5.00,
        "percentage_fee": 10.00,
        "fx_markup": 0.005
      },
      "client_markup": {
        "fixed_fee": 2.50,
        "percentage_fee": 5.00,
        "fx_markup": 0.003
      },
      "network_fee": 0.00,
      "penalty_markup": 0.00,
      "total_fees": 22.50
    }
  }
}

Response Fields

FieldDescription
quote_idUnique identifier for the quote
base_amountAmount in source currency
base_currencySource currency code
quote_amountAmount recipient will receive
quote_currencyDestination currency code
account_typePayment rail used
rateCommercial exchange rate
kira_rateEffective rate after all markups
expiration_tsQuote expiration timestamp (10 minutes from creation)
statusQuote status (ACTIVE, EXPIRED, USED)
feesDetailed fee breakdown
networkBlockchain network (stablecoins only)

Supported Currencies

Base Currencies

CurrencyDescriptionNetworks
USDUS DollarN/A
USDCUSD CoinSolana (default), Polygon
USDTTetherTron (default), Polygon

Quote Currencies

CurrencyRegionDefault Account TypeValid Account Types
MXNMexicoSPEISPEI
COPColombiaPSEPSE, WALLET
ARSArgentinaARSARS
BRLBrazilBRLBRL
CLPChileCLPCLP
PENPeruPENPEN
UYUUruguayUYUUYU
GTQGuatemalaGTQGTQ
CRCCosta RicaCRCCRC
DOPDominican RepublicDOPDOP
PYGParaguayPYGPYG
USDUnited StatesACHACH, WIRE, SWIFT, PEUSD, ECUSD, PAUSD, SVUSD
USDCGlobalWALLETWALLET
USDTGlobalWALLETWALLET

Stablecoin Networks

When using USDC or USDT as the base currency, you can specify which blockchain network to use.

USDC Networks

NetworkDescription
solanaSolana blockchain (default)
polygonPolygon (Matic) blockchain

USDT Networks

NetworkDescription
tronTron blockchain (default)
polygonPolygon (Matic) blockchain

Example: USDC Quote with Specific Network

curl -X POST https://api.balampay.com/v1/quotations \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "base_currency": "USDC",
    "quote_currency": "MXN",
    "amount": 500.00,
    "network": "polygon"
  }'

Response with Network

{
  "data": {
    "quote_id": "550e8400-e29b-41d4-a716-446655440000",
    "base_amount": 500.00,
    "base_currency": "USDC",
    "quote_amount": 9750.00,
    "quote_currency": "MXN",
    "account_type": "SPEI",
    "network": "polygon",
    "rate": 19.80,
    "kira_rate": 19.62,
    "expiration_ts": "2026-02-03T12:15:00.000Z",
    "status": "ACTIVE",
    "fees": {
      "network_fee": 1.00,
      "total_fees": 15.00
    }
  }
}

Account Types

The account_type parameter specifies which payment rail to use. If not provided, it defaults based on the quote currency.

USD Account Types

When quote_currency is USD, you can choose from multiple rails:

Account TypeDescription
ACHUS domestic bank transfer (default)
WIREUS domestic wire transfer
SWIFTInternational wire transfer
PEUSDUSD in Peru
ECUSDUSD in Ecuador
PAUSDUSD in Panama
SVUSDUSD in El Salvador

Example: USD Quote with WIRE

curl -X POST https://api.balampay.com/v1/quotations \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "base_currency": "USD",
    "quote_currency": "USD",
    "amount": 5000.00,
    "account_type": "WIRE"
  }'

Inverse Calculation

Use amount_in_destination: true when you know how much the recipient should receive and need to calculate how much to send.

Example: Specify Destination Amount

curl -X POST https://api.balampay.com/v1/quotations \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "base_currency": "USD",
    "quote_currency": "MXN",
    "amount": 20000.00,
    "amount_in_destination": true
  }'

Response

{
  "data": {
    "quote_id": "550e8400-e29b-41d4-a716-446655440000",
    "base_amount": 1045.00,
    "base_currency": "USD",
    "quote_amount": 20000.00,
    "quote_currency": "MXN",
    "kira_rate": 19.62,
    "status": "ACTIVE"
  }
}

In this example:

  • You specified you want the recipient to receive 20,000 MXN
  • The API calculated you need to send 1,045 USD

Fee Structure

Fee Components

ComponentDescription
base_fees.fixed_feePlatform fixed fee
base_fees.percentage_feePlatform percentage fee (in base currency)
base_fees.fx_markupPlatform FX markup
client_markup.fixed_feeClient-specific fixed fee
client_markup.percentage_feeClient-specific percentage fee
client_markup.fx_markupClient-specific FX markup
network_feeBlockchain network fee (stablecoins only)
penalty_markupOff-hours or holiday surcharge
total_feesSum of all fees

Fee Calculation

Total Fixed Fee = base_fees.fixed_fee + client_markup.fixed_fee + network_fee
Total Percentage Fee = (base_fees.percentage_fee + client_markup.percentage_fee) as rate

Amount After Fees = base_amount - Total Fixed Fee - (base_amount × Total Percentage Fee)
Quote Amount = Amount After Fees × kira_rate

Penalty Markup

Additional FX markup may apply during:

  • Off-hours: Evening and weekend hours (America/New_York timezone)
  • Holidays: Specific holiday dates

The penalty markup is automatically calculated and included in the quote.


Quote Expiration

All quotes expire 10 minutes after creation.

  • Status: ACTIVEEXPIRED
  • Timestamp: expiration_ts field shows exact expiration time
  • Update: Updating quote amount resets the 10-minute timer

If you need a new rate after expiration, create a new quote.


Error Responses

Validation Error

Status: 400 Bad Request

{
  "error": "quote_currency is required",
  "valid_quote_currencies": ["MXN", "COP", "ARS", "BRL", "CLP", "PEN", "UYU", "GTQ", "CRC", "DOP", "PYG", "USD", "USDC", "USDT"]
}

Invalid Network

Status: 400 Bad Request

{
  "error": "Invalid network 'ethereum' for USDC",
  "valid_networks": ["solana", "polygon"]
}

Invalid Account Type

Status: 400 Bad Request

{
  "error": "Invalid account_type 'WIRE' for currency 'MXN'",
  "valid_account_types": ["SPEI"]
}

Currency Pair Not Enabled

Status: 400 Bad Request

{
  "error": {
    "code": "CURRENCY_PAIR_NOT_ENABLED",
    "message": "Currency pair not enabled for this account type",
    "details": {
      "base_currency": "USD",
      "quote_currency": "XYZ",
      "account_type": "SPEI"
    }
  }
}

Fees Exceed Amount

Status: 409 Conflict

{
  "error": {
    "code": "FEES_EXCEED_AMOUNT",
    "message": "Total fees exceed the amount",
    "details": {
      "amount": 10.00,
      "total_fees": 15.00
    }
  }
}

Invalid Calculated Amount

Status: 400 Bad Request

Occurs when using amount_in_destination: true with an amount too small to cover fees.

{
  "error": {
    "code": "INVALID_CALCULATED_AMOUNT",
    "message": "Amount too small to calculate with given fees",
    "details": {
      "requested_amount": 100.00,
      "calculated_base_amount": -50.00
    }
  }
}

Quote Not Found

Status: 404 Not Found

{
  "error": {
    "code": "QUOTE_NOT_FOUND",
    "message": "Quote not found: 550e8400-e29b-41d4-a716-446655440000"
  }
}

Quote Invalid State

Status: 400 Bad Request

{
  "error": {
    "code": "QUOTE_INVALID_STATE",
    "message": "Quote is not active or has expired"
  }
}

Unauthorized

Status: 401 Unauthorized

{
  "code": "unauthorized",
  "message": "No client ID found in claims"
}

Best Practices

  1. Create quotes close to payout time - Quotes expire after 10 minutes
  2. Handle expiration gracefully - If a quote expires, create a new one
  3. Use inverse calculation wisely - Useful when the recipient needs an exact amount
  4. Specify account type when needed - Use explicit account types for USD payouts
  5. Check fee breakdown - Review the fee structure before committing to a payout
  6. Store quote IDs - Save the quote_id to reference when creating payouts

Next Steps

After creating a quote:

  1. Create a Payout - Use the quote to send funds to a recipient
  2. Set up Webhooks - Track payout status updates

Support