API v1 · REST

FleexPay API Reference

A single REST API for quotes, conversion, fiat on/off-ramp, custody, payouts and settlement. Predictable JSON, idempotent writes, and signed webhooks. Everything you need to integrate wholesale money movement.

Introduction

The FleexPay API is organised around REST. It has predictable, resource-oriented URLs, accepts application/json request bodies, returns JSON responses, and uses standard HTTP response codes, authentication and verbs. All amounts are represented as decimal strings to avoid floating-point rounding (e.g. "50000.00"), and all timestamps are ISO-8601 in UTC.

All API access is over HTTPS. Requests made over plain HTTP are rejected. The API is designed for server-to-server use — never expose a live secret key in a browser or mobile app.

Base URL & versions

The API is versioned in the path. The current stable version is v1.

EnvironmentBase URLKeys
Productionhttps://api.fleexpay.io/v1sk_live_…
Sandboxhttps://sandbox.api.fleexpay.io/v1sk_test_…

Authentication

Authenticate by supplying your secret API key as a Bearer token in the Authorization header. You can create, roll and revoke keys from the FleexPay dashboard. Each key carries a set of scopes (e.g. quotes:write, payouts:write, custody:read).

HEADERAuthorization: Bearer sk_live_•••

Example request

auth.sh
curl https://api.fleexpay.io/v1/accounts \
  -H "Authorization: Bearer sk_live_4f9c2a7b1e8d"
Treat secret keys like passwords. If a key is compromised, revoke it immediately from the dashboard — revocation is instant. Public/publishable keys (pk_…) are read-limited and safe for hosted-flow widgets only.

Idempotency

All POST requests that create or move money support idempotency. Pass a unique Idempotency-Key header (we recommend a UUID v4). If a request is retried with the same key within 24 hours, FleexPay returns the original response and never performs the action twice.

HEADERIdempotency-Key: 7e1b9c44-2f0a-4c1e-9a3b-6d2f8a0c1e55

Pagination

List endpoints are cursor-paginated. Use limit (1–100, default 25) and starting_after / ending_before with an object id.

Response envelope

list response
{
  "object": "list",
  "data": [ /* … resources … */ ],
  "has_more": true,
  "next_cursor": "tx_9f2k7Lp0"
}

Errors

FleexPay uses conventional HTTP status codes. Codes in the 2xx range indicate success, 4xx indicate a client error, and 5xx indicate a FleexPay-side error. Every error returns a structured body.

CodeMeaning
400Bad request — malformed JSON or invalid parameters
401Unauthorized — missing or invalid API key
403Forbidden — key lacks the required scope
404Not found — resource does not exist
409Conflict — idempotency or state conflict
422Unprocessable — validation failed (e.g. insufficient funds)
429Too many requests — rate limited
500Server error — retry with backoff

Error body

422 Unprocessable Entity
{
  "error": {
    "type": "insufficient_funds",
    "message": "Account balance is below the requested amount.",
    "param": "amount",
    "request_id": "req_8Hk2p9Lm"
  }
}

Rate limits

The default limit is 100 requests/second per API key for reads and 50/second for writes. Limits are returned on every response via headers. When throttled you receive 429 with a Retry-After header.

HeaderDescription
X-RateLimit-LimitMaximum requests in the window
X-RateLimit-RemainingRequests remaining
X-RateLimit-ResetUnix epoch when the window resets

Customers (KYC / KYB)

A customer represents an end-client you onboard onto FleexPay. Customers must pass KYC (individuals) or KYB (businesses) before they can transact. You may also use hosted onboarding flows.

POST/v1/customers

Request

create customer
curl https://api.fleexpay.io/v1/customers \
  -H "Authorization: Bearer sk_live_•••" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "business",
    "legal_name": "Acme Fintech Ltd",
    "registration_number": "12345678",
    "country": "GB",
    "email": "[email protected]",
    "contact": { "first_name": "Jordan", "last_name": "Lee" }
  }'

Response 201 Created

customer
{
  "id": "cus_2Nq8Xy",
  "object": "customer",
  "type": "business",
  "legal_name": "Acme Fintech Ltd",
  "country": "GB",
  "kyc_status": "pending",
  "created_at": "2026-06-30T11:58:04Z"
}

Parameters

FieldTypeNotes
type requiredstringindividual or business
legal_name requiredstringFull legal name
country requiredstringISO 3166-1 alpha-2
emailstringPrimary contact email
registration_numberstringBusiness only
GET/v1/customers/{id}
GET/v1/customers

Accounts & balances

An account holds balances across multiple assets (fiat and crypto) for you or a sub-ledgered customer. Retrieve balances to power dashboards and reconciliation.

GET/v1/accounts/{id}/balances

Response 200 OK

balances
{
  "object": "list",
  "account_id": "acc_5Tg1Wq",
  "data": [
    { "currency": "EUR",  "available": "182450.00", "pending": "0.00" },
    { "currency": "USDC", "available": "95120.50",  "pending": "500.00" },
    { "currency": "BTC",  "available": "3.10482000", "pending": "0.00000000" }
  ]
}

Quotes

A quote locks a wholesale exchange rate for a short window (typically 30 seconds). Reference the quote id when you execute a conversion to guarantee the rate.

POST/v1/quotes

Request

create quote
curl https://api.fleexpay.io/v1/quotes \
  -H "Authorization: Bearer sk_live_•••" \
  -H "Content-Type: application/json" \
  -d '{
    "from_currency": "EUR",
    "to_currency": "USDC",
    "from_amount": "50000.00",
    "side": "sell"
  }'

Response 200 OK

quote
{
  "id": "qt_3p9Xk2",
  "object": "quote",
  "from_currency": "EUR",
  "to_currency": "USDC",
  "from_amount": "50000.00",
  "to_amount": "54160.00",
  "rate": "1.0832",
  "fee": { "currency": "EUR", "amount": "25.00" },
  "side": "sell",
  "status": "open",
  "expires_at": "2026-06-30T12:00:30Z"
}

Parameters

FieldTypeNotes
from_currency requiredstringSource asset
to_currency requiredstringTarget asset
from_amountstringProvide either from_amount or to_amount
to_amountstringDesired output amount
sidestringbuy or sell

Conversions (exchange)

Execute a previously created quote to perform the conversion. The debit and credit settle atomically against the account balance.

POST/v1/conversions

Request

execute conversion
curl https://api.fleexpay.io/v1/conversions \
  -H "Authorization: Bearer sk_live_•••" \
  -H "Idempotency-Key: 7e1b9c44-2f0a-4c1e-9a3b-6d2f8a0c1e55" \
  -H "Content-Type: application/json" \
  -d '{ "quote_id": "qt_3p9Xk2", "account_id": "acc_5Tg1Wq" }'

Response 201 Created

conversion
{
  "id": "cnv_7Lm0Qa",
  "object": "conversion",
  "quote_id": "qt_3p9Xk2",
  "from": { "currency": "EUR",  "amount": "50000.00" },
  "to":   { "currency": "USDC", "amount": "54160.00" },
  "rate": "1.0832",
  "status": "settled",
  "created_at": "2026-06-30T12:00:12Z"
}

Fiat on-ramp (deposits)

Create a deposit intent to receive fiat into a virtual account via bank rails. FleexPay returns the bank details (or a virtual IBAN) to present to the payer; funds credit automatically on receipt and fire a webhook.

POST/v1/deposits

Request

create deposit
curl https://api.fleexpay.io/v1/deposits \
  -H "Authorization: Bearer sk_live_•••" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "acc_5Tg1Wq",
    "currency": "EUR",
    "method": "sepa",
    "customer_id": "cus_2Nq8Xy"
  }'

Response 201 Created

deposit
{
  "id": "dep_9Kx2Pe",
  "object": "deposit",
  "currency": "EUR",
  "method": "sepa",
  "status": "awaiting_funds",
  "deposit_instructions": {
    "account_holder": "FleexPay / Isla-Mia Blockchain Solutions LLC",
    "iban": "DE89 3704 0044 0532 0130 00",
    "bic": "COBADEFFXXX",
    "reference": "FPX-9KX2PE"
  },
  "created_at": "2026-06-30T12:01:40Z"
}

Payouts (off-ramp)

Create a payout to send fiat to a bank account or convert and pay out in stablecoin/crypto to a beneficiary. Payouts debit the account balance and can be funded directly or via a linked conversion.

POST/v1/payouts

Request

create payout
curl https://api.fleexpay.io/v1/payouts \
  -H "Authorization: Bearer sk_live_•••" \
  -H "Idempotency-Key: 1c0d…f9" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "acc_5Tg1Wq",
    "currency": "USD",
    "amount": "25000.00",
    "beneficiary_id": "ben_4Rt8Zo",
    "rail": "swift",
    "reference": "Invoice 8841"
  }'

Response 201 Created

payout
{
  "id": "pay_6Yh3Vn",
  "object": "payout",
  "currency": "USD",
  "amount": "25000.00",
  "fee": "12.00",
  "beneficiary_id": "ben_4Rt8Zo",
  "rail": "swift",
  "status": "processing",
  "estimated_arrival": "2026-07-01T16:00:00Z",
  "created_at": "2026-06-30T12:03:11Z"
}

Parameters

FieldTypeNotes
account_id requiredstringSource account
currency requiredstringPayout currency
amount requiredstringDecimal string
beneficiary_id requiredstringPre-registered beneficiary
railstringsepa · swift · ach · fps · onchain
referencestringStatement narrative

Custody wallets

Create custody wallets and generate deposit addresses. Keys are managed by FleexPay's MPC custody; you never handle private keys. Withdrawals require policy-based approval.

POST/v1/wallets

Request & response

create wallet → 201
# request
{ "asset": "USDC", "network": "ethereum", "label": "treasury-1" }

# response
{
  "id": "wlt_8Zc1Df",
  "object": "wallet",
  "asset": "USDC",
  "network": "ethereum",
  "address": "0x7A2f…9C41",
  "balance": "0.00",
  "custody": "mpc",
  "created_at": "2026-06-30T12:04:50Z"
}
GET/v1/wallets/{id}
POST/v1/wallets/{id}/addresses

Crypto transfers

Move digital assets out of a custody wallet to an external address. Transfers are screened against sanctions and travel-rule policy before broadcast.

POST/v1/transfers
create transfer → 201
# request
{
  "wallet_id": "wlt_8Zc1Df",
  "to_address": "0x91Bd…7E03",
  "asset": "USDC",
  "network": "ethereum",
  "amount": "10000.00"
}

# response
{
  "id": "trf_2Wq9Lk",
  "object": "transfer",
  "status": "pending_approval",
  "amount": "10000.00",
  "asset": "USDC",
  "network_fee": "1.20",
  "tx_hash": null,
  "created_at": "2026-06-30T12:06:22Z"
}

Beneficiaries

Register and reuse payout destinations — bank accounts or crypto addresses. Beneficiaries are validated and screened once, then referenced by id on payouts.

POST/v1/beneficiaries
create beneficiary → 201
# request — bank beneficiary
{
  "type": "bank",
  "name": "Globex Trading Inc",
  "currency": "USD",
  "bank": {
    "account_number": "000123456789",
    "routing_number": "021000021",
    "country": "US"
  }
}

# response
{ "id": "ben_4Rt8Zo", "object": "beneficiary", "status": "active" }

Transactions & ledger

Every movement of value creates an immutable ledger transaction. Query the ledger for reconciliation, statements and reporting.

GET/v1/transactions?account_id=acc_5Tg1Wq&limit=2
transactions
{
  "object": "list",
  "data": [
    {
      "id": "txn_0Aa1Bb",
      "type": "conversion",
      "direction": "debit",
      "currency": "EUR",
      "amount": "50000.00",
      "balance_after": "132450.00",
      "reference": "cnv_7Lm0Qa",
      "created_at": "2026-06-30T12:00:12Z"
    },
    {
      "id": "txn_0Cc2Dd",
      "type": "deposit",
      "direction": "credit",
      "currency": "EUR",
      "amount": "100000.00",
      "balance_after": "182450.00",
      "reference": "dep_9Kx2Pe",
      "created_at": "2026-06-30T11:40:00Z"
    }
  ],
  "has_more": true,
  "next_cursor": "txn_0Cc2Dd"
}

Webhooks

Subscribe to events to receive real-time notifications. FleexPay sends a signed POST to your endpoint. Verify the FleexPay-Signature header (HMAC-SHA256 of the raw body using your webhook secret) before trusting the payload.

POST/v1/webhook_endpoints

Register an endpoint

create webhook → 201
# request
{
  "url": "https://api.yourapp.com/hooks/fleexpay",
  "events": [ "deposit.completed", "payout.completed", "transfer.confirmed" ]
}

# response
{
  "id": "whk_5Nm2Op",
  "object": "webhook_endpoint",
  "secret": "whsec_a1b2c3d4e5",
  "status": "enabled"
}

Event payload

POST → your endpoint
{
  "id": "evt_7Qw3Er",
  "object": "event",
  "type": "payout.completed",
  "created_at": "2026-07-01T16:02:10Z",
  "data": {
    "id": "pay_6Yh3Vn",
    "status": "completed",
    "amount": "25000.00",
    "currency": "USD"
  }
}

Signature verification (Node.js)

verify.js
const crypto = require('crypto');

function verify(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Event types

EventFires when
customer.kyc_updatedKYC/KYB status changes
deposit.completedIncoming fiat funds credited
conversion.settledA conversion settles
payout.completedA payout reaches the beneficiary
payout.failedA payout is returned or rejected
transfer.confirmedOn-chain transfer confirmed
wallet.deposit_receivedInbound crypto deposit detected

Sandbox & testing

Use sandbox keys (sk_test_…) against https://sandbox.api.fleexpay.io/v1. The sandbox mirrors production behaviour, issues test funds, and lets you simulate state transitions and webhooks without moving real money.

POST/v1/sandbox/fund
simulate a deposit
{ "account_id": "acc_5Tg1Wq", "currency": "EUR", "amount": "100000.00" }
Sandbox conversions use indicative rates and never touch live liquidity. To trigger a webhook on demand, call POST /v1/sandbox/events with an event type and the target object id.

Status reference

ResourceStatuses
Quoteopen · executed · expired
Conversionpending · settled · failed
Depositawaiting_funds · completed · returned
Payoutprocessing · completed · failed · returned
Transferpending_approval · broadcasting · confirmed · failed
Customerpending · approved · rejected · review

Get your API keys

Request sandbox access today and start integrating in minutes. Our solutions engineers will help you go live.

Request access →