PayintoDocs

Transfers

Resolve a beneficiary, quote the fee, and send money.

A transfer has three steps: resolve the account, check the fee, then send. This module is called transfers.

Resolve the beneficiary

Find the bank code with GET /transfers/banks, then confirm the account name. Show the name to your user, or check it against your records, before you continue.

curl https://api.payinto.co/api/v1/business/transfers/resolve-account \
  --header "Authorization: Bearer $PAYINTO_SECRET_KEY" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{
    "bank_code": "058",
    "account_number": "0123456789"
  }'

Keep data.reference for the next steps:

{
  "status": "success",
  "message": "Account resolved successfully.",
  "timestamp": 1793404800000,
  "data": {
    "reference": "0196431c-6e02-7a44-8d1f-52b1c9e07a33",
    "bank_code": "058",
    "bank_name": "Guaranty Trust Bank",
    "account_name": "Ada Example",
    "alias": null,
    "account_number": "0123456789",
    "is_saved": false,
    "updated_at": "2026-10-31T09:00:00.000000Z",
    "bank_logo_url": null
  }
}

Quote the fee (optional)

POST /transfers/fee returns the total that will leave your account.

curl https://api.payinto.co/api/v1/business/transfers/fee \
  --header "Authorization: Bearer $PAYINTO_SECRET_KEY" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{
    "amount": 250000,
    "beneficiary_bank_code": "058"
  }'

Send the transfer

Send a merchant_reference so you can retry safely.

curl https://api.payinto.co/api/v1/business/transfers \
  --header "Authorization: Bearer $PAYINTO_SECRET_KEY" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{
    "resolved_account_reference": "0196431c-6e02-7a44-8d1f-52b1c9e07a33",
    "beneficiary_bank_code": "058",
    "beneficiary_account_number": "0123456789",
    "amount": 250000,
    "narration": "Vendor settlement",
    "merchant_reference": "payout-10002"
  }'

Confirm the outcome

A 200 means Payinto accepted the request, and the response has no final status. Call GET /transactions/tsq/{reference} to confirm it.

curl https://api.payinto.co/api/v1/business/transactions/tsq/payout-10002 \
  --header "Authorization: Bearer $PAYINTO_SECRET_KEY"

The transaction.debit.succeeded webhook confirms that your account was debited. It doesn't confirm that the money reached the beneficiary.

Choose the debit account

Transfers debit your main account by default. To use another account, send the same debit_account_id when you resolve, quote, and send.

Transfer to a Payinto Tag

To pay a Payinto user, resolve their tag first. POST /transfers accepts bank details only, so pass the resolved values to it.

curl https://api.payinto.co/api/v1/business/transfers/resolve-recipient \
  --header "Authorization: Bearer $PAYINTO_SECRET_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "recipient": "@tag_recipient" }'

Tags are case-insensitive, and the @ is optional. The response adds resolved_account_reference, display_tag, and business_name to the usual beneficiary fields.

StatusMeaning
404The tag doesn't exist in this environment.
422The tag is malformed, or the recipient has no receiving account.
400The debit account wasn't found, or bank resolution failed.

Common errors

StatusMessageFix
400Could not find the account.Check debit_account_id, and confirm the account belongs to this environment.
400Could not validate the account details.Check the bank code and account number.
409Duplicate merchant reference with a different payload.Use a new reference, or resend the original payload.
422Field errorsFix the fields listed in errors.

On this page