Atlas for Fintech - Collections Migration Guide
This guide is for fintech partners using Atlas for collections (managing multi-currency sub-accounts in KES, TZS, UGX, NGN, etc and sweeping funds to parent accounts.
This document serves as the official migration roadmap for fintech partners utilizing Atlas for multi-currency collections, funds sweeping, and FX settlement workflows. It outlines deprecated legacy endpoints, new API specifications, and the technical changes required to maintain operational continuity.
While core parts of your collection flow remain unchanged, there are breaking changes to our FX Services and Payout workflows that require your immediate attention.
| Workflow | Legacy Status | Impact Level | Action Required |
|---|---|---|---|
| Authorization (Login) | Breaking | Critical | Mandatory baseline update. Migrate to the new base URL and implement RSA-encrypted challenge-response payloads. Static API keys will be blocked. |
| Sub-Account Onboarding | No Change | None | Keep current implementation. |
| Get Wallets | Deprecated | Low | Migrate from Get a Wallet to Get all Wallets. |
| Receive Funding Webhook | No Change | None | Keep current implementation. |
| Sub-Account Sweep | No Change | None | Verify usage of Wallet-to-Wallet Transfer. |
| Get FX Rate | Breaking | Breaking Change | Change method to POST; update nested body parameters. |
| Create FX Trade | Breaking | Breaking Change | Migrate to new FX trading endpoints and payloads. |
| Get Beneficiaries | Breaking | Breaking Change | Migrate to new response structure |
| Wallet Payout / Withdrawal | Breaking | Breaking Change | Migrate to the new payout framework. |
🛠️ Phase-by-Phase Technical Changes
Phase 0: Authorization & Authentication
Before interacting with any updated v1.1 endpoints, all Atlas clients must update their Authentication setup, as the new Login API endpoint requires a certificated based authentication and different URL.
Why is this a breaking change?
If you try to send your plain, raw API key from the Legacy Login method to the new system, the connection will be rejected.
Additionally, because a live timestamp is mixed into the package during encryption, the login request automatically expires after 30 seconds.
Your backend must create this encrypted package dynamically right before making the login call. To get started on migrating the login:
- Change your login URL:
- Old Endpoint:
POSThttps://api-v3-sandbox.vertofx.com/users/login - New Endpoint:
POSThttps://api-company-sandbox.vertofx.com/users/login
- Swap the Value:
In your JSON request body, keep the parameter name exactly as "apiKey", but replace your plain text key with your newly encrypted text block.
{
"clientId": "YOUR_28_DIGIT_CLIENT_ID",
"apiKey": "RAW_STATIC_API_KEY_STRING",
"mode": "apiKey"
}{
"clientId": "YOUR_28_DIGIT_CLIENT_ID",
"apiKey": "eyJKdW5lMTg...[Encrypted Base64 String Input]...",
"mode": "apiKey"
}For more technical examples, required encryption settings, and instructions on how to download your digital certificate from the dashboard, please see the Authentication Guide and the Certificate-Based Authentication Guide.
Phase 1: Account Creation & Funding Sweeps (Low/No Impact)
The underlying operational flow for managing regional sub-accounts in local currencies e.g KES, TZS, UGX, NGN remains identical. If you have built integrations around sub-account creation, you only need to verify one endpoint boundary:
| Actions | Status |
|---|---|
| Create Sub-Account | No change |
| Add Onboarding Data | No change |
| Create Wallet | No change |
| Get Account Details for Wallet | No change |
| Receive Funding Webhook | No change |
⚠️ Critical Endpoint Deprecation Notice: If you are calling the legacy Get a Wallet (v2.2) endpoint, you must transition to the new Get all Wallets endpoint immediately.
Phase 2: FX Services (Breaking Changes) 🚨
For fintechs collecting in one currency (such as NGN or KES) and converting them into liquidity pools or settlement currencies (such as USD), the currency exchange layer contains critical breaking structural changes.
A. Get FX Rate
Migrating from the old Get an FX Rate endpoint to the new one introduces several critical breaking changes. You will need to rewrite the HTTP request method, the URL endpoints, and entirely restructure the data payload.
Here is a detailed breakdown of the breaking changes:
HTTP Method Change(GET to POST)
Old API: Used a GET request, meaning parameters were passed visibly in the URL string.
New API: Uses a POST request. Parameters must now be passed securely inside the HTTP request body as a JSON payload.
Impact: High. Any code natively calling this as a GET request will fail with a 405 Method Not Allowed or 404 Not Found error.
Base URL and Route Updates
Old API: https://api-v3-sandbox.vertofx.com/orders/v2.1/fx
New API: https://api-exchange-now-beta.vertofx.com/fx/rate
Impact: Medium.
The host domain and path have completely changed. Ensure your environment variables/configuration files are updated.
Payload Restructuring (Flat Query String to Nested Objects)
The parameter format has changed from flat query strings to objects inside a JSON body.
Legacy API: Passed strings directly (currencyFrom=USD¤cyTo=NGN).
https://api-v3-sandbox.vertofx.com/orders/v2.1/fx?currencyFrom=GHS¤cyTo=USD' New API: Requires currencyFrom and currencyTo to be formatted as JSON objects, not flat strings. Passing strings like "currencyFrom": "USD" in the new payload will result in a 400 Bad Request schema validation error.
New Mandatory Parameters (amount and amountCurrency)**
The Legacy API only required the currency pair (currencyFrom and currencyTo). You did not have to provide the transactional volume to get a general rate. The New API now introduces mandatory amount and amountCurrency parameters into the mix.
Introduction of paymentMode
The Legacy API had no logic for settlement timing on the rate fetch layer. The New API introduces an optional paymentMode parameter which defaults to immediate, but allows later. This gives your system new flexibility if you intend to book forward trades or delayed settlement cycles.
B. Create FX Trade
The new API /fx/payments is much more robust, treating FX trades as unified payment flows. It replaces the old side-based system (BUY/SELL) with explicit source/target amounts and introduces wallet identifiers for a more secure and descriptive transaction structure.
Here are the key changes you need to make to your integration.
Endpoint URL Update
The API base URL and version routing have completely changed.
Legacy URL: POST https://api-v3-sandbox.vertofx.com/orders/v2.1/fx
New URL: POST https://api-exchange-now-beta.vertofx.com/fx/payments
Request Payload Restructuring (Field-by-Field Mapping)
Payload properties have been renamed, restructured, or replaced.
Legacy Field | New Field | Change Type | Description / Migration Action |
|---|---|---|---|
vfx_token | vfxToken | Breaking | Snake case changed to camelCase. Still required and bound to the Get Rate validity window |
side (BUY / SELL) | currencyFrom, currencyTo, amountCurrency | Breaking | (Core Logic ) The side enum is removed. Instead of specifying a BUY/SELL side direction against an implicit currency pair, you must explicitly pass the source/target objects and designate which currency the amount applies to using amountCurrency. |
amount | amount | Modified Logic | While the field name is the same, its behavior now depends on amountCurrency rather than the legacy side orientation. |
clientReference | customPaymentReference | Breaking | Renamed. Max length and validation rules should be verified against the new schema. |
-- | paymentType | Breaking | New Required Field. |
-- | targetWalletId | Breaking | New Required Field. |
Handling the Removal of side (BUY / SELL)
In the new API, you no longer specify side. Instead, you define either sourceAmount or targetAmount inside the sources array based on what you know:
- If your Legacy Side was
SELL: (You are selling a fixed amount of the source currency).MapamounttosourceAmount. - If your Legacy Side was
BUY: (You want to buy a fixed amount of the destination currency).MapamounttotargetAmount.
🔄 Payload Comparison (Flow 1: Wallet-to-Wallet) Below is an explicit comparison of how to change your request payload to perform an intra-wallet FX trade.
Legacy Request Example:
{
"vfx_token": "tok_1234567890",
"side": "SELL",
"amount": 5000,
"clientReference": "InternalRef123"
}{
"paymentMode": "immediate",
"paymentType": "convertWithinWallets",
"vfxToken": "tok_1234567890",
"currencyFrom": {
"currencyName": "GBP"
},
"currencyTo": {
"currencyName": "NGN"
},
"amountCurrency": "GBP",
"amount": 5000,
"targetWalletId": 98765,
"customPaymentReference": "InternalRef123"
}Response Body Changes
The response payload is now flatter and provides significantly more metadata regarding pricing, settlement times, and state tracking.
- Order Object Nesting: The response no longer wraps the transaction details inside an order block. All core fields are now at the root level of the JSON response.
- Currency Fields: Previously returned only if successful,
currencyFromandcurrencyToare explicitly returned at the root. - Status Tracking: The fields
transactionStateandstatushave been consolidated and expanded. Look at the state field (e.g., initiated, confirmed, inwardSettlementDone) to track progress.
| Legacy Response Field | New Response Field | Notes |
|---|---|---|
order.id | id | Now returned as a String at the root level. |
order.reference | reference | Remains a string reference code |
order.amountFrom | amountFrom | Root level float |
order.amountTo | amountTo | Root level float |
order.rate | rate | Returned as a numeric type instead of a string |
order.transactionState | state | Updated enum values (initiated, confirmed, etc.) |
Phase 3: Get Beneficiaries (Breaking Changes) 🚨
This change affects scenarios where your fintech entity initiates bulk withdrawals out of the Verto ecosystem to an external account e.g., clearing collected funds from your internal wallet (USD Wallet) directly into your external corporate account e.g Standard Chartered USD Account.
Domain & Path Changes
The domain and path have changed to separate beneficiary management into its own optimized microservice.
Old Endpoint: https://api-v3-sandbox.vertofx.com/profile/v2.1/beneficiaries
New Endpoint: https://api-beneficiary-beta.vertofx.com/recipients
Pagination Parameters Renamed
If your automated scripts use pagination to look through large lists of bank accounts, the parameter keys have been renamed.
Old Parameters: You used customPageSize (how many items to show) and page (which page to view).
New Parameters: You must now use limit (max records to return) and skip (number of items to skip over).
Data Response Restructuring
The structure of the data your system receives back has changed format.
Old Response: Returned a flat list of items wrapped directly in a generic layout.
New Response:
Returns a clean, structured JSON object containing a totalCount integer and an items array.
Additionally, specific details like bank addresses are now cleaner, nested objects.
Examples:
curl --request GET \
--url 'https://api-v3-sandbox.vertofx.com/profile/v2.1/beneficiaries?customPageSize=10&page=1' \
--header 'accept: application/json'curl --request GET \
--url 'https://api-beneficiary-beta.vertofx.com/recipients?limit=10&skip=10' \
--header 'accept: application/json'[
{
"id": 284,
"accountNumber": "2000293918130",
"bankName": "PUNJAB NATIONAL BANK",
"beneficiaryAddress": "123 Main St, Floor 1..."
}
]{
"totalCount": 1,
"items": [
{
"id": 284,
"accountNumber": "2000293918130",
"bankName": "PUNJAB NATIONAL BANK",
"bankAddress": {
"address": "123 Main St, Floor 1..."
}
}
]
}Phase 3: Make Payout (Breaking Changes) 🚨
To initiate a payout to an external beneficiary, the end points have changed
Domain & Path Changes
The domain and path have changed to separate beneficiary management into its own optimized microservice.
Old Endpoint: https://api-v3-sandbox.vertofx.com/profile/v2.2/request
New Endpoint: https://api-payment-preview.vertofx.dev/payments/create
curl --request POST \
--url https://api-v3-sandbox.vertofx.com/profile/v2.1/request \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'Authorization: Bearer <LEGACY_TOKEN>' \
--data '
{
"walletId": 3,
"amount": 100,
"beneficiaryId": 284,
"purposeId": 3,
"clientReference": "Payment-100"
}
'TBD