Merchant onboarding & KYB
Before a merchant can process a single payment, acquiring rules require know-your-business (KYB) verification. You create the merchant with one API call; Finscale collects the verification data, runs the checks, and reports every state change as an event. This page walks the lifecycle from created to active — and what restricted and suspended mean when monitoring flags something.
The KYB lifecycle
Every merchant moves through one state machine, exposed as kyb_status on the Merchant object. Verification states move forward; under_review can bounce back to kyb_pending when the checks need more information, and monitoring can move an active merchant to restricted or suspended at any time.
kyb_status | Meaning | Can process? |
|---|---|---|
created | The record exists; no verification data yet. | No |
kyb_pending | Waiting on required information or documents from the merchant. | No |
under_review | Checks are running. May return to kyb_pending if more information is needed. | No |
active | Verified. Capabilities activate and a mid is assigned. | Yes |
restricted | Action required; some capabilities are paused until it's resolved. | Partially |
suspended | All activity paused — no payments, no payouts. | No |
Start onboarding
Create the merchant with its registered legal identity and a four-digit ISO 18245 merchant category code (MCC) describing its line of business. legal_name and country are fixed after creation — a different legal entity is a new merchant.
curl https://api.finscale.dev/v1/merchants \
-H "Authorization: Bearer sk_test_51FinscaleDemo…" \
-H "Idempotency-Key: idem_mch_aurora_01" \
-H "Content-Type: application/json" \
-d '{
"legal_name": "Aurora Retail B.V.",
"trading_name": "Aurora",
"country": "NL",
"mcc": "5734"
}'
# 201 Created
{
"id": "mch_7Rq3wN8dK2Vs",
"object": "merchant",
"legal_name": "Aurora Retail B.V.",
"trading_name": "Aurora",
"country": "NL",
"mcc": "5734",
"mid": null,
"kyb_status": "kyb_pending",
"capabilities": {
"card_payments": "pending",
"local_methods": "pending",
"payouts": "inactive"
},
"livemode": false,
"created_at": "2026-07-16T08:02:19Z"
}
The merchant comes back in kyb_status: kyb_pending with capabilities pending or inactive and no mid yet. From here, Finscale collects the required verification data and documents through hosted onboarding — you don't build document-upload flows or talk to registries. Track progress via merchant.updated events or by polling GET /v1/merchants/{id}.
What KYB verifies
The checks are the ones anti-money-laundering regulation and card-scheme rules require before an entity may accept payments:
- Legal existence. The entity is registered, in good standing, and
legal_namematches the registry of itscountryof incorporation. - Ownership. Ultimate beneficial owners (UBOs) and directors are identified and verified.
- Screening. The entity and its owners are screened against sanctions and watchlists — at onboarding and continuously afterwards.
- Line of business. What the merchant actually sells matches the declared
mccand is acceptable under scheme and provider rules. - Settlement account. The bank account that will receive payouts belongs to the verified entity.
Most merchants clear the checks without intervention. When a check can't complete automatically, the merchant returns to kyb_pending with a request for more information — each bounce fires a merchant.updated event, so your onboarding UI can react without polling.
Activation: MCC & MID
When the checks pass, kyb_status becomes active and two things happen:
-
The MCC is confirmed
You declare an
mccat creation; review validates it against the merchant's real line of business and corrects it if it's wrong — a mismatched MCC is a scheme-compliance problem, not a cosmetic one. Changingmcclater (via update) can send the merchant back tounder_review. -
A MID is provisioned
The merchant gets a
mid— its merchant id at the acquiring level. This is the identifier that appears in scheme clearing records and settlement reports, and it's how you tie a settlement line back to a specific merchant.midisnullin every state beforeactive.
Capabilities activate at the same time — usually together, but they can stagger: card_payments may go active while payouts stays pending on the bank-account check. Gate each feature of your product on its capability, not on kyb_status.
After activation: restricted & suspended
Verification doesn't end at active. Screening reruns continuously, registry data goes stale, and transaction monitoring watches live volume. When something needs attention, the merchant moves to restricted: the affected capabilities pause, and the dashboard shows exactly what's needed — an expired document, an ownership change to re-verify, activity that doesn't match the declared line of business. Resolve it and the merchant returns to active.
suspended is the severe case — confirmed sanctions hits, fraud findings, unresolved restrictions. All activity pauses: no payments, no payouts. Reinstatement goes back through review, not through a support ticket.
restricted merchant is one unresolved request away from suspended. Surface the required action to the merchant the moment the merchant.updated event arrives — waiting for them to notice a failed payout is the slow path.
Webhook events
Every change to kyb_status or a capability fires merchant.updated with the full Merchant object in its new state:
{
"id": "evt_5s8Y2kLmN0Ta",
"object": "event",
"type": "merchant.updated",
"created_at": "2026-07-18T14:11:47Z",
"livemode": false,
"data": {
"object": {
"id": "mch_7Rq3wN8dK2Vs",
"object": "merchant",
"kyb_status": "active",
"mid": "845512000318",
"capabilities": {
"card_payments": "active",
"local_methods": "active",
"payouts": "active"
}
}
}
}
data.object abridged — deliveries carry the complete Merchant object. Events are not ordered; derive state from the object, not from arrival sequence. See Webhooks → Ordering.
Error scenarios
| Scenario | Response |
|---|---|
Invalid mcc (not four digits) or country (not ISO 3166-1 alpha-2) |
400 — invalid_request_error |
| Retrieving or updating a merchant id that doesn't exist | 404 — invalid_request_error |
Reusing an Idempotency-Key with a different payload |
409 — idempotency_error |
Processing attempted for a merchant whose relevant capability isn't active |
400 — invalid_request_error; activate the capability first |
Field-by-field details of the object and every endpoint are on the Merchant API page; where the mid shows up downstream is covered in Settlement & payouts and Reconciliation.