Payout Beneficiaries
A payout beneficiary is a pre-screened payout recipient. You register the destination once, CrissCross runs two independent pre-acceptance checks against it — account verification with the receiving network and AML pre-screening — and from then on you reference the beneficiary by payoutBeneficiaryId on every payout instead of re-sending the full account details.
This keeps sensitive account data out of repeat requests, surfaces invalid or sanctioned destinations before money moves, and lets you build dashboards over the recipients a merchant has approved.
When to Use a Payout Beneficiary
Use a payout beneficiary when:
- You expect to pay the same recipient more than once
- You want destination validity confirmed before initiating a payout (e.g. before debiting the merchant balance)
- You want a stable, audit-friendly handle for a recipient
Pass recipient inline on the payout request instead when:
- It’s a one-off payout you don’t expect to repeat
- You don’t need (or want) pre-validation before initiating
Both flows are supported. payoutBeneficiaryId and recipient are mutually exclusive — supply exactly one on Initiate Payout.
Supported Destination Types
A beneficiary uses the same recipient shape as a payout. The type discriminator selects the destination:
Both bank_account and mobile_money flow through the same internal AccountValidationService, so they share the same lifecycle, the same verifications.accountVerification surface, and the same accept / reject signal behaviour.
Pre-acceptance Checks
Every beneficiary runs two independent checks while it is in pending_review. Both must clear before the beneficiary transitions to approved; either can independently block.
Account verification
CrissCross verifies the destination with the receiving network. For mobile money that’s the carrier confirming the MSISDN belongs to a live wallet under the supplied account name; for bank accounts it’s the partner bank-verification provider (e.g. Flutterwave for NGA Access Bank). The outcome surfaces on verifications.accountVerification:
VERIFIED— the network confirmed the destination and the returned name matched.PARTIAL_MATCH— the network confirmed the destination but returned an account holder name that differs from the merchant-submitted name. The differing name is exposed asreturnedAccountHolderNameso the merchant can compare them side-by-side. The beneficiary stays inpending_reviewuntil cleared viasignal.NOT_VERIFIED— the network could not locate the account, or rejected it. The beneficiary moves torejected.PENDING— verification has not completed yet.
AML pre-screening
In parallel, CrissCross screens the beneficiary’s name (and identifying details where supplied) against sanctions lists (OFAC, UN, EU, UK), PEP lists, and internal risk lists.
- A clear-cut hit moves the beneficiary to
rejectedwith an AML-specific reason. - A possible hit holds the beneficiary in
pending_reviewwithverifications.amlScreening.state: REVIEW. CrissCross’s compliance team reviews the hold in our screening provider’s tooling and clears or declines it there — the decision is not merchant-actionable, andaccept/rejectagainst an AML hold returns422. The merchant simply waits; the beneficiary moves toapprovedonce compliance clears it, or torejectedif compliance declines.
Use signal: retry to re-run both checks if either had a transient error.
Lifecycle
A beneficiary moves through this lifecycle:
Beneficiaries are immutable after creation. To change any field — MSISDN, account number, account name, anything — create a new beneficiary. There is intentionally no PATCH / PUT.
Creating a Beneficiary
POST /v1/payout-beneficiaries
The request body carries merchantId, a merchant-side merchantReference (persisted and round-tripped on every read), and the recipient (same shape as on Initiate Payout).
Mobile Money
Response (201):
Poll Retrieve Payout Beneficiary (or subscribe to webhooks once available) until status is approved before referencing the beneficiary on a payout.
Bank Account
Bank accounts run the same verification path as mobile money: any applicable internal format rules first (e.g. NUBAN check-digit for NGA), then the partner bank-verification provider. The verification outcome surfaces on verifications.accountVerification exactly like mobile money.
Duplicate Handling
The API soft-blocks duplicate creates. If you submit a beneficiary whose identifying details match one you already own, you get back 409 Conflict with the existing payoutBeneficiaryId:
In almost every case the right thing to do is reuse the returned ID. If you genuinely need a second record (for example, the previous one was rejected and you want a fresh verification attempt under a new ID), resend with allowDuplicate: true:
Using a Beneficiary on a Payout
Once the beneficiary is approved, reference it from Initiate Payout using payoutBeneficiaryId instead of recipient:
payoutBeneficiaryId and recipient are mutually exclusive — supply one or the other. A payout that references a non-approved beneficiary is rejected with 422.
Signals — Manual Lifecycle Transitions
POST /v1/payout-beneficiaries/{payoutBeneficiaryId}/signal
Signals let the merchant clear a name-mismatch hold or re-run the pre-acceptance checks after a transient failure.
accept and reject are merchant-facing decisions about the account-name verification only (the data the merchant submitted, compared to what the receiving network returned). They are not valid against an AML compliance hold.
AML screening decisions are made by CrissCross’s compliance team in our screening provider’s tooling — never by the merchant. When a beneficiary is in compliance review (verifications.amlScreening.state: REVIEW), the merchant waits; sending accept or reject against that hold returns 422 INVALID_SIGNAL_FOR_STATUS. retry remains valid and re-runs both checks.
A beneficiary held on a partial account-name match looks like this when retrieved:
The merchant compares recipient.accountHolderName against verifications.accountVerification.returnedAccountHolderName and signals:
For a transient failure:
Returns 200 with the updated beneficiary. Sending a signal that isn’t valid for the current status (e.g. retry on an already-approved beneficiary) returns 422.
Listing and Retrieval
GET /v1/payout-beneficiaries?merchantIds=<id>[,<id>...]&status=<status>— list beneficiaries across one or more merchants the caller has access to, optionally filtered by status.GET /v1/payout-beneficiaries/{payoutBeneficiaryId}— fetch a single beneficiary. Returns404if it doesn’t exist or isn’t owned by the caller.
List responses are an envelope of payoutBeneficiaries:
Best Practices
- Reuse, don’t recreate. A duplicate
409is telling you the beneficiary already exists — store the returned ID and use it. - Wait for
approved. Don’t reference apending_review,failed, orrejectedbeneficiary on a payout. The payout will be rejected. - Treat beneficiaries as immutable. Account details changed? Create a new beneficiary and update your local mapping.
- Show
returnedAccountHolderNameon partial matches. Surface it in your UI alongside the submitted name so a human canaccept/rejectwith full context. - Don’t gate your UX on AML compliance reviews. Compliance reviews can take hours to days, are decided by CrissCross’s compliance team in our screening provider’s tooling, and are not merchant-actionable. Show “Under compliance review — we’ll update you” rather than offering Accept/Decline buttons.
- Use
signal: retryfor transient failures. If verification errored because the provider was down,retryre-runs both checks without creating a new record.
For full request/response details, see the Payout Beneficiaries API Reference.