List customers: filters and opt-in pagination
GET /customer now accepts optional exact-match filters and opt-in pagination so you can recover a single customer by identifier or page through large result sets.
- New filters:
email,id_number,registration_number,verification_status(PENDING/PROCESSING/VERIFIED/REJECTED), andtype(individual/business). All are scoped to your business and combine with each other. - Pass
?paginate=trueto receive a paginated envelope (data,links,meta) with 15 items per page. The paginated path returns results newest-first. - Backwards compatible. Omitting
paginatereturns the existing shape unchanged.
New: kyb_scope on business customers — Standard and Minimal KYB
Business customers now carry a kyb_scope field that picks
one of two onboarding paths:
FULL(Standard KYB) — business identity (name, registration number, country of incorporation), beneficial owners summing to 100% ownership, an ID file for each owner, plus a formation document. Eligible for NGN, USD, GBP, and EUR Virtual Bank Accounts.MINIMAL— same business identity as Full, without owners or per-owner ID files, plus a formation document. Eligible for NGN VBAs only.
Who can use Minimal: Minimal is gated by an admin-controlled
allow list — typically Nigerian platforms collecting payments in naira
for their own customers. Allow-listed platforms default to
MINIMAL when they don’t send kyb_scope, and
can pass FULL explicitly when they need non-NGN currencies.
Platforms not on the list default to FULL; sending
MINIMAL returns 422. Contact
support@blaaiz.com if your use
case is genuinely NGN-only.
Upgrading is one-way. UsePOST /customer//upgrade-kyb-scopeto promote a MINIMAL customer to FULL by
adding beneficial owners. There is no downgrade. After the upgrade,
upload owner ID files and call /submit to re-verify under
the Standard checks.
How businesses identify themselves. Every business
customer (Minimal or Full) identifies via
registration_number + incorporation_country.
The id_type and id_number fields are
individual-only — sending them on a business create or update returns
422.
Backwards compatibility. Existing business customers
(created before this release) are tagged kyb_scope=MINIMAL
and have their canonical identity columns backfilled from the legacy
ones. Their NGN VBAs continue to work; the legacy columns stay
populated for read-side compatibility. To enable non-NGN currencies
for an existing business customer, call the upgrade endpoint.
- Business customer KYB — Overview (Two paths section, what we check before /submit, upgrade flow).
- Onboarding a business customer (Minimal KYB onboarding section + Upgrading section).
- POST /customer//upgrade-kyb-scope — new endpoint reference.
Breaking: business-type customers now use a dedicated KYB flow
- You only create
type=individualcustomers — nothing changes. Continue using POST /file/get-presigned-url + POST /customer//files. That flow is unchanged. - You create
type=businesscustomers — yes, you must migrate. The legacyPOST /customer//fileswithid_file=<cert_of_inc>no longer triggers verification for business customers. The file is still stored, but our verification pipeline does not look at it for businesses, and/submitwill return422with a readiness error. - Your existing
VERIFIEDbusiness customers are untouched. They remainVERIFIEDand valid for every operation they were valid for before. You only need to migrate the flow you use to verify new business customers.
- Before (no longer works for business):
POST /customerwithtype=business,id_type=certificate_of_incorporation→ upload via/file/get-presigned-url→POST /customer//fileswithid_file. - Now:
POST /customerwithtype=business+business_name+registration_number+incorporation_country+ (optional)ownersarray (or add owners later viaPUT /customer/) → upload owner ID files viaPOST /customer//owner//file/presigned-urlandPOST /customer//owner//files→ register KYB documents viaPOST /customer//document/presigned-urlandPOST /customer//document→ finalize withPOST /customer//submit. - . Use
registration_number+incorporation_countryas the canonical identifier. Sendingid_typeorid_numberon atype=businesscreate or update returns422. Individuals continue to requireid_type+id_numberas before. - Uniqueness:
registration_numberis now unique within your business perincorporation_country— two of your business customers cannot share the same(registration_number, incorporation_country)pair. The same number across different incorporation countries is fine. - Country fields are explicit and split. A business
customer now carries three ISO alpha-2 country codes, each with a
distinct meaning:
incorporation_country— the legal jurisdiction the company is registered in. Top-level, business-only, required.country— the registered-address country. Top-level, required for both individuals and businesses. For businesses, must equalincorporation_country(a company’s registered office sits in its country of incorporation by company law). The cross-field check is enforced at validation time, including on update — when changing the jurisdiction, send both fields together.operating_country— the operating-address country, on KYC data. Business-only. Required whenever any otheroperating_*field is supplied. Can differ from the other two when the business operates from a different jurisdiction.
zip_codeagainstcountry,operating_zip_codeagainstoperating_country. Same rules acrossPOST /customer,PUT /customer/, andPOST /customer//kyc-data. - Type-specific fields are strictly scoped.
Sending fields that don’t apply to the customer’s
type(for example,operating_*ontype=individual, or business KYB fields on an individual) fails the entire request with422. Send only what applies. - . On
PUT /customer/, sending a property asnullwritesnullto the column. Omit the property to leave it unchanged. Applies to the customer object and to entries inside theownersarray. - The certificate-of-incorporation file goes into the new
KYB document collection (
type=CERTIFICATE_OF_INCORPORATION) instead of through/files.
Readiness floor that /submit enforces for business customers
(each returns 422 with a specific message; same checks
run on initial submit and on re-submit after a REJECTED
verdict):
- Customer-level identity —
business_name,registration_number, and a valid ISOincorporation_countryare all set;countryequalsincorporation_country. - At least one beneficial owner.
- . 99.99% won’t pass.
- Owner emails are unique within the customer (case-insensitive).
- Per-owner ID slot consistency — every owner has
id_document_front;drivers_license/id_card/resident_permitrequireid_document_back;passportmust not have a back image. - Per-owner identity invariants —
date_of_birthis at least 18 years ago,id_expiry_dateis strictly after today, and ISO codes (nationality,country,id_document_country) are valid alpha-2 where set. - At least one KYB document of a formation type:
CERTIFICATE_OF_INCORPORATION,ARTICLES_OF_INCORPORATION,BENEFICIAL_OWNERSHIP_CERTIFICATE,INCORPORATION_DOCUMENTS, orCAC_STATUS_REPORT.
Lock matrix. A child record (owner or document) is
locked if its own status is APPROVED or
PROCESSING, OR the parent customer is in
PROCESSING or VERIFIED. Edits to locked
records return 400. Wait for
customer.status_changed before attempting edits.
Editing a REJECTED owner or document
auto-resets it. Any field change or file replacement on a
previously-rejected owner or document flips its status
back to PENDING and clears its
admin_comments. The corrected record is re-routed
through review on the next /submit. Records that are
APPROVED stay locked and aren’t re-reviewed.
What’s new in the response shape. GET /customer/ now returns:
owners[]— beneficial owners with per-recordstatus(PENDING/PROCESSING/APPROVED/REJECTED) andadmin_comments(array of strings).APPROVEDandPROCESSINGowners are locked from edits.documents[]— KYB document collection with the samestatus+admin_commentsshape and the same lock semantics. Note: this replaces nothing — it is a new field on the customer.- On
customer.status_changedwithnew_status=REJECTEDfor a business customer, render each owner’s and each KYB document’sadmin_commentsentries to your end customer as separate bullets. Rejected items are editable;APPROVEDitems stay locked. Fix and call/submitagain to re-review only the items you changed.
Webhook contract.
customer.status_changed remains the single customer-level event;
you do not need to update your webhook handler. Inspect
old_status and new_status as before. Business
customers introduce one new new_status value:
PROCESSING, fired right after /submit. There are
no per-owner or per-document webhooks — the customer-level
event is the only signal.
Timeline expectations. Individual KYC remains a
minutes-to-2-hours process. Business KYB review typically takes
1–5 business days. Wait for
customer.status_changed; do not raise support tickets within
the standard window.
Currency eligibility. Verified business customers on
kyb_scope=FULL can hold NGN, USD, GBP, and EUR Virtual Bank
Accounts. kyb_scope=MINIMAL customers are NGN-only. For
payout-currency coverage on business recipients, contact support.
Read these before migrating: Business customer KYB overview, Onboarding a business customer (full curl walkthrough + a “Common mistakes” section that calls out the /files trap), Handling KYB rejections, and KYB FAQ.
PHP SDK Now Available
The official framework-agnostic PHP SDK for the Blaaiz Platform API is now available on Packagist. It handles authentication, request signing, and error handling out of the box.
- Install via Composer:
composer require blaaiz/blaaiz-php-sdk - Works with any PHP 8.1+ project — no framework dependency required.
- For Laravel-specific features, the Laravel SDK is also available.
See the SDKs page for all available SDKs.
Customer ID Now Required for All Virtual Bank Accounts
The customer_id field is now required when
creating a Virtual Bank Account for all currencies, including NGN. Previously,
NGN allowed creating accounts without a customer by passing an
account_name instead — this is no longer supported.
customer_idis now a required field in the Create Virtual Bank Account request for all currencies (NGN, GBP, EUR, USD).- The
account_namerequest parameter has been removed. - The customer must have
verification_statusofVERIFIEDbefore a Virtual Bank Account can be created.
Action required: If your integration creates NGN Virtual
Bank Accounts without a customer_id, you must update your
integration to create and verify a customer first.
Back ID Document Support for Customer Verification
The File API and Upload Files endpoint now support back-side identity document uploads for two-sided documents (e.g. driver’s license).
- Added
identity_backas a newfile_categoryoption in the File API presigned upload endpoint. - Added
id_file_backas a new optional parameter in the Upload Files for a Customer endpoint. - Back ID uploads are optional — only needed when the identity document has two sides. Single-sided documents (passport, certificate of incorporation) do not require a back upload.
- The
id_file(front ID) remains the verification trigger. Other files (back ID, liveness check, proof of address) can be uploaded before or alongsideid_filewithout triggering verification. - Rejected customers can now re-upload documents and resubmit for verification without requiring a manual reset.
- Uploads are now blocked while verification is actively in progress to prevent document mutation during review.
Granular OAuth Scopes and Credential Rotation
OAuth credentials now support granular scopes and scope bundles, giving integrators fine-grained control over API access.
- Added documentation for 21 individual OAuth scopes (e.g.
wallet:read,payout:create,webhook:write) and 6 scope bundles (e.g.full-access,read-only,payouts). - Added credential rotation guide — rotate credentials from the dashboard to change scopes or recover from a compromised secret.
- Webhook registration endpoint now returns a
signing_secretin the response. Store this securely to verifyx-blaaiz-signatureheaders. - Legacy API key creation is now disabled. Legacy API key authentication will be removed soon.
OAuth Authentication and Webhook Signing Secret
Blaaiz Platform API authentication is now documented around OAuth client credentials for integrations.
- Added OAuth token acquisition guidance for API access.
- Updated guides and API reference examples to use Bearer tokens instead of legacy API key headers.
- Clarified that webhook signature verification uses a dedicated
webhook
signing_secret, not an API credential secret. - Marked legacy API key usage as temporary and advised all integrators to switch fully to OAuth immediately.
Common Use Cases Guide
We added a new Common use cases guide that walks through the most popular patterns businesses build with the Blaaiz Platform API.
- Cross-border remittances — collect in one currency, pay out in another.
- Marketplace and platform payouts — disburse to sellers across countries.
- Payroll for distributed teams — pay employees in their local currency.
- Virtual accounts for deposit collection — issue dedicated accounts per customer.
- Crypto on/off-ramps — accept stablecoins and settle to fiat.
- B2B invoice and vendor payments — automate cross-border vendor payments.
Each use case includes a flow diagram, step-by-step integration guide, and links to the relevant API endpoints.
Merchant Redirect URL for Collections
The
Initiate Collection
endpoint now accepts an optional redirect_url parameter.
After payment authorization (e.g. 3DS for card collections or open
banking), the customer is automatically redirected to your specified
URL with transaction_id and status query
parameters appended.
- Only HTTPS URLs are accepted (max 2048 characters).
- If no
redirect_urlis provided, the existing default redirect behavior is used. - Query parameters are appended with the correct separator whether your URL already contains a query string or not.
Swap API Reference and Transaction Response Updates
We added documentation for the new
POST /api/external/swap endpoint so businesses can swap
funds between their own wallets.
We also updated the transaction reference to document the latest response shape returned by the API.
Other updates:
- Added the new
SwapAPI reference section and navigation entry. - Documented
type: SWAPas a supported filter on the transaction list endpoint. - Added
swap_detailsto both the list and show transaction response examples and schemas. - Added swap-specific error examples, including validation and access restriction responses.
Virtual Bank Accounts Guide & Payout Documentation Improvements
We added a new Virtual Bank Accounts guide that explains what Virtual Bank Accounts are, how to create them, and the prerequisites for each supported currency (NGN, GBP, EUR, USD).
We also expanded the Creating your first payout guide with currency-specific prerequisites and common error scenarios for NGN, GBP, USD, EUR, and CAD payouts.
Other updates:
- Updated the Virtual Bank Account creation response message to reflect the new “initiated” status wording.
- Added new Virtual Bank Account validation error examples to the Payout API reference.
- Added request examples for every supported currency and payout method (NGN, GBP, USD ACH, USD Wire, EUR, CAD Interac, and Crypto) to the Payout API reference.
New Blaaiz Platform API Documentation 🎉
Migrated to the new docs platform. It now features: a more intuitive navigation and a better search experience.
- A more intuitive navigation and a better search experience.
- An interactive playground for testing API endpoints.
- Refined API Reference layout and examples.

