skills/paystack-transfers/SKILL.md
Paystack Transfers API — send money to bank accounts and mobile wallets. Initiate single and bulk transfers, finalize OTP-verified transfers, list, fetch, and verify transfer status. Use this skill whenever implementing payouts, disbursements, vendor payments, withdrawal flows, or any feature that sends money from your Paystack balance to recipients. Also use when you see references to transfer_code, TRF_ prefixed codes, the /transfer endpoint, or need to handle transfer OTP verification.
npx skillsauth add rexedge/paystack paystack-transfersInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The Transfers API lets you send money from your Paystack balance to bank accounts and mobile wallets. Transfers require a pre-created transfer recipient.
Depends on: paystack-setup for the
paystackRequesthelper.
Related: paystack-transfer-recipients for creating recipients before transfers.
| Method | Endpoint | Description |
| --- | --- | --- |
| POST | /transfer | Initiate a transfer |
| POST | /transfer/finalize_transfer | Finalize transfer (OTP) |
| POST | /transfer/bulk | Initiate bulk transfer |
| GET | /transfer | List transfers |
| GET | /transfer/:id_or_code | Fetch a transfer |
| GET | /transfer/verify/:reference | Verify a transfer |
POST /transfer
Returns status pending if OTP is disabled on your account, or otp if OTP is required.
| Param | Type | Required | Description |
| --- | --- | --- | --- |
| source | string | Yes | balance (only option) |
| amount | integer | Yes | Amount in subunits (kobo/pesewas) |
| recipient | string | Yes | Recipient code (e.g. RCP_gd9vgag7n5lr5ix) |
| reference | string | Yes | Unique identifier (16-50 chars, lowercase a-z, 0-9, -, _) |
| reason | string | No | Reason for transfer (shows in customer's credit notification) |
| currency | string | No | Currency code (defaults to NGN) |
| account_reference | string | No | Required in Kenya for MPESA Paybill and Till transfers |
const transfer = await paystackRequest<{
transfer_code: string;
status: string;
reference: string;
amount: number;
}>("/transfer", {
method: "POST",
body: JSON.stringify({
source: "balance",
amount: 100000, // ₦1,000
recipient: "RCP_gd9vgag7n5lr5ix",
reference: `txf_${crypto.randomUUID()}`,
reason: "Vendor payment for January",
}),
});
// transfer.data.status → "pending" or "otp"
// transfer.data.transfer_code → "TRF_v5tip3zx8nna9o78"
POST /transfer/finalize_transfer
Required when transfer status is otp. Submit the OTP sent to your business phone.
| Param | Type | Required | Description |
| --- | --- | --- | --- |
| transfer_code | string | Yes | Transfer code from initiate response |
| otp | string | Yes | OTP sent to business phone |
await paystackRequest("/transfer/finalize_transfer", {
method: "POST",
body: JSON.stringify({
transfer_code: "TRF_v5tip3zx8nna9o78",
otp: "928783",
}),
});
POST /transfer/bulk
Batch multiple transfers in a single request. OTP must be disabled on your account to use this endpoint.
| Param | Type | Required | Description |
| --- | --- | --- | --- |
| source | string | Yes | balance |
| transfers | array | Yes | Array of transfer objects |
Each transfer object:
| Param | Type | Required | Description |
| --- | --- | --- | --- |
| amount | integer | Yes | Amount in subunits |
| recipient | string | Yes | Recipient code |
| reference | string | Yes | Unique reference (16-50 chars) |
| reason | string | No | Transfer reason |
const result = await paystackRequest("/transfer/bulk", {
method: "POST",
body: JSON.stringify({
source: "balance",
currency: "NGN",
transfers: [
{
amount: 20000,
recipient: "RCP_gd9vgag7n5lr5ix",
reference: `txf_${crypto.randomUUID()}`,
reason: "Bonus for the week",
},
{
amount: 35000,
recipient: "RCP_m7ljkv8leesep7p",
reference: `txf_${crypto.randomUUID()}`,
reason: "January salary",
},
],
}),
});
// result.message → "2 transfers queued."
GET /transfer
| Param | Type | Required | Description |
| --- | --- | --- | --- |
| perPage | integer | No | Records per page (default: 50) |
| page | integer | No | Page number (default: 1) |
| recipient | integer | No | Filter by recipient ID |
| from | datetime | No | Start date |
| to | datetime | No | End date |
const transfers = await paystackRequest("/transfer?perPage=20&page=1");
GET /transfer/:id_or_code
const transfer = await paystackRequest(
`/transfer/${encodeURIComponent("TRF_v5tip3zx8nna9o78")}`
);
GET /transfer/verify/:reference
Verify the status of a transfer using its reference.
const result = await paystackRequest(
`/transfer/verify/${encodeURIComponent(reference)}`
);
// result.data.status → "success" | "failed" | "pending" | "reversed"
// 1. Create recipient (see paystack-transfer-recipients skill)
// 2. Initiate transfer
const transfer = await paystackRequest("/transfer", {
method: "POST",
body: JSON.stringify({
source: "balance",
amount: 500000,
recipient: "RCP_gd9vgag7n5lr5ix",
reference: `txf_${crypto.randomUUID()}`,
}),
});
// 3. If OTP required, finalize
if (transfer.data.status === "otp") {
const otp = await getOTPFromUser();
await paystackRequest("/transfer/finalize_transfer", {
method: "POST",
body: JSON.stringify({
transfer_code: transfer.data.transfer_code,
otp,
}),
});
}
// 4. Listen for webhooks: transfer.success, transfer.failed, transfer.reversed
balance — ensure your Paystack balance has sufficient funds- and _ onlyaccount_reference in the transfertransfer.success, transfer.failed) rather than pollingdevelopment
Paystack webhook integration — signature validation with HMAC SHA512, event parsing, IP whitelisting, retry policy, and all supported event types. Use this skill whenever setting up a webhook endpoint for Paystack, validating x-paystack-signature headers, handling charge.success or transfer.success events, debugging webhook delivery failures, implementing idempotent event processing, or building any server-side Paystack event listener. Also use when encountering webhook timeout issues or needing the list of Paystack webhook IP addresses.
tools
Paystack Verification API — KYC verification tools for resolving bank accounts, validating account ownership, and looking up card BIN information. Use this skill whenever verifying bank account details before transfers, confirming account holder names, validating customer identity for compliance, looking up card brand/type/bank from BIN, or implementing KYC flows. Also use when you see references to /bank/resolve, /bank/validate, /decision/bin endpoints, or need to match account numbers to names.
development
Paystack Transfer Recipients API — create, list, fetch, update, and delete transfer recipients (beneficiaries) for payouts. Supports NUBAN (Nigeria), GHIPSS (Ghana), Mobile Money, BASA (South Africa), and authorization-based recipients. Use this skill whenever adding bank accounts or mobile wallets as payout destinations, creating transfer recipients before initiating transfers, managing beneficiary lists, or doing bulk recipient creation. Also use when you see references to recipient_code, RCP_ prefixed codes, or the /transferrecipient endpoint.
development
Paystack Transactions API — initialize payments, verify transactions, list/fetch transaction history, charge saved authorizations, view timelines, get totals, export data, and perform partial debits. Use this skill whenever building a checkout flow, verifying payment status, recharging a returning customer's saved card, pulling transaction reports or analytics, exporting transaction CSVs, or handling any transaction-related Paystack endpoint. Also use when you see references to /transaction/initialize, /transaction/verify, authorization_url, access_code, or charge_authorization in Paystack integrations.