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.

WorkflowLegacy StatusImpact LevelAction Required
Authorization (Login)BreakingCriticalMandatory baseline update. Migrate to the new base URL and implement RSA-encrypted challenge-response payloads. Static API keys will be blocked.
Sub-Account OnboardingNo ChangeNoneKeep current implementation.
Get WalletsDeprecatedLowMigrate from Get a Wallet to Get all Wallets.
Receive Funding WebhookNo ChangeNoneKeep current implementation.
Sub-Account SweepNo ChangeNoneVerify usage of Wallet-to-Wallet Transfer.
Get FX RateBreakingBreaking ChangeChange method to POST; update nested body parameters.
Create FX TradeBreakingBreaking ChangeMigrate to new FX trading endpoints and payloads.
Get BeneficiariesBreakingBreaking ChangeMigrate to new response structure
Wallet Payout / WithdrawalBreakingBreaking ChangeMigrate 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:

  1. Change your login URL:
  1. 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:

ActionsStatus
Create Sub-AccountNo change
Add Onboarding DataNo change
Create WalletNo change
Get Account Details for WalletNo change
Receive Funding WebhookNo 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&currencyTo=NGN).

https://api-v3-sandbox.vertofx.com/orders/v2.1/fx?currencyFrom=GHS&currencyTo=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.
Must be explicitly set to convertWithinWallets for the wallet-to-wallet flow. This enables moving funds from child sub-account wallets to the parent wallet for payout.

--

targetWalletId

Breaking

New Required Field.
You must now explicitly pass the destination wallet ID.

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).Map amount to sourceAmount.
  • If your Legacy Side was BUY: (You want to buy a fixed amount of the destination currency).Map amount to targetAmount.

🔄 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, currencyFrom and currencyTo are explicitly returned at the root.
  • Status Tracking: The fields transactionState and status have been consolidated and expanded. Look at the state field (e.g., initiated, confirmed, inwardSettlementDone) to track progress.
Legacy Response FieldNew Response FieldNotes
order.ididNow returned as a String at the root level.
order.referencereferenceRemains a string reference code
order.amountFromamountFromRoot level float
order.amountToamountToRoot level float
order.raterateReturned as a numeric type instead of a string
order.transactionStatestateUpdated 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