Use this recipe to push funds to beneficiaries such as drivers, vendors, or partners. Payouts share the same aggregator credentials you use for pay-ins.
Prerequisites
{{aggregator_id}} and {{secret_key}}
- Beneficiary IBAN validated with the account validation utilities
- Webhook endpoint ready to receive payout status updates
Flow summary
Call the payout endpoint
Send POST /v1/aggregators/{{aggregator_id}}/payout with a unique request_id, the payout amount (string, in PKR), and the beneficiary creditor_iban.
Track completion
Listen for webhook notifications or poll GET /v1/aggregators/{{aggregator_id}}/payments to confirm settlement and update ledgers.
Set {{base_url}} to https://dev.api.getsafepay.com/raastwire in Sandbox or https://api.getsafepay.com/raastwire in Production.
Payouts
Request Fields
API Example
Sample Response
UUID that keeps payout submissions idempotent.
Amount in PKR represented as a string (for example, "200" = PKR 200).
Beneficiary IBAN that will receive the funds.
curl --request POST "{{base_url}}/v1/aggregators/{{aggregator_id}}/payout" \
--header "X-SFPY-AGGREGATOR-SECRET-KEY: {{secret_key}}" \
--header "Content-Type: application/json" \
--data '{
"request_id": "{{request_id}}",
"amount": "200",
"creditor_iban": "PK25ALFH0216001008658216"
}'
const baseUrl = '{{base_url}}';
const aggregatorId = '{{aggregator_id}}';
const secretKey = '{{secret_key}}';
const payoutResponse = await fetch(
`${baseUrl}/v1/aggregators/${aggregatorId}/payout`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-SFPY-AGGREGATOR-SECRET-KEY': secretKey,
},
body: JSON.stringify({
request_id: crypto.randomUUID(),
amount: '200',
creditor_iban: 'PK25ALFH0216001008658216',
}),
},
);
if (!payoutResponse.ok) {
const error = await payoutResponse.json();
throw new Error(`Payout failed: ${payoutResponse.status} ${error.message}`);
}
type CreatePayoutPayload = {
api_version: string;
data: {
token: string;
status: 'P_INITIATED' | 'P_RECEIVED' | 'P_FAILED' | 'P_REJECTED' | 'P_SETTLED';
amount: string;
request_id: string;
trace_reference?: string;
msg_id?: string;
created_at: string;
};
};
const payoutPayload: CreatePayoutPayload = await payoutResponse.json();
console.log('Payout token', payoutPayload.data.token);
{
"api_version": "v1",
"data": {
"token": "pm_2a8c2cfc-e61d-431e-a850-f1808405ca07",
"status": "P_INITIATED",
"amount": "200",
"request_id": "{{request_id}}",
"trace_reference": "2005867c-752f-430f-8619-a4c998423e3d",
"msg_id": "QAI8456FZ5NOR5H6ITEVK2U2NCD7POCSKQS",
"created_at": "2025-10-02T06:03:11Z"
}
}
Webhook events to expect
Refer to the webhooks delivery guide for the full event catalog. Settlement-related events are emitted as batch processing progresses.
Failure handling checklist
- Inspect webhook payloads for failure reasons (insufficient funds, invalid account, compliance hold).
- Retry transient errors with the same
request_id to stay idempotent.
- Raise manual review tasks for permanent failures and notify beneficiaries.
See also