v1 API · Stable

APIs Built for
Speed and Scale

Simple REST API. Signed webhooks. No SDK required. Your first sandbox payout is two calls away.

Quick start

The same two calls in cURL and plain Node.js — no client library needed. Phone, currency, and network values below are placeholders. The codes for a licensed market are shared during onboarding.

cURL

Quick Start — cURL
bash
# 1. Get a quote
curl -X POST https://api.settlra.com/v1/quotes \
  -H "Authorization: Bearer pk_test_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: quote_001" \
  -d '{
    "source_amount_usdc": 25.50,
    "target_currency": "LOCAL",
    "idempotency_key": "quote_001"
  }'

# 2. Execute the payout
curl -X POST https://api.settlra.com/v1/payouts \
  -H "Authorization: Bearer pk_test_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_8821" \
  -d '{
    "quote_id": "qt_01HXYZ9ABCDEF",
    "recipient_phone": "+00000000000",
    "network": "MOBILE_MONEY",
    "recipient_name": "Grace Nakamura",
    "idempotency_key": "order_8821"
  }'

Node.js (fetch)

Quick Start — Node.js
typescript
const BASE = 'https://api.settlra.com/v1';
const headers = (key) => ({
  Authorization: `Bearer ${process.env.SETTLRA_API_KEY}`,
  'Content-Type': 'application/json',
  'Idempotency-Key': key,
});

// Get a quote (valid for 45 seconds)
const quote = await fetch(`${BASE}/quotes`, {
  method: 'POST',
  headers: headers('quote_001'),
  body: JSON.stringify({
    source_amount_usdc: 25.5,
    target_currency: 'LOCAL',
    idempotency_key: 'quote_001',
  }),
}).then((r) => r.json());

// Create the payout
const payout = await fetch(`${BASE}/payouts`, {
  method: 'POST',
  headers: headers('order_8821'),
  body: JSON.stringify({
    quote_id: quote.quote_id,
    recipient_phone: '+00000000000',
    network: 'MOBILE_MONEY',
    recipient_name: 'Grace Nakamura',
    idempotency_key: 'order_8821',
  }),
}).then((r) => r.json());

console.log(payout.status);          // 'AWAITING_FUNDS'
console.log(payout.deposit_address); // send exactly the quoted USDC here

Everything you need

REST API

Clean, predictable REST endpoints. JSON request/response with consistent error codes and detailed messages.

Webhooks

Real-time event notifications for every payout state change. Signed payloads with HMAC-SHA256 verification.

No SDK required

Official SDKs are not published yet. The API is small enough to call directly — the docs show every example in plain fetch and Python requests.

Sandbox Environment

Same host, pk_test_ keys. No real money moves; wallet deposits can be simulated. Sandbox and production are bound to the key, not a header.

Idempotency

Safe retries with idempotency keys. Duplicate requests return the original response — no double payouts.

Status Page

Live operational status for the API and each payment provider at settlra.com/status.

API endpoints

Base URL: https://api.settlra.com

Method
Endpoint
Description
Auth
POST
/v1/quotes
Create a conversion quote (valid for 45 seconds)
🔑
POST
/v1/payouts
Execute a payout using a valid quote ID
🔑
GET
/v1/payouts/:id
Retrieve the status of a payout
🔑
GET
/v1/payouts
List payouts with pagination and filtering
🔑
POST
/v1/webhooks
Register a webhook endpoint
🔑
GET
/v1/networks
List supported networks and their current status
—
GET
/v1/rates
Get current FX rates for all supported networks
—

Webhooks

Receive real-time notifications when payout status changes. All webhook payloads are signed with HMAC-SHA256 so you can verify authenticity.

Event types

  • payout.funds_receivedUSDC confirmed on-chain
  • payout.initiatedSent to the mobile money provider
  • payout.compliance_holdPaused for manual review
  • payout.settledMobile money delivered
  • payout.failedPayout could not be completed
  • payout.reversedFailed payout reversed, USDC returned
webhook-handler.ts
typescript
import crypto from 'crypto';

// Your webhook handler (Express.js, raw body parser)
app.post('/webhooks/settlra', (req, res) => {
  const signature = req.headers['x-settlra-signature']; // hex HMAC-SHA256, no prefix
  const expected = crypto
    .createHmac('sha256', process.env.SETTLRA_WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');

  const a = Buffer.from(signature ?? '');
  const b = Buffer.from(expected);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body.toString());
  switch (event.type) {
    case 'payout.settled':
      console.log('Payout delivered:', event.data.payout_id);
      break;
    case 'payout.failed':
      console.log('Payout failed:', event.data.payout_id);
      break;
  }

  res.json({ received: true });
});

Ready to build?

Sign up, complete KYC review with our team, and start in the sandbox — no credit card required.