Skip to main content
21/05/2026

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), and type (individual / business). All are scoped to your business and combine with each other.
  • Pass ?paginate=true to receive a paginated envelope (data, links, meta) with 15 items per page. The paginated path returns results newest-first.
  • Backwards compatible. Omitting paginate returns the existing shape unchanged.
06/05/2026

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.

26/04/2026

Breaking: business-type customers now use a dedicated KYB flow

  • You only create type=individual customers — nothing changes. Continue using POST /file/get-presigned-url + POST /customer//files. That flow is unchanged.
  • You create type=business customers — yes, you must migrate. The legacy POST /customer//files with id_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 /submit will return 422 with a readiness error.
  • Your existing VERIFIED business customers are untouched. They remain VERIFIED and 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 /customer with type=business, id_type=certificate_of_incorporation → upload via /file/get-presigned-url POST /customer//files with id_file.
  • Now: POST /customer with type=business + business_name + registration_number + incorporation_country + (optional)owners array (or add owners later via PUT /customer/) → upload owner ID files via POST /customer//owner//file/presigned-url and POST /customer//owner//files → register KYB documents via POST /customer//document/presigned-url and POST /customer//document → finalize with POST /customer//submit.
  • . Use registration_number + incorporation_country as the canonical identifier. Sending id_type or id_number on a type=business create or update returns 422. Individuals continue to require id_type + id_number as before.
  • Uniqueness: registration_number is now unique within your business per incorporation_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 equal incorporation_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 other operating_* field is supplied. Can differ from the other two when the business operates from a different jurisdiction.
    Postal-code validation is anchored per address: zip_code against country, operating_zip_code against operating_country. Same rules across POST /customer, PUT /customer/, and POST /customer//kyc-data.
  • Type-specific fields are strictly scoped. Sending fields that don’t apply to the customer’s type (for example, operating_* on type=individual, or business KYB fields on an individual) fails the entire request with 422. Send only what applies.
  • . On PUT /customer/, sending a property as null writes null to the column. Omit the property to leave it unchanged. Applies to the customer object and to entries inside the owners array.
  • 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 ISO incorporation_country are all set; country equals incorporation_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_permit require id_document_back; passport must not have a back image.
  • Per-owner identity invariants date_of_birth is at least 18 years ago, id_expiry_date is 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, or CAC_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-record status (PENDING / PROCESSING / APPROVED / REJECTED) and admin_comments (array of strings). APPROVED and PROCESSING owners are locked from edits.
  • documents[] — KYB document collection with the same status + admin_comments shape and the same lock semantics. Note: this replaces nothing — it is a new field on the customer.
  • On customer.status_changed with new_status=REJECTED for a business customer, render each owner’s and each KYB document’s admin_comments entries to your end customer as separate bullets. Rejected items are editable; APPROVED items stay locked. Fix and call /submit again 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.

06/04/2026

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.

05/04/2026

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_id is now a required field in the Create Virtual Bank Account request for all currencies (NGN, GBP, EUR, USD).
  • The account_name request parameter has been removed.
  • The customer must have verification_status of VERIFIED before 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.

04/04/2026

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_back as a new file_category option in the File API presigned upload endpoint.
  • Added id_file_back as 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 alongside id_file without 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.
16/03/2026

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_secret in the response. Store this securely to verify x-blaaiz-signature headers.
  • Legacy API key creation is now disabled. Legacy API key authentication will be removed soon.
15/03/2026

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.
15/03/2026

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.

13/03/2026

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_url is 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.
13/03/2026

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 Swap API reference section and navigation entry.
  • Documented type: SWAP as a supported filter on the transaction list endpoint.
  • Added swap_details to both the list and show transaction response examples and schemas.
  • Added swap-specific error examples, including validation and access restriction responses.
03/03/2026

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.
09/01/2026

Added Virtual Account Closure Endpoint

We added a new endpoint that allows you to close a virtual account. This could be useful for when a user no longer needs a virtual account or when a virtual account is no longer needed.

Checkout thedocsfor more information.

25/12/2025

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.