Two verification modes, step-by-step flows, status transitions, and bulk operations.
KYC Verification Guide
Every user must be identity-verified before they can make a payment through UrbanPayX . This guide covers both verification modes, step-by-step flows, status transitions, and bulk operations.
Why verification is required
Open banking regulations require that payment recipients verify the identity of payers. UrbanPayX enforces this at the API level — the payment link endpoint will reject any request for a user who has not completed verification.
Two verification modes
UrbanPayX supports two approaches to identity verification. Choose based on whether you want UrbanPayX to handle verification or do it yourself.
| UrbanPayX KYC | External Attestation | |
|---|---|---|
| Mode value | urbanpayx_kyc | external_attestation |
| Who verifies | UrbanPayX (via hosted provider) | You (your own process) |
| User experience | User completes ID + liveness check on hosted page | You verify identity through your own process, then tell UrbanPayX |
| Status field | kyc_status | external_verification_status |
| Payment-eligible status | approved | verified |
| Best for | When you need compliant identity verification without building it yourself | When you already have a KYC process and want to bring your own verification results |
Your client account has a default verification mode. When you create a user without specifying verification_mode, it inherits the default. You can override the mode per user.
UrbanPayX KYC flow
This mode uses a hosted verification page where users upload identity documents and complete a liveness check.
Step 1 — Create the user
POST /api/v1/kyc/users
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
{
"email": "[email protected]",
"full_name": "Jane Smith",
"verification_mode": "urbanpayx_kyc"
}The user is created with kyc_status: none.
Step 2 — Initiate verification
POST /api/v1/kyc/verify
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
{
"email": "[email protected]",
"full_name": "Jane Smith",
"level_name": "id-and-liveness"
}Verification levels:
| Level | What it checks |
|---|---|
id-and-liveness | ID document upload + live selfie check |
id-only | ID document upload only |
idv-and-phone-verification | ID document + phone number verification |
The response includes a verification_url — this is a hosted page where the user completes the identity check. The link is valid for 7 days.
{
"user_id": "uuid",
"kyc_status": "pending",
"verification_url": "https://verification-provider.com/...",
"message": "KYC verification initiated"
}Step 3 — User completes verification
Send the verification_url to your user. They will upload their ID document and (for liveness checks) take a live selfie. This happens entirely on the hosted verification page — no integration work needed on your side.
Step 4 — Receive the result
When the verification is complete, UrbanPayX sends a kyc.status_changed webhook to your configured webhook URL:
{
"type": "kyc.status_changed",
"data": {
"user_id": "uuid",
"previous_status": "pending",
"current_status": "approved"
}
}You can also poll the status:
GET /api/v1/kyc/status/USER_IDStatus transitions
none --> pending --> approved
--> rejected
| Status | Meaning | Can generate payment link? |
|---|---|---|
none | No verification initiated | No |
pending | Verification in progress | No |
approved | Identity verified | Yes |
rejected | Verification failed | No |
If a user is rejected: The rejection is final for that verification attempt. You can check the reason and, if appropriate, initiate a new verification attempt.
If a user is already approved: Calling the verify endpoint returns the current approved status immediately without generating a new link.
External attestation flow
This mode lets you use your own identity verification process and report the result to UrbanPayX.
Step 1 — Create the user
POST /api/v1/kyc/users
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
{
"email": "[email protected]",
"full_name": "Jane Smith",
"verification_mode": "external_attestation"
}The user is created with external_verification_status: pending.
Step 2 — Verify the user through your own process
Run your own identity checks (document verification, database lookups, manual review — whatever your process requires).
Step 3 — Report the result
POST /api/v1/kyc/external/status/USER_ID
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
{
"status": "verified",
"provider": "your-kyc-provider",
"reference": "your-internal-ref-123",
"reason": "Identity verified via document check",
"payload": {
"document_type": "passport",
"verified_at": "2026-03-26"
}
}The provider, reference, reason, and payload fields are optional but recommended for your audit trail. All status changes are recorded in an audit log with the acting account ID and timestamp.
Status transitions
pending --> verified
--> rejected
| Status | Meaning | Can generate payment link? |
|---|---|---|
pending | Waiting for your attestation | No |
verified | You confirmed identity | Yes |
rejected | You rejected identity | No |
Switching verification modes
You can change a user's verification mode after creation:
PATCH /api/v1/kyc/users/USER_ID/verification-mode
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
{
"verification_mode": "external_attestation"
}The user retains their existing verification data for both modes. The system checks eligibility based on the active mode.
Bulk operations
For onboarding large numbers of users, UrbanPayX supports bulk endpoints.
Bulk create users
Create up to 500 users in a single request:
POST /api/v1/kyc/users/bulk
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
{
"users": [
{ "email": "[email protected]", "full_name": "User One" },
{ "email": "[email protected]", "full_name": "User Two", "verification_mode": "external_attestation" }
]
}The response reports per-item success or failure, supporting partial success:
{
"total": 2,
"succeeded": 2,
"failed": 0,
"results": [
{ "index": 0, "email": "[email protected]", "success": true, "user": {} },
{ "index": 1, "email": "[email protected]", "success": true, "user": {} }
]
}Bulk update external verification
Update verification status for up to 500 users at once (external attestation mode only):
POST /api/v1/kyc/external/status/bulk
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
{
"items": [
{
"user_id": "uuid-1",
"status": "verified",
"provider": "your-provider",
"reference": "ref-001"
},
{
"user_id": "uuid-2",
"status": "rejected",
"provider": "your-provider",
"reference": "ref-002",
"reason": "Document expired"
}
]
}This also supports partial success — individual items can fail (e.g., wrong verification mode) without blocking the rest.
Listing users
Retrieve all users with pagination:
GET /api/v1/kyc/lists?page=1&page_size=50
Authorization: Bearer YOUR_ACCESS_TOKENPayment eligibility summary
Before a payment link can be generated, the system checks the user's verification status based on their active mode:
| Mode | Allowed | Blocked (error code) |
|---|---|---|
urbanpayx_kyc | kyc_status = approved | KYC_REQUIRED (none or rejected), KYC_PENDING (pending) |
external_attestation | external_verification_status = verified | EXTERNAL_VERIFICATION_PENDING (pending), EXTERNAL_VERIFICATION_REJECTED (rejected) |
If you get a 400 error when generating a payment link, check the user's verification status first.
API endpoints reference
| Method | Path | Description |
|---|---|---|
| POST | /kyc/users | Create a single user |
| POST | /kyc/users/bulk | Bulk create users (max 500) |
| PATCH | /kyc/users/USER_ID/verification-mode | Switch verification mode |
| POST | /kyc/verify | Initiate UrbanPayX KYC verification |
| GET | /kyc/status/USER_ID | Get user verification status |
| GET | /kyc/lists | List all users (paginated) |
| POST | /kyc/external/status/USER_ID | Update external verification status |
| POST | /kyc/external/status/bulk | Bulk update external status (max 500) |
Related guides
- Core Concepts — How Users fit into the domain model
- Getting Started — End-to-end flow including user verification
- Error Reference — All KYC-related errors explained
- Roles and Permissions — Which roles can manage KYC