Save a recipient

Name-checked, screened, and reusable — the way to pay a bank account twice.

A beneficiary is somewhere you pay, saved. It carries the name on the account, the account itself, the country and the currency, plus two things a raw destination on a payout can never have: what the rail said the account is called, and whether the recipient has cleared screening.

Beneficiaries are a dashboard session only, in both directions — an API key can neither read nor manage them. See Authentication.

Save one

curl -X POST https://sandbox.inversepay.app/api/b/v1/beneficiaries \
  -H "Authorization: Bearer $INVERSEPAY_SESSION_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Rwanda Metal Works — settlement",
    "full_name": "Rwanda Metal Works Ltd",
    "type": "bank",
    "account_identifier": "00040100123456789",
    "bank_name": "Banque de Kigali",
    "currency": "RWF",
    "country_code": "RW"
  }'
Field
labelrequiredWhat you call them. Shown in lists; ours to display, never to match on.
full_namerequiredThe name on the account. This is what gets checked.
typerequiredmobile_money, bank or card.
account_identifierrequiredThe wallet number, account number or card token.
currencyrequiredThree letters.
country_coderequiredTwo letters.
bank_nameoptional
destinationoptionalAnything else the rail needs, in the same open shape a payout takes.

A wallet is the same call with "type": "mobile_money" and the number as the account_identifier:

A mobile money recipient
curl -X POST https://sandbox.inversepay.app/api/b/v1/beneficiaries \
  -H "Authorization: Bearer $INVERSEPAY_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Aline — payroll",
    "full_name": "Aline Uwase",
    "type": "mobile_money",
    "account_identifier": "+250788123456",
    "currency": "RWF",
    "country_code": "RW",
    "destination": { "network": "MTN" }
  }'

Saving the same account twice is a 409. Pay the one you have rather than creating a second, which would carry its own separate screening state.

The response is the interesting part

201 Created
{
  "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "label": "Rwanda Metal Works — settlement",
  "full_name": "Rwanda Metal Works Ltd",
  "type": "bank",
  "currency": "RWF",
  "country_code": "RW",
  "account_identifier": "00040100123456789",
  "bank_name": "Banque de Kigali",
  "validation_status": "unavailable",
  "account_name_returned": null,
  "screening_status": "pending",
  "payable": false,
  "archived_at": null,
  "created_at": "2026-08-14T09:02:11Z"
}

Two fields decide whether money can move, and payable is the one to read. It is the single gate: the payout path and the dashboard both compute it the same way, so they cannot disagree about it.

validation_status — is this account called what you think?

We ask the rail who owns the account and compare it to full_name.

ValueMeaning
matchedThe rail's name and yours agree.
partialClose, not exact. Worth a human glance.
mismatchThey differ. Somebody else owns this account.
unavailableWe could not check — the rail has no lookup, or it did not answer.
uncheckedNot checked yet.

unavailable is not a mismatch and is never reported as one. "We could not check" and "the names differ" are different facts, and a business shown the second when the first is true stops trusting the check.

Whatever the rail said is in account_name_returned, verbatim. If you are disputing a mismatch you need the other name, not our verdict on it.

This does not block a payout. A mismatch is a warning; acting on it is yours.

screening_status — may money move at all?

Valuepayable
unscreenedno
pendingno
hitno — on a sanctions list
clearyes
cleared_after_reviewyes — a person judged a hit a false positive
blockedno, permanently — a person confirmed the hit

Screening fails closed. Anything other than clear or cleared_after_review does not pay, and that includes unscreened and pending: not having looked is not a clean result, and the first payout to a new recipient is exactly when that matters.

Clearing a recipient for payment

A beneficiary sitting at pending or hit is waiting on a person. They are in the review queue:

curl https://sandbox.inversepay.app/api/b/v1/beneficiaries/review-queue \
  -H "Authorization: Bearer $INVERSEPAY_SESSION_TOKEN"

Clearing one is the Owner's alone — it is the one action that turns "this may not be paid" into "this may":

curl -X POST https://sandbox.inversepay.app/api/b/v1/beneficiaries/$BENEFICIARY_ID/clear \
  -H "Authorization: Bearer $INVERSEPAY_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "note": "Known supplier since 2023. Name matches the contract." }'

The note is kept. An auditor reading this later needs to know what the reviewer believed, not just that somebody clicked.

Clearing only works from pending or hit. Clearing something never flagged would be a way to mark a beneficiary reviewed without anybody reviewing them.

The opposite decision is /block, which is permanent, and /archive, which retires a recipient without deleting them — deleting would take the screening history with it and leave every payout already made to them pointing at nothing.

Paying one

curl -X POST https://sandbox.inversepay.app/api/b/v1/payouts \
  -H "Authorization: Bearer $INVERSEPAY_SESSION_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "invoice-8821-settlement",
    "amount_minor": 240000000,
    "currency": "RWF",
    "method": "bank",
    "transaction_type": "b2b",
    "beneficiary_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
  }'

The name, country and destination come from the beneficiary. Send any of them yourself and yours wins.

A payout to a beneficiary that is not payable is a 409, and the response says which screening status refused it. The check runs again at payout time, not only when the recipient was saved: lists change, and somebody cleared in March can be listed in June.

Then what

On this page