Introduction

Welcome to the Tulu Switch API Reference. This section documents every available endpoint, request parameters, and response shapes. All requests use JSON over HTTPS, and every route requires a short-lived JWT access token.

Channels

Every customer, wallet, and transaction belongs to one channel. Choose the channel that fits how your platform manages funds.

Walletchannel: WALLET

Each customer gets a virtual account number linked to a real bank account. Funds move through the virtual layer. Best for platforms where customers need an account number to receive transfers.

Key endpoints: POST /v2/customers · POST /v2/customers/:id/wallets · POST /v2/purse/deposit

Accountchannel: ACCOUNT

Each customer gets a dedicated bank account that holds money directly. Best for platforms where customers need a real account to hold and manage balances.

Key endpoints: POST /v2/customers · POST /v2/checkout/accounts

Stablecoinchannel: STABLECOIN

Customer-level stablecoin wallets on supported networks (Hedera, Base, etc.). Supports HBAR, USDC, USDT, and other token currencies. Each customer has independent balances and transfer capability.

Key endpoints: POST /v2/stablecoin/customers/wallets · POST /v2/stablecoin/customers/send

Base URLs

Tulu Switch has two API base URLs — one per environment. Use the matching base URL and key prefix together.

TESThttps://api.sandbox.switch.tulupay.com
EnvironmentBase URLKey prefix
TEST (Sandbox)https://api.sandbox.switch.tulupay.compk_test_ / sk_test_
LIVE (Production)https://api.switch.tulupay.compk_live_ / sk_live_
The base URL and the key prefix must match. Sending a pk_test_ key to the LIVE base URL (or vice versa) will return a 401.

Authentication

All API requests require a short-lived JWT access token in the Authorization header.

  • Generate your API Keys from Account > Developers in the dashboard.
  • Exchange your key pair for a token via the Authenticate endpoint.
  • Include the token in every request as Authorization: Bearer <accessToken>.
  • Tokens expire after 15 minutes by default. Use the Refresh endpoint to renew without re-authenticating.
Authorization header(Bash)
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Request Format

  • All request bodies must be sent as JSON with Content-Type: application/json
  • Path parameters (e.g. :id, :reference) must be URL-encoded
  • Validate payloads before sending — the API returns a 400 with field-level errors on validation failures
Example request body(JSON)
{
  "firstName": "Ada",
  "lastName": "Obi",
  "email": "ada.obi@example.com",
  "country": "NG",
  "channel": "WALLET",
  "currency": "NGN"
}

Response Format

All responses follow the same envelope regardless of success or failure:

successtrue on success, false on any error

statusCode — HTTP status code (200, 400, 401, etc.)

message — human-readable result description

data — response payload; null on errors

errors — validation error details (present on 400 responses)

timestamp — ISO 8601 datetime of the response

Success(JSON)
{
  "success": true,
  "statusCode": 200,
  "message": "Success",
  "data": { ... },
  "timestamp": "2025-01-01T00:00:00.000Z"
}
Error(JSON)
{
  "success": false,
  "statusCode": 400,
  "message": "Currency NGN is not supported for the STABLECOIN channel",
  "errors": ["currency must be one of: USDC, USDT"],
  "data": null,
  "timestamp": "2025-01-01T00:00:00.000Z",
  "path": "/v2/purse/deposit"
}