SZNDSZND

Beneficiaries API

The Beneficiaries API allows you to create and manage payment recipients. Beneficiaries are required for withdrawals, transfers, and exchanges where funds need to be sent to external accounts.

Create Beneficiary

Create a new beneficiary for receiving payments. The required fields vary depending on the currency and country.

Endpoint

POST /api/v1/client/beneficiaries

Authentication

This endpoint requires HMAC authentication (Business API Key). Include your API key and signature in the request headers:

http
x-api-key: <your-api-key>x-timestamp: <RFC3339-timestamp>x-signature: <HMAC-signature>

Request Body

FieldTypeRequiredDescriptionExample
user_idstringYes (business API)Business API only. Which Transfaar user this beneficiary is created for. Use "self" or a customer UUID — see Business API: user_id."self" or a UUID
recipient_typestringNoRecipient type: individual (default) or business (corporate / company bank account)"business"
first_namestringConditionalRequired when recipient_type is individual (or omitted)"John"
last_namestringConditionalRequired when recipient_type is individual (or omitted)"Doe"
emailstringConditionalRequired for CAD Interac; otherwise optional"john.doe@example.com"
phonestringNoBeneficiary's phone number"+1234567890"
bank_namestringYesName of the bank"Access Bank"
account_numberstringConditionalBank account number (required for NGN)"0123456789"
bank_codestringNoBank code (from banks API)"044"
country_codestringYesISO 3166-1 alpha-2 country code"NG", "US", "CA"
currency_codestringYesCurrency code for the beneficiary"NGN", "USD", "CAD"
account_namestringConditionalAccount holder name. Required for business (company / trading name). Also required by GBP/EUR/USD corridor rules. For individuals on non-USD, auto-filled from first+last when omitted."Acme Ltd"
ibanstringNoIBAN for SEPA transfers"GB82WEST12345698765432"
bic_swift_codestringNoBIC/SWIFT code for international transfers"CHASUS33"
recipient_addressstringNoPhysical address of the recipient"123 Main St, Lagos"
notesstringNoAdditional notes about the beneficiary"Monthly salary payment"
routing_numberstringNoRouting number (US/Canada)"021000021"
account_typestringNoAccount type"Checking", "Savings"
payment_methodstringNoPayment method/rail"ACH", "Wire", "Sepa"
addressobjectNoStructured address objectSee Address Object below

Business (corporate) payees

Set recipient_type to "business" and provide the company name in account_name. Personal first_name / last_name are not required. Supported for GBP, EUR, USD, NGN, and CAD EFT.

Example (GBP corporate):

json
{  "user_id": "self",  "recipient_type": "business",  "account_name": "Acme Trading Ltd",  "bank_name": "Barclays",  "account_number": "12345678",  "sort_code": "200000",  "country_code": "GB",  "currency_code": "GBP",  "address": {    "street_1": "1 High Street",    "city": "London",    "state": "LND",    "postal_code": "SW1A 1AA",    "country": "GB"  }}

Then reference the returned id as beneficiary_id on your payout quote (with matching on_behalf_of / user_id).

Example (NGN corporate):

json
{  "user_id": "self",  "recipient_type": "business",  "account_name": "Acme Nigeria Ltd",  "bank_name": "Access Bank",  "account_number": "0123456789",  "bank_code": "044",  "country_code": "NG",  "currency_code": "NGN"}

Example (USD corporate ACH):

json
{  "user_id": "self",  "recipient_type": "business",  "account_name": "Acme USA Inc",  "bank_name": "Chase Bank",  "account_number": "123456789",  "routing_number": "021000021",  "account_type": "Checking",  "payment_method": "ACH",  "country_code": "US",  "currency_code": "USD",  "address": {    "street_1": "100 Main St",    "city": "San Francisco",    "state": "CA",    "postal_code": "94105",    "country": "US"  }}

Example (EUR corporate):

json
{  "user_id": "self",  "recipient_type": "business",  "account_name": "Acme Europe BV",  "bank_name": "ING",  "iban": "NL91ABNA0417164300",  "bic_swift_code": "INGBNL2A",  "country_code": "NL",  "currency_code": "EUR",  "payment_method": "Sepa",  "address": {    "street_1": "Damrak 1",    "city": "Amsterdam",    "state": "NH",    "postal_code": "1012LG",    "country": "NL"  }}
[blocked]

Business API: user_id (on behalf of)

POST /api/v1/client/beneficiaries is authenticated with your business API key. Every beneficiary is stored against a Transfaar user (the “on behalf of” user). That user must be part of your business.

You send user_idBehavior
"self" (recommended)Explicitly create the beneficiary for the business owner (the Transfaar user tied to your API key). Case-insensitive. Safer than omitting the field.
Customer UUIDThe beneficiary is created for that user. They must be the business owner, an active team member, or a registered customer linked to your business. Otherwise 400 with user_id does not belong to this business.
Omitted or emptyNot allowed for the business API — returns 400 asking for "self" or a customer id.

Tip: For a customer, pass their user id from the Customers API. For your business’s own recipients, pass "user_id": "self".

The user_id here must match the on_behalf_of you later pass on the quote — a quote is rejected when it pairs a customer with a beneficiary belonging to someone else. Pass "self" for both when the payout is your business's own.

Address Object (Optional)

When provided, address is validated. State is required (when the country has subdivisions) and must be a subdivision code only (e.g. NY, LA, ON)—subdivision names are not accepted for beneficiaries. Use Regions API to list valid codes.

country must be the country the address is actually in: postal_code and state are validated against that country's format and subdivision codes, not against the beneficiary's country_code. A UK address sent with "country": "NG" is rejected because WC2B 6UN is not a valid Nigerian postal code.

street_1 and street1 are both accepted (street_2/street2 likewise); responses return street1.

json
{  "street_1": "123 Main Street",  "city": "Lagos",  "state": "LA",  "postal_code": "100001",  "country": "NG"}

Currency-Specific Requirements

NGN (Nigerian Naira)

  • account_number is required
  • bank_code is recommended (use from Banks API)
  • bank_name is required
  • For corporate payees set recipient_type to "business" (company name in account_name)

USD (US Dollar)

  • payment_method is required (ACH, Wire, or Sepa)
  • For ACH: routing_number and account_number are required
  • For Wire: routing_number, account_number, and bic_swift_code are required
  • account_type is recommended (Checking or Savings)
  • For corporate payees set recipient_type to "business" (company name in account_name)

GBP (British Pound)

  • account_number, sort_code, bank_name, and account_name are required
  • address is required with street_1, city, postal_code, and country (GB for a UK address)
  • For corporate payees set recipient_type to "business" (company name in account_name)

EUR (Euro)

  • iban (or account_number), bank_name, and account_name are required
  • address is required
  • For corporate payees set recipient_type to "business"

INR (Indian Rupee)

Used for INR bank payouts (IMPS, NEFT, or RTGS). The payout quote is a same-currency WITHDRAWAL (INR to INR).

  • account_number is required — 6 to 34 alphanumeric characters
  • bank_code is required — 11-character IFSC (4 letters, 0, then 6 letters or digits), for example HDFC0001234
  • account_name is required — 1 to 120 characters
  • email is required — the beneficiary's own email
  • phone is required — 10-digit Indian mobile number (+91 is accepted)
  • country_code: IN
  • currency_code: INR

CAD (Canadian Dollar)

  • Interac e-Transfer: email is required — payout is delivered via Interac to the recipient's email. No bank account details needed.
  • Bank transfer (EFT): For crypto offramp and other bank-transfer payouts, set payment_method to "EFT" and provide account_number, bank_code (institution number), and routing_number (transit number). recipient_type is individual or business.

Crypto offramp fiat beneficiaries {#crypto-offramp-fiat-beneficiaries}

When converting stablecoin to fiat via Crypto offramp, register a standard bank beneficiary for the customer:

CurrencyRequired fields
GBPaccount_number, sort_code, account_name, country_code: GB; optional recipient_type: business
EURiban, bic_swift_code, account_name, country_code, payment_method: Sepa (or Wire where applicable); optional recipient_type: business
CAD (EFT)account_number, bank_code, routing_number, payment_method: EFT, recipient_type
USDACH/Wire fields as above; optional recipient_type: business
NGNaccount_number, bank_name; optional recipient_type: business

The beneficiary must belong to the same customer you pass as on_behalf_of on the offramp quote. Sznd maps a crypto deposit address to this fiat beneficiary — the address typically persists for that bank account, but amount and funding deadline are returned on each quote accept.

See Crypto offramp for the full integration flow.

TZS, UGX, SLE, LRD (Mobile money payout)

Mobile money beneficiaries use the same create endpoint. Payouts use the standard Fiat Payout flow (WITHDRAWAL or EXCHANGE) — no separate mobile-money payout API.

  • bank_code is required — must be a mobile money operator from the Banks API with ?type=momo (not a traditional bank code)
  • phone is required — recipient wallet number in international format without + (e.g. 255712345678 for Tanzania, 231771234567 for Liberia, 23276123456 for Sierra Leone)
  • bank_name is required — operator display name (e.g. MTN Mobile Money, Orange Money)
  • account_number is optional — if omitted, phone is used for payout delivery
  • country_code: TZ (TZS), UG (UGX), SL (SLE), LR (LRD)

Supported operators (current API catalog):

CountryCurrencyOperatorbank_codePhone prefix
KEKESM-PESA (Safaricom)mpesa254
KEKESAirtel Moneyairtel254
TZTZSTIGOTIGTZA255
TZTZSAIRTELAIRTZA255
TZTZSHALOTELHALTZA255
TZTZSVODACOM (M-PESA)VODTZA255
UGUGXMTN MOBILE MONEYMTNUGA256
UGUGXAIRTELAIRUGA256
SLSLEOrange MoneyORASLE232
SLSLEAfricell AfrimoneyAFRSLE232
LRLRDMTN Mobile MoneyMTNLBR231
LRLRDOrange MoneyORALBR231

Full list and updates: GET /banks/{country}?type=momo — see Banks API: mobile money operators.

List operators:

bash
curl -X GET "https://api.transfaar.com/api/v1/client/banks/TZ?type=momo" \  -H "x-api-key: <your-api-key>" \  -H "x-timestamp: <RFC3339-timestamp>" \  -H "x-signature: <HMAC-signature>"

Example: TZS mobile money beneficiary

json
{  "user_id": "self",  "first_name": "Amina",  "last_name": "Hassan",  "email": "amina.hassan@example.com",  "phone": "255712345678",  "bank_name": "HALOTEL",  "bank_code": "HALTZA",  "country_code": "TZ",  "currency_code": "TZS"}

GHS (Ghana)

Ghana supports mobile money and bank (GHIPSS) payouts. Use the Banks API type filter to load the correct list:

Payout typeBanks APIRequired beneficiary fields
Mobile moneyGET /banks/GH?type=momobank_code (operator), phone, bank_name
Bank accountGET /banks/GH?type=banksbank_code, account_number, bank_name

Supported mobile money operators (Ghana):

Operator (API name)bank_codePhone prefix (no +)
MTN MOBILE MONEYMTN233
VODAFONE CASHVOD233
AIRTELTIGO MONEYAIR233

For mobile money, use phone in international format without + (e.g. 233241234567).

Other Currencies

  • Requirements vary by country
  • Check specific country requirements in the Banks API documentation

Success Response (201 Created)

json
{  "id": "550e8400-e29b-41d4-a716-446655440000",  "user_id": "660e8400-e29b-41d4-a716-446655440001",  "first_name": "John",  "last_name": "Doe",  "email": "john.doe@example.com",  "phone": "+1234567890",  "bank_name": "Access Bank",  "account_number": "0123456789",  "bank_code": "044",  "country_code": "NG",  "currency_code": "NGN",  "status": "pending",  "is_verified": false,  "account_name": "John Doe",  "is_internal": false,  "created_at": "2024-01-15T10:30:00Z",  "updated_at": "2024-01-15T10:30:00Z"}

Error Responses

Status CodeDescription
400Bad Request - Missing required fields, invalid data, or validation errors. For the business API, includes user_id is required... when user_id is missing, user_id does not belong to this business for an invalid user, or user_id "self" is only valid for business API requests when a non-business caller sends "self".
401Unauthorized - Invalid or missing API credentials
409Conflict - Beneficiary already exists
500Internal Server Error

Example Request

bash
curl -X POST https://api.transfaar.com/api/v1/client/beneficiaries \  -H "Content-Type: application/json" \  -H "x-api-key: tf_test_biz_your_api_key" \  -H "x-timestamp: 2024-01-15T10:30:00Z" \  -H "x-signature: your_hmac_signature" \  -d '{    "user_id": "self",    "first_name": "John",    "last_name": "Doe",    "email": "john.doe@example.com",    "phone": "+2348012345678",    "bank_name": "Access Bank",    "account_number": "0123456789",    "bank_code": "044",    "country_code": "NG",    "currency_code": "NGN"  }'

For a registered customer, set "user_id" to that customer’s Transfaar user UUID instead of "self".

Example: JavaScript/Node.js

javascript
const crypto = require('crypto');
async function createBeneficiary(apiKey, secretKey, beneficiaryData) {  const timestamp = new Date().toISOString();  const body = JSON.stringify(beneficiaryData);  const dataToSign = body + '|' + timestamp;    const signature = crypto    .createHmac('sha256', secretKey)    .update(dataToSign)    .digest('hex');
  const response = await fetch('https://api.transfaar.com/api/v1/client/beneficiaries', {    method: 'POST',    headers: {      'Content-Type': 'application/json',      'x-api-key': apiKey,      'x-timestamp': timestamp,      'x-signature': signature    },    body: body  });
  return await response.json();}
// Usageconst beneficiary = await createBeneficiary(  'your-api-key',  'your-secret-key',  {    user_id: 'self',    first_name: 'John',    last_name: 'Doe',    email: 'john.doe@example.com',    phone: '+2348012345678',    bank_name: 'Access Bank',    account_number: '0123456789',    bank_code: '044',    country_code: 'NG',    currency_code: 'NGN'  });

List Beneficiaries

Retrieve a paginated list of beneficiaries for the authenticated business.

Endpoint

GET /api/v1/client/beneficiaries

Query Parameters

ParameterTypeDescriptionExample
page_idintegerPage number (default: 1)1
page_sizeintegerNumber of items per page (default: 10)20
currencystringFilter by currency code"NGN", "USD"
countrystringFilter by country code"NG", "US"
emailstringFilter by beneficiary email"john@example.com"
namestringSearch by beneficiary name"John"
user_idstring (UUID)Business API: Optional filter — only beneficiaries for this user. If provided, must be a user that belongs to your business (owner, team member, or customer); otherwise 400. Omit to list across all users under your business.Customer UUID
use_tagbooleanFilter for internal tag beneficiariestrue, false

Success Response (200 OK)

json
{  "data": [    {      "id": "550e8400-e29b-41d4-a716-446655440000",      "first_name": "John",      "last_name": "Doe",      "email": "john.doe@example.com",      "bank_name": "Access Bank",      "country_code": "NG",      "currency_code": "NGN",      "status": "verified",      "is_verified": true    }  ],  "pagination": {    "page_id": 1,    "page_size": 10,    "total": 25,    "total_pages": 3  }}

Get Beneficiary

Retrieve details of a specific beneficiary by ID.

Endpoint

GET /api/v1/client/beneficiaries/{id}

Path Parameters

ParameterTypeDescription
idUUIDBeneficiary ID

Success Response (200 OK)

Returns the full beneficiary object with all details.


Update Beneficiary

Update an existing beneficiary's information.

Endpoint

PATCH /api/v1/client/beneficiaries/{id}

Request Body

Same structure as create beneficiary, but all fields are optional. Only provided fields will be updated.


Delete Beneficiary

Delete a beneficiary. Beneficiaries that are associated with active transactions cannot be deleted.

Endpoint

DELETE /api/v1/client/beneficiaries/{id}

Success Response (200 OK)

json
{  "message": "Beneficiary deleted successfully"}

Related Endpoints


Best Practices

  1. Use Bank IDs - When creating beneficiaries, use the bank_code from the Banks API for better reliability
  2. Validate Accounts - Use the account lookup endpoint to verify account numbers before creating beneficiaries
  3. Handle Verification - Beneficiaries start with status: "pending" and may require verification depending on currency and amount
  4. Store Beneficiary IDs - Save the beneficiary id returned from create for use in quote/transaction requests