Your First Payout
In this tutorial you'll send your first payout through NextAPI — from checking your balance, to creating a payout request, to receiving confirmation.
Time: ~10 minutes Prerequisites: Sandbox credentials from /sandbox. Complete Your First API Call first if you haven't verified your auth yet.
What you'll build
By the end of this tutorial you'll have:
- Checked your account balance in the sandbox
- Sent a payout to a test bank account
- Checked the payout status
- Understood the payout lifecycle
Step 1: Get your account ID
Your account UUID is shown in your NextAPI sandbox credentials at /sandbox. Use it directly as source_account_id in the payout request.
Step 2: Check your balance
Before sending a payout, confirm the account has available funds. In sandbox, accounts start with test funds pre-loaded.
- cURL
- Node.js
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
"https://api.partners.nextpay.world/v2/accounts/YOUR_ACCOUNT_UUID/balances"
const response = await fetch(
'https://api.partners.nextpay.world/v2/accounts/YOUR_ACCOUNT_UUID/balances',
{
headers: {
'Authorization': 'Basic ' + Buffer.from('YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').toString('base64'),
},
}
);
const balance = await response.json();
console.log(`Available: PHP ${(balance.available / 100).toFixed(2)}`);
{
"available": 10000000,
"pending": 0,
"reserved": 0,
"currency": "PHP"
}
10000000 centavos = PHP 100,000.00. Only available funds can be disbursed.
Step 3: Send a payout
Create a payout request to send PHP 100.00 (10000 centavos) to a test BPI account:
- cURL
- Node.js
- Python
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-X POST "https://api.partners.nextpay.world/v2/payout-requests" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: tutorial-payout-001" \
-d '{
"source_account_id": "YOUR_ACCOUNT_UUID",
"external_id": "tutorial-payout-001",
"amount_cents": 10000,
"currency": "PHP",
"settlement_rail": "instapay",
"status": "published",
"settlement_account": {
"bank_account_name": "Test Recipient",
"bank_account_number": "1234567890",
"bank_code": "BOPIPHMMXXX"
},
"description": "My first payout"
}'
const response = await fetch('https://api.partners.nextpay.world/v2/payout-requests', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from('YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').toString('base64'),
'Content-Type': 'application/json',
'X-Idempotency-Key': 'tutorial-payout-001',
},
body: JSON.stringify({
source_account_id: 'YOUR_ACCOUNT_UUID',
external_id: 'tutorial-payout-001',
amount_cents: 10000, // PHP 100.00
currency: 'PHP',
settlement_rail: 'instapay',
status: 'published',
settlement_account: {
bank_account_name: 'Test Recipient',
bank_account_number: '1234567890',
bank_code: 'BOPIPHMMXXX',
},
description: 'My first payout',
}),
});
const payoutRequest = await response.json();
console.log('Payout Request ID:', payoutRequest.id);
console.log('Status:', payoutRequest.status);
import requests
import base64
credentials = base64.b64encode(b'YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').decode()
response = requests.post(
'https://api.partners.nextpay.world/v2/payout-requests',
headers={
'Authorization': f'Basic {credentials}',
'Content-Type': 'application/json',
'X-Idempotency-Key': 'tutorial-payout-001',
},
json={
'source_account_id': 'YOUR_ACCOUNT_UUID',
'external_id': 'tutorial-payout-001',
'amount_cents': 10000, # PHP 100.00
'currency': 'PHP',
'settlement_rail': 'instapay',
'status': 'published',
'settlement_account': {
'bank_account_name': 'Test Recipient',
'bank_account_number': '1234567890',
'bank_code': 'BOPIPHMMXXX',
},
'description': 'My first payout',
}
)
payout_request = response.json()
print(f"Payout Request ID: {payout_request['id']}")
print(f"Status: {payout_request['status']}")
Response
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"source_account_id": "YOUR_ACCOUNT_UUID",
"amount_cents": 10000,
"currency": "PHP",
"status": "published",
"external_id": "tutorial-payout-001",
"description": "My first payout",
"settlement_rail": "instapay",
"settlement_account": {
"bank_account_name": "Test Recipient",
"bank_account_number": "1234567890",
"bank_code": "BOPIPHMMXXX"
},
"created_at": "2025-11-15T10:30:00Z"
}
status: "published" — the payout has been submitted and is queued for processing. It's not instant.
Step 4: Check the payout status
Poll the payout request to see when it completes:
- cURL
- Node.js
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
"https://api.partners.nextpay.world/v2/payout-requests/YOUR_PAYOUT_REQUEST_UUID"
const response = await fetch(
'https://api.partners.nextpay.world/v2/payout-requests/YOUR_PAYOUT_REQUEST_UUID',
{
headers: {
'Authorization': 'Basic ' + Buffer.from('YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').toString('base64'),
},
}
);
const payoutRequest = await response.json();
console.log('Status:', payoutRequest.status);
In sandbox, payouts simulate real processing time. Check again after a few seconds and you should see:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "queued",
...
}
Step 5: Understand the status progression
A payout request moves through these states:
published → queued → processed (success)
↘ rejected (terminal failure)
↘ queue_failed (terminal failure)
↘ processing_failed (terminal failure)
| Status | Meaning |
|---|---|
published | Submitted, awaiting processing |
authorization_pending | Awaiting internal authorization |
authorized | Authorized, queued for settlement |
queued | Picked up by the settlement rail |
processed | Bank confirmed receipt — done ✓ |
rejected | Rejected before processing — terminal ✗ |
canceled | Canceled — terminal ✗ |
queue_failed | Failed to enter the settlement rail — terminal ✗ |
processing_failed | Settlement attempted but failed — terminal ✗ |
In production, InstaPay payouts typically reach processed in under 30 seconds. PESONet payouts complete at the next batch cutoff (10 AM or 3 PM Manila time).
For any terminal failure state, funds reserved for the payout are returned to your available balance.
What's next?
You've sent your first payout. Here's where to go from here:
- Handle failures gracefully: Handle Payout Failures — error classification, retry strategies
- Send to many recipients: Run Mass Payroll — batch payout API
- Get notified in real time: Setup Webhooks — instead of polling
- Understand the lifecycle: Payout Lifecycle — full state machine