KYB Verification Guide
UrbanPayX verifies the businesses you register, either through its own hosted flow or by recording a result you obtained elsewhere. This guide covers both verification modes, step-by-step flows, status transitions, and resubmission.
The subject of every KYB flow is a business customer: a company record owned by your account, identified by company_name, registration_number, and country.
Why verify
AML rules generally require you to know which company you are moving money for. UrbanPayX gives you the verification tooling and stores the outcome, but it does not enforce it: no endpoint checks kyb_status. Where verification sits in your flow, and what you do with a rejected result, is your decision.
Two verification modes
Every business customer carries a verification_mode:
| Mode | What it means |
|---|---|
urbanpayx_kyb | UrbanPayX runs the check. You get a hosted verification link, the business submits its documents there, and the decision drives kyb_status. |
external_attestation | You verify the business yourself and report the outcome. UrbanPayX stores the status, provider label, and reference; it runs no check of its own. |
If you omit verification_mode on create, your account default applies. A business can only be acted on through the endpoint that matches its mode: initiating managed KYB on an external_attestation business, or posting an external status on a urbanpayx_kyb business, returns 400.
UrbanPayX KYB flow
Step 1 - Create the business customer
curl -X POST https://api-sandbox.urbanpayx.com/api/v1/kyb/businesses \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"company_name": "Example Trading SL",
"registration_number": "B12345678",
"country": "ESP",
"legal_address": "Calle Mayor 1, 28013 Madrid",
"tax_id": "ESB12345678",
"contact_email": "[email protected]",
"kyb_level": "standard"
}'company_name, registration_number, and country (ISO 3166-1 alpha-3) are required; everything else is optional. The call is idempotent on (registration_number, country): if the business already exists it is returned unchanged rather than duplicated.
kyb_level picks which set of checks runs. Call GET /kyb/levels for the keys available to your account, including any custom workflows you built. Omit it to use your account default.
Step 2 - Initiate verification
curl -X POST https://api-sandbox.urbanpayx.com/api/v1/kyb/verify \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"company_name": "Example Trading SL",
"registration_number": "B12345678",
"country": "ESP",
"callback_url": "https://yourapp.com/kyb/done",
"send_email": true
}'The endpoint takes the same identity fields as create and registers the business if it does not exist yet, so you can skip Step 1 for a brand-new business. The level comes from the business record (or your account default), not from this request.
{
"business_customer_id": "bc_...",
"kyb_status": "pending",
"verification_url": "https://verify.urbanpayx.com/...",
"message": "KYB verification initiated"
}verification_urlis the hosted link the business opens to submit documents. Calling the endpoint again while a verification is in progress returns the existing link instead of starting a second one.callback_urlis where the business is redirected when it finishes. It must be HTTPS. Omit it to use your account's default verification callback URL.send_email: trueemails the link to the businesscontact_emailfor you. Omit the field to use your account default.
Step 3 - The business completes verification
The business opens the link and submits its registry details and documents. Nothing is required from you during this step.
Step 4 - Receive the result
The decision arrives as a kyb.status_changed webhook. Two pull-based fallbacks exist for a missed webhook:
| Endpoint | Use it for |
|---|---|
GET /kyb/status/{business_id} | Current kyb_status and the latest verification link. |
GET /kyb/decision/{business_id} | The full decision, reconciling kyb_status on demand. |
GET /kyb/detail/{business_id} | The latest curated verification record (extracted company data and check outcomes). |
GET /kyb/detail/{business_id}/history | Every verification record for the business. |
GET /kyb/detail/{business_id}/documents/{file_role} | Download a document the business submitted. |
Status transitions
none --> pending --> approved
|
+----> rejected
approved --> on_hold (ongoing monitoring)
kyb_status | Meaning |
|---|---|
none | Created but verification not yet initiated. |
pending | A verification session is open; awaiting the decision. |
approved | The business passed. |
rejected | The business failed. |
on_hold | A previously approved business placed under review by ongoing monitoring. |
External attestation flow
Step 1 - Create the business
Same as above, with "verification_mode": "external_attestation".
Step 2 - Verify through your own process
Run whatever checks your compliance policy requires, with whichever provider you use.
Step 3 - Report the result
curl -X POST https://api-sandbox.urbanpayx.com/api/v1/kyb/external/status/bc_... \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "verified",
"provider": "your-provider-name",
"reference": "case-12345",
"reason": "Registry and UBO check passed"
}'status is pending, verified, or rejected and drives external_verification_status; kyb_status stays none for these businesses. provider, reference, reason, and a free-form payload object are optional and stored for your audit trail.
Switching verification modes
curl -X PATCH https://api-sandbox.urbanpayx.com/api/v1/kyb/businesses/bc_.../verification-mode \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"verification_mode": "external_attestation"}'Switching clears the verification source unless the business is already approved or verified, in which case the existing result is kept.
Editing and deactivating
PATCH /kyb/businesses/{business_id} updates company_name, legal_address, tax_id, and contact_email. Identity fields lock once the business has been verified, so a change to a locked field returns 409.
POST /kyb/businesses/{business_id}/deactivate soft-deletes the business (is_active=false) and requires a reason of at least 10 characters, recorded in your audit log. POST /kyb/businesses/{business_id}/activate reverses it. Both are restricted to OWNER.
Resubmission
When a verification fails on fixable steps (an unreadable document, a missing file), ask the business to redo just those steps on the same session instead of starting a new one:
curl -X POST https://api-sandbox.urbanpayx.com/api/v1/kyb/bc_.../resubmit \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"No body. Allowed while kyb_status is pending or rejected. The response returns session_url for the business to reopen and resubmit_steps listing what it must redo. Reusing the session means the resubmission is not billed as a second verification.
Listing businesses
curl "https://api-sandbox.urbanpayx.com/api/v1/kyb/businesses?page=1&page_size=20&effective_status=approved" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Filters: kyb_status, effective_status, verification_mode, external_verification_status, q (free-text search), and include_inactive. Use effective_status when you want one filter that covers both modes: it resolves external_attestation businesses to their external_verification_status. Deactivated businesses are excluded unless you pass include_inactive=true.
GET /kyb/summary returns counts per status for a dashboard tile.
Verification and payments
Payment initiation does not check verification state. A business whose kyb_status is none, pending, rejected, or on_hold can be paid for exactly like an approved one, and there is no verification-related error code on the payment endpoint.
If you want an approved-only policy, read kyb_status (or external_verification_status for externally attested businesses) and gate the call in your own code. The kyb.status_changed webhook is the cheapest way to keep that state fresh.
API endpoints reference
| Method | Path | Description |
|---|---|---|
| POST | /kyb/businesses | Create a business customer |
| GET | /kyb/businesses | List business customers (paginated) |
| PATCH | /kyb/businesses/{business_id} | Update a business's details |
| PATCH | /kyb/businesses/{business_id}/verification-mode | Switch verification mode |
| POST | /kyb/businesses/{business_id}/activate | Reactivate a business |
| POST | /kyb/businesses/{business_id}/deactivate | Deactivate a business |
| POST | /kyb/verify | Initiate UrbanPayX KYB verification |
| POST | /kyb/external/status/{business_id} | Report an external verification result |
| GET | /kyb/status/{business_id} | Get current verification status |
| GET | /kyb/decision/{business_id} | Full decision, reconciled on demand |
| GET | /kyb/detail/{business_id} | Latest curated verification record |
| GET | /kyb/detail/{business_id}/history | All verification records |
| GET | /kyb/detail/{business_id}/documents/{file_role} | Download a submitted document |
| POST | /kyb/{business_customer_id}/resubmit | Ask the business to redo failed steps |
| GET | /kyb/levels | List verification levels available |
| GET | /kyb/summary | Count businesses by verification status |
Related guides
- KYB Verification - endpoint-level reference, permissions, and error responses
- KYC Verification Guide - the same flows for individual users
- Custom Verification Workflows - build your own KYB level from modules
- Core Concepts - how businesses and verification fit in the domain model
- Error Reference - error codes across the API