Lock an Exchange Rate

Locking an exchange rate lets you guarantee the conversion price before executing a transaction protecting you and your users from market fluctuations between quote and execution.

All three flows: payins, payout, and bulk exchange: follow the same two-step pattern:

  1. Get a quote: Call the Currency Exchange Quote API specifying the operation type (payin, payout, or CurrencyExchange). You'll receive an exchangeRateToken with a guaranteed rate and an expiration time.
  2. Use the token: Include the exchangeRateToken in your payin, payout, or bulk exchange request. The API applies the locked rate automatically.

The sections below use a payin as the example, but the structure is similar for payouts and bulk exchange.

⚠️

Rate expiration

The locked rate is only guaranteed until the token's expirationDate. If the token expires before you submit the transaction, the operation will use the market rate at that moment.


Quote a Payin

Use this flow when you want to show the exchange rate to your user before collecting a payment.

Step 1: Request a quote

Request

curl --request GET \
     --url 'https://api.stage.localpayment.com/api/fx/currency-exchange/payin?sourceCurrency=ARS&quoteCurrency=USD&accountNumber={{accountNumber}}&quoteAccountNumber={{accountNumber}}' \
     --header 'Authorization: Bearer <your_access_token>' \
     --header 'accept: application/json'

Response

{
  "exchangeRateToken": "5c3q89a7-f1bc-4ba5-a3b5-411ba0d144ca",
  "transactionType": "PayIn",
  "accountNumber": "{{accountNumber}}",
  "sourceCurrency": "ARS",
  "creationDate": "2024-12-27T21:33:32.6513692+00:00",
  "expirationDate": "2024-12-28T05:33:32.6513692+00:00",
  "quotes": [
    {
      "paymentMethodCode": "1005",
      "rate": 0.0008369108482392735,
      "quoteCurrency": "USD"
    },
    {
      "paymentMethodCode": "1023",
      "rate": 0.0008369108482392735,
      "quoteCurrency": "USD"
    },
    {
      "paymentMethodCode": "1000",
      "rate": 0.0008369108482392735,
      "quoteCurrency": "USD"
    }
  ]
}

Step 2: Submit the payin with the token

Request

curl --request POST \
     --url https://api.stage.localpayment.com/api/payin/ \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "paymentMethod": {
    "type": "CreditCard",
    "code": "1000",
    "flow": "DIRECT"
  },
  "externalId": "4423f38d-cc35-4ca9-8119-b9102059172d",
  "country": "ARG",
  "currency": "ARS",
  "amount": 100,
  "accountNumber": "{{accountNumber}}",
  "conceptCode": "0001",
  "comment": "APPROVED",
  "exchangeRateToken": "5c3q89a7-f1bc-4ba5-a3b5-411ba0d144ca,
  "merchant": {
    "type": "COMPANY",
    "name": "Company",
    "document": {
      "id": "3000091105",
      "type": "CUIT"
    }
  },
  "payer": {
    "type": "INDIVIDUAL",
    "name": "John",
    "lastname": "Doe",
    "document": {
      "id": "37993123",
      "type": "DNI"
    },
    "email": "[email protected]",
    "phone": {
      "countryCode": "1",
      "areaCode": "11",
      "number": "98189123"
    },
    "bank": {
      "account": {
        "type": "C"
      }
    }
  },
  "metaData": {
    "1finalStatus": "APPROVED",
    "2finalStatus": "INPROGRESS"
  },
  "card": {
    "name": "APPRO",
    "number": "4970100000000055",
    "cvv": "123",
    "expirationMonth": "11",
    "expirationYear": "2029",
    "installments": 1,
    "save": false
  }
}
'

Response

{
  "transactionType": "PayIn",
  "externalId": "949e5683-4320-4129-bf0a-ea3b027b6cd1",
  "internalId": "22b29c98-92af-44bd-a164-1863ae2f1bb3",
  "paymentMethod": {
    "type": "CreditCard",
    "code": "1000",
    "flow": "DIRECT"
  },
  "country": "ARG",
  "currency": "ARS",
  "amount": 1002,
  "accountNumber": "{{accountNumber}}",
  "confirmed": {
    "currency": "ARS",
    "amount": 1002,
    "fxQuote": 1,
    "exchangeRateToken": null
  },
  "payment": {
    "installment": null,
    "currency": "ARS",
    "fxQuote": 1,
    "financingFee": 0,
    "amount": 1002
  },
  "localTaxes": [],
  "withHoldings": [],
  "fees": {
    "description": "Fee",
    "currency": "ARS",
    "fxSource": 210.8,
    "fxQuote": 1,
    "amount": 13.02,
    "account": "{{accountNumber}}"
  },
  "status": {
    "code": "103",
    "description": "APPROVED",
    "detail": "The payin was confirmed but not credited yet"
  },
  "ticket": null,
  "qr": null,
  "beneficiary": null,
  "merchant": {
    "type": "COMPANY",
    "name": "Company"
  },
  "payer": {
    "type": "INDIVIDUAL",
    "name": "John",
    "lastname": "Doe",
    "document": {
      "id": "37895247",
      "type": "DNI"
    },
    "email": "[email protected]",
    "phone": {
      "countryCode": "1",
      "areaCode": "11",
      "number": "98789632"
    },
    "address": null,
    "birthdate": null,
    "nationality": null
  },
  "intermediaries": [],
  "wireInstructions": null,
  "date": {
    "creationDate": "2024-05-19T19:02:44.018+00:00",
    "processedDate": "2024-05-19T19:02:44.799618",
    "expirationDate": "0001-01-01T00:00:00"
  },
  "card": {
    "token": "N66a0BVHGJY/oCwOyl/CbxIJ5DmCINWeir9PY9gxVGI=",
    "bin": "402670",
    "brand": "VISA",
    "country": "RS",
    "name": "John Doe",
    "last4": "3263",
    "expirationYear": 2029,
    "expirationMonth": 9
  },
  "errors": []
}


curl --request POST \
     --url https://api.stage.localpayment.com/api/payout/ \
     --header 'Authorization: Bearer <your_access_token>' \
     --header 'Content-Type: application/json' \
     --data '[{
       "externalId": "3b7e91a0-2c4d-4f83-a1b2-d05143e2238a",
       "country": "ARG",
       "currency": "ARS",
       "amount": 10000,
       "accountNumber": "{{accountNumber}}",
       "exchangeRateToken": "8f2d14b3-c4ea-4912-b7a1-922cd1e255fb",
       "paymentMethod": {
         "type": "BankTransfer",
         "code": "1005",
         "flow": "DIRECT"
       }
     }]'

Show the exchange rate before checkout

If you're building a checkout and want to display the exchange rate to your user before they confirm the payment, this is the flow:

  1. The user selects an amount and currency.
  2. Your backend calls Currency Exchange Quote API and receives the rate in the exchangeRateToken parameter.
  3. Your frontend shows: "You will pay 10,000 ARS ≈ 8.37 USD (rate: 0.000837)"
  4. User confirms.
  5. Your backend submits the payin with the exchangeRateToken to apply the locked rate.

This guarantees that the rate your user saw is the rate applied to the transaction as long as you submit before the token's expirationDate.

💡

Design tip:

Show the expirationDate in your UI as a countdown (e.g. "Rate valid for 8 hours"). This sets the right expectation and reduces support tickets when a rate changes between sessions.