Skip to main content

Prerequisites

  • An active Yala sandbox account. Request access from your Yala relationship manager or by emailing developers@useyala.com.
  • A sandbox API key (x-api-key) with CAN_INITIATE_PAYMENT permission.
  • A registered business with funded wallets in the currencies you plan to send.
  • Currency pairs enabled in your dashboard.
Newly generated API keys can take up to 20-30 minutes to fully propagate. During this window, requests may return 403 Forbidden.
New to Yala? Read the End-to-End Integration Flow guide first to understand how to integrate payout APIs into your application for your end users.

1. Configure environments

EnvironmentBase URL
Productionhttps://gateway.useyala.com/v1/payout-api/payouts
Sandboxhttps://gateway.staging.useyala.com/v1/payout-api/payouts
Sandbox tip: Use gateway.staging.useyala.com when testing against the sandbox app.
Save the x-api-key in your secret manager and inject it at runtime. Avoid hardcoding keys in source control.

2. Check wallet balances

Before requesting quotes or initiating payouts, check your available balances by currency:
curl https://gateway.staging.useyala.com/v1/payout-api/payouts/wallets \
  -H "x-api-key: <SANDBOX_API_KEY>"
For full request/response fields and examples, see Get Wallet Balances.

3. Enable currency pairs

Before creating payouts, enable currency pairs in your Yala dashboard. Only enabled pairs are available via API.
# Check enabled pairs
curl https://gateway.staging.useyala.com/v1/payout-api/payouts/pairs \
  -H "x-api-key: <SANDBOX_API_KEY>"

4. Get payment methods and rates

Call the methods endpoint to get available payment methods, current rates, and required beneficiary fields for your corridor.
curl "https://gateway.staging.useyala.com/v1/payout-api/payouts/methods?sourceCurrency=NGN&destinationCurrency=CNY&destinationCountryCode=CHN" \
  -H "x-api-key: <SANDBOX_API_KEY>"
Response includes:
  • Current exchange rate
  • Available payment methods (e.g., ALIPAY, WECHAT, SWIFT)
  • Required and optional beneficiary fields for each method
  • Fees and settlement times
Use the requiredFields array to dynamically render your payout form based on the selected payment method.

5. Upload a supporting document

For most payouts, attach an invoice before the payment can be processed. Withdrawals—transfers to your business’s own account or to a UBO’s account—do not require an invoice. You can attach documents when initiating the payout or after via PATCH, as long as the payout has not finished processing. How upload works: You call Yala once for a presigned URL, PUT the file directly to S3 (not to Yala), then pass the returned documentUrl when initiating or patching the payout.
// 1. Get presigned URL from Yala (JSON only — no file bytes)
const uploadMeta = await fetch(
  'https://gateway.staging.useyala.com/v1/payout-api/payouts/documents/upload-url',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': apiKey,
    },
    body: JSON.stringify({
      filename: 'invoice.pdf',
      contentType: 'application/pdf',
    }),
  }
);
const { uploadUrl, documentUrl, headers } = await uploadMeta.json();

// 2. PUT file bytes to S3 (Amazon — not Yala)
const fileBuffer = await fs.readFile('invoice.pdf');
await fetch(uploadUrl, {
  method: 'PUT',
  headers,
  body: fileBuffer,
});

// 3. Use documentUrl on POST /initiate (step 6) or PATCH /:id/documents later
See Uploading Supporting Documents for both flows (before or after initiate).

6. Initiate the payout

Important: You must generate an Idempotency-Key client-side before making the request. This prevents duplicate payouts if the request is retried.
// Generate idempotency key (client-side)
const idempotencyKey = crypto.randomUUID();
// OR use your order ID: `order-${orderId}`
curl https://gateway.staging.useyala.com/v1/payout-api/payouts/initiate \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "x-api-key: <SANDBOX_API_KEY>" \
  -d '{
    "sourceAmount": 10000,
    "sourceCurrency": "NGN",
    "destinationCurrency": "CNY",
    "destinationCountryCode": "CHN",
    "method": "ALIPAY",
    "beneficiary": {
      "accountName": "Li Wei",
      "accountCurrency": "CNY",
      "alipayId": "user@alipay.com",
      "address": "123 Main St",
      "city": "Beijing",
      "postCode": "100000"
    },
    "narration": "Payment for services",
    "supportingDocument": "<documentUrl from upload-url step, or omit and attach later>"
  }'
Response includes:
  • id - Save this payout ID for tracking status
  • status - Initial status (PENDING)
  • Conversion details (exchange rate, amounts)
  • payoutRef - Human-readable reference
What happens:
  1. Debit is always from the source currency wallet—your NGN wallet is debited by the total (source amount + fees).
  2. System handles FX conversion automatically
  3. Payout created with status PENDING
Idempotency-Key is required. If the request fails (network error, timeout), retry with the same key + same body. The API will return the original payout (no duplicate created).

7. Track payout status

Query payout status using the payout ID from the initiate response:
curl https://gateway.staging.useyala.com/v1/payout-api/payouts/{payoutId} \
  -H "x-api-key: <SANDBOX_API_KEY>"
Status values (same in API responses and webhooks):
  • PENDING - Payout created or awaiting approval; additional info submitted and under review; not yet sent for processing
  • ADDITIONAL_INFO_REQUIRED - Additional information has been requested for this payout
  • PROCESSING - Payout is being processed (ops, bank, or treasury)
  • SUCCESSFUL - Completed; funds have been sent
  • FAILED - Processing failed (e.g. bank failure)
  • REJECTED - Rejected (e.g. compliance, initiation checks, or bank)
Subscribe to webhooks for real-time status updates:
  1. Activate webhook notifications in your Yala dashboard
  2. Configure your webhook endpoint URL
  3. Receive payout.status.changed.v1 events when status changes
The webhook payload includes the payout id so you can match it with your records.

Complete Example

// 1. Generate idempotency key
const idempotencyKey = crypto.randomUUID();

// 2. Get methods and rates
const methodsResponse = await fetch(
  'https://gateway.staging.useyala.com/v1/payout-api/payouts/methods?sourceCurrency=NGN&destinationCurrency=CNY&destinationCountryCode=CHN',
  {
    headers: { 'x-api-key': apiKey }
  }
);
const { methods, rate } = await methodsResponse.json();
console.log(`Rate: ${rate.rate}, Methods: ${methods.map(m => m.code).join(', ')}`);

// 3. Create payout
const payoutResponse = await fetch(
  'https://gateway.staging.useyala.com/v1/payout-api/payouts/initiate',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Idempotency-Key': idempotencyKey,  // Client-generated
      'x-api-key': apiKey,
    },
    body: JSON.stringify({
      sourceAmount: 10000,
      sourceCurrency: 'NGN',
      destinationCurrency: 'CNY',
      destinationCountryCode: 'CHN',
      method: 'ALIPAY',
      beneficiary: {
        accountName: 'Li Wei',
        accountCurrency: 'CNY',
        alipayId: 'user@alipay.com',
        address: '123 Main St',
        city: 'Beijing',
        postCode: '100000',
      },
      narration: 'Payment for services',
      supportingDocument: 'https://example.com/invoice.pdf',
    }),
  }
);

const payout = await payoutResponse.json();
console.log(`Payout created: ID=${payout.id}, Status=${payout.status}`);

// 4. Save payout.id for tracking
const payoutId = payout.id; // Use this ID to track status

// 5. Check status (or subscribe to webhooks for real-time updates)
const statusResponse = await fetch(
  `https://gateway.staging.useyala.com/v1/payout-api/payouts/${payoutId}`,
  {
    headers: { 'x-api-key': apiKey }
  }
);
const status = await statusResponse.json();
console.log(`Current status: ${status.status}`);

Testing with Postman

Quick start: Import the ready-to-use Postman collection with all payout API endpoints pre-configured at https://docs.useyala.com/resources/postman.json.
The Postman collection includes:
  • All payout API endpoints (pairs, methods, wallets, quote, document upload-url, S3 PUT, initiate, get status, add documents)
  • A Supporting documents folder for upload-url, S3 PUT, and PATCH documents
  • Pre-configured headers (x-api-key, Idempotency-Key)
  • Scripts that save documentUrl and payoutId to collection variables
  • Example request bodies (initiate sample includes SWIFT-required beneficiary fields for the NGN to USD USA corridor)
Setup:
  1. In Postman, select Import and use https://docs.useyala.com/resources/postman.json
  2. Create environment with:
    • YALA_BASE_URL_LOCAL: https://gateway.staging.useyala.com/v1/payout-api/payouts (sandbox)
    • YALA_PAYOUT_API_KEY: Your API key
  3. Select the environment and start testing

Next steps

End-to-End Flow

Understand how to integrate payout APIs into your application.

Idempotency guide

Learn how to generate and use Idempotency-Key headers.

Get methods endpoint

Understand how to get rates and required fields.

Error handling

Handle validation failures and rate limiting gracefully.

Payout initiation

Review complete endpoint documentation.