KYC / KYB
The KYC / KYB (Know Your Customer / Know Your Business) capability verifies the identity of agents, humans, and businesses participating in the ItPay ecosystem. Verification levels gate payment limits — higher levels unlock higher transaction amounts, more payment channels, and lower fees.
Swimlane Diagram — Identity Verification Flow
┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────┐
│ Human │ │ Agent │ │ ItPay │ │ Channel │
│ (Payer) │ │ (Buyer) │ │ Protocol │ │ (Alipay) │
└────┬─────┘ └──────┬───────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
│ (1) Initiate │ │ │
│ KYC Upgrade │ │ │
│ ─────────────────▶ │ │
│ "I want to │ │ │
│ increase my │ │ │
│ payment limit │ │ │
│ to $100/transaction" │ │
│ │ │ │
│ │ (2) POST /v1/kyc/verify │
│ │ ─────────────────▶ │
│ │ { level: "basic", │
│ │ data: { email, phone } } │
│ │ │ │
│ │ │ (3) OTP │
│ (4) Receive OTP │ │ Challenge │
│ ◄────────────────│◄─────────────────│ │
│ "Enter the 6-digit code │ │
│ sent to your phone/email" │ │
│ │ │ │
│ (5) Submit OTP │ │ │
│ ─────────────────▶ │ │
│ │ (6) Forward │ │
│ │ OTP + Verify │ │
│ │ ─────────────────▶ │
│ │ │ │
│ │ │ (7) Channel │
│ │ │ KYC Check │
│ │ │ ───────────────▶
│ │ │ │
│ │ │ ◄──────────────│
│ │ │ Alipay L1 OK │
│ │ │ │
│ │ (8) 201 Created │ │
│ │ ◄────────────────│ │
│ │ { status: │ │
│ │ "pending" } │ │
│ │ │ │
│ │ (9) Webhook: │ │
│ │ kyc.verified │ │
│ │ ◄────────────────│ │
│ │ │ │
│ (10) Confirmed │ │ │
│ ◄────────────────│ │ │
│ "You're now at │ │ │
│ Level 1 — │ │ │
│ you can pay up │ │ │
│ to $100/transaction!" │ │
│ │ │ │
Level Upgrade (L1 → L2 → L3)
┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────┐
│ Human │ │ Agent │ │ ItPay │ │ Channel │
│ (Payer) │ │ (Buyer) │ │ Protocol │ │ (Alipay) │
└────┬─────┘ └──────┬───────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
│ L1→L2 Upgrade │ │ │
│ ─────────────────▶ │ │
│ "I need to pay │ │ │
│ $500 for a │ │ │
│ subscription" │ │ │
│ │ │ │
│ │ POST /v1/kyc/verify │
│ │ { level: "enhanced", │
│ │ data: { document_type, │
│ │ document_number, country } } │
│ │ ─────────────────▶ │
│ │ │ │
│ │ ┌─ Document Verification ────┐ │
│ │ │ Step 1: Validate document │ │
│ │ │ format & number │ │
│ │ │ Step 2: Cross-reference │ │
│ │ │ with issuing auth │ │
│ │ │ Step 3: Match name + DOB │ │
│ │ └────────────────────────────┘ │
│ │ │ │
│ │ REJECTED │ │
│ │ ◄────────────────│ │
│ "Document │ │ │
│ verification │ │ │
│ failed. │ │ │
│ Please re- │ │ │
│ submit a │ │ │
│ valid passport │ │ │
│ or national ID"│ │ │
│ ◄────────────────│ │ │
│ │ │ │
│ Re-submit │ │ │
│ corrected docs │ │ │
│ ─────────────────▶ │ │
│ │ │ │
│ │ POST /v1/kyc/verify │
│ │ { level: "enhanced", │
│ │ data: { updated docs } } │
│ │ ─────────────────▶ │
│ │ │ │
│ │ kyc.verified │ │
│ │ ◄────────────────│ │
│ "Congratulations! You're now at │ │
│ Level 2 — $1000/transaction limit" │
│ ◄────────────────│ │ │
│ │ │ │
Payment Gating by KYC Level
┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────┐
│ Human │ │ Agent │ │ ItPay │ │ Channel │
│ (Payer) │ │ (Buyer) │ │ Protocol │ │ (Alipay) │
└────┬─────┘ └──────┬───────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
│ "I want to pay │ │ │
│ $50 using │ │ │
│ Alipay" │ │ │
│ ─────────────────▶ │ │
│ │ │ │
│ │ POST /v1/payments │
│ │ { amount: 50, │
│ │ kyc_level: 0 } │
│ │ ─────────────────▶ │
│ │ │ │
│ │ │ 403 │
│ │ ◄────────────────│ │
│ │ INSUFFICIENT_KYC │ │
│ │ "Level 0 max │ │
│ │ is $10/txn. │ │
│ │ Upgrade to │ │
│ │ Level 1 for │ │
│ │ $100/txn cap." │ │
│ "You need to │ │ │
│ verify your │ │ │
│ identity first │ │ │
│ — max $10 │ │ │
│ without KYC" │ │ │
│ ◄────────────────│ │ │
│ │ │ │
Detailed Interaction Trace
Step 1: Human Initiates KYC Upgrade
The human tells their agent they want higher payment limits. The agent constructs a KYC verification request.
Human dialog:
"I want to increase my payment limit. I need to pay $50 for a premium report — can you verify my identity?"
Agent decision: The agent checks current KYC level (Level 0 — $10/txn limit). Since the desired payment ($50) exceeds Level 0, the agent initiates basic (Level 1) KYC.
Step 2: Agent Submits KYC Verification (Basic — Level 1)
HTTP Request:
POST /v1/kyc/verify
Content-Type: application/json
Authorization: Bearer api_key_merchant_abc123
{
"agent_id": "agent_cli_a1b2c3d4",
"level": "basic",
"data": {
"email": "user@example.com",
"phone": "+861****8000"
}
}
Error handling — invalid data:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"code": "validation_error",
"message": "Phone number is required for basic verification",
"details": {
"field": "data.phone",
"reason": "missing_field"
}
}
}
Human dialog (error):
"Your phone number is missing. Please provide a valid phone number where you can receive SMS."
Step 3: ItPay Issues OTP Challenge
ItPay creates the verification request in pending state and sends OTPs to the provided email and phone.
HTTP Response (initial):
HTTP/1.1 201 Created
Content-Type: application/json
{
"verification_id": "kyc_01J7Z4A5B6C7D8E9F0G1H2I3J",
"agent_id": "agent_cli_a1b2c3d4",
"level": "basic",
"status": "pending",
"challenge": {
"type": "otp",
"channels": ["email", "sms"],
"expires_at": "2026-05-27T09:45:00Z"
},
"created_at": "2026-05-27T09:35:00Z",
"updated_at": "2026-05-27T09:35:00Z"
}
Human dialog:
"I've sent a 6-digit verification code to your email (user@example.com) and phone (+861****8000). Please check them and enter the code to proceed."
Step 4: Human Submits OTP
The human retrieves the OTP and provides it to the agent, who forwards it to ItPay.
HTTP Request (OTP verification):
POST /v1/kyc/verify
Content-Type: application/json
Authorization: Bearer api_key_merchant_abc123
{
"verification_id": "kyc_01J7Z4A5B6C7D8E9F0G1H2I3J",
"otp": "482931"
}
Error handling — wrong OTP:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": {
"code": "invalid_otp",
"message": "The provided OTP is incorrect or has expired",
"details": {
"attempts_remaining": 2,
"retry_after_seconds": 30
}
}
}
Human dialog (wrong OTP):
"That code isn't correct. You have 2 more attempts before a new code needs to be sent. Please check your messages again."
Step 5: Channel KYC Cross-Reference
ItPay checks whether the human is already verified on any supported payment channel (e.g., Alipay real-name verified). If so, it may expedite or skip parts of the verification.
Internal ItPay processing:
{
"channel_check": {
"alipay": {
"user_found": true,
"kyb_level": "real_name_verified",
"equivalent_to": "basic"
},
"wechat": {
"user_found": true,
"kyb_level": "real_name_verified",
"equivalent_to": "basic"
}
},
"friction_reduction_applied": true,
"expedited": true
}
Step 6: Verification Approved
ItPay processes the verification and emits a webhook event.
Webhook:
POST https://merchant.example.com/webhooks/itpay
Content-Type: application/json
ItPay-Signature: t=1716801000,v1=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
{
"type": "kyc.verified",
"data": {
"verification_id": "kyc_01J7Z4A5B6C7D8E9F0G1H2I3J",
"agent_id": "agent_cli_a1b2c3d4",
"level": "basic",
"previous_level": "anonymous",
"limits": {
"daily": { "value": 1000, "currency": "USD" },
"per_transaction": { "value": 100, "currency": "USD" }
},
"channels": ["alipay", "wechat", "promptpay", "paynow"]
},
"created_at": "2026-05-27T09:36:00Z"
}
Human dialog (success):
"Great news! Your identity has been verified at Level 1 (Basic). You can now make transactions up to $100 each, with a daily limit of $1,000. Alipay and WeChat are available as payment channels."
Step 7: Upgrade to Enhanced (Level 2) — Document Submission
Human requests a higher limit. Agent submits enhanced KYC with government ID documents.
HTTP Request:
POST /v1/kyc/verify
Content-Type: application/json
Authorization: Bearer api_key_merchant_abc123
{
"agent_id": "agent_cli_a1b2c3d4",
"level": "enhanced",
"data": {
"email": "user@example.com",
"phone": "+861****8000",
"country": "CN",
"full_name": "Zhang Wei",
"document_type": "national_id",
"document_number": "110101199001011234"
}
}
3-Step Verification Process:
| Step | Action | Description | Expected Duration |
|---|---|---|---|
| 1 | Document format validation | Checks that document number follows country-specific format (e.g., 18-digit CN ID) | < 1 second |
| 2 | Issuing authority cross-reference | Validates document against government databases or trusted third-party KYC providers | 1–30 seconds |
| 3 | Identity match | Verifies name, date of birth, and face (if photo ID) match the provided details | 10–60 seconds |
Human dialog (document upload):
"For Level 2 (Enhanced), I need you to provide a government-issued ID. A national ID, passport, or driver's license will work. Please upload a clear photo of the front and back."
Step 8: Rejection Scenario
If document verification fails, the system returns a rejection.
HTTP Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"verification_id": "kyc_01J7Z4B6C7D8E9F0G1H2I3J4K",
"agent_id": "agent_cli_b2c3d4e5",
"level": "enhanced",
"status": "rejected",
"rejection_reason": {
"code": "document_mismatch",
"message": "The submitted document number does not match the provided name and date of birth",
"details": "The name 'Zhang Wei' on the application does not match the registered name 'Wang Wei' on document number 110101199001011234"
}
}
Webhook (rejection):
{
"type": "kyc.rejected",
"data": {
"verification_id": "kyc_01J7Z4B6C7D8E9F0G1H2I3J4K",
"agent_id": "agent_cli_b2c3d4e5",
"level": "enhanced",
"rejection_reason": {
"code": "document_mismatch",
"message": "Name does not match document"
},
"appeal_available": true,
"appeal_url": "https://itpay.ai/kyc/appeal/kyc_01J7Z4B6C7D8E9F0G1H2I3J4K"
}
}
Human dialog (rejection):
"The identity verification didn't pass. The name on your application doesn't match your ID document. You can either:
- Re-submit with the correct document matching your registered name
- File an appeal at https://itpay.ai/kyc/appeal if you believe this is an error"
Step 9: Appeal Flow
The human can appeal a rejection. This submits the existing verification data to a manual review queue.
HTTP Request (appeal):
POST /v1/kyc/appeal
Content-Type: application/json
Authorization: Bearer api_key_merchant_abc123
{
"verification_id": "kyc_01J7Z4B6C7D8E9F0G1H2I3J4K",
"reason": "My legal name was updated after marriage. I have attached my marriage certificate and updated ID. The document I submitted matches my current legal name."
}
HTTP Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"appeal_id": "appl_01K2L3M4N5O6P7Q8R9S0T1U2V",
"verification_id": "kyc_01J7Z4B6C7D8E9F0G1H2I3J4K",
"status": "under_review",
"estimated_resolution": "2026-05-29T09:40:00Z",
"message": "Your appeal has been submitted. A compliance officer will review within 48 hours."
}
Human dialog (appeal):
"Thanks for explaining. I've submitted your appeal with the supporting documents. A compliance team member will review it within 48 hours. Your current KYC level (Basic — $100/txn) remains active during the review."
Step 10: Upgrade to Business (Level 3) — Full KYB
For businesses needing high limits ($10,000/txn) and access to USDC/stablecoin channels.
Human dialog:
"I'm registering my business 'SummaryBot Inc.' for Level 3. I'll need to provide our business registration documents and UBO (Ultimate Beneficial Owner) declaration."
HTTP Request:
POST /v1/kyc/verify
Content-Type: application/json
Authorization: Bearer api_key_merchant_abc123
{
"agent_id": "agent_srv_9x8y7z6w",
"level": "business",
"data": {
"email": "legal@summarybot.ai",
"phone": "+165****1234",
"country": "US",
"full_name": "Jane Smith",
"business_name": "SummaryBot Inc.",
"registration_number": "US-123456789",
"ubo_declaration": {
"full_name": "Jane Smith",
"ownership_pct": 100
}
}
}
HTTP Response:
HTTP/1.1 201 Created
Content-Type: application/json
{
"verification_id": "kyc_01J7Z4C7D8E9F0G1H2I3J4K5L",
"agent_id": "agent_srv_9x8y7z6w",
"level": "business",
"status": "pending",
"limits": {
"daily": { "value": 100000, "currency": "USD" },
"per_transaction": { "value": 10000, "currency": "USD" }
},
"channels": ["alipay", "wechat", "promptpay", "paynow", "duitnow", "vietqr", "gcash", "usdc"],
"compliance_review_required": true,
"estimated_review_time_hours": 72,
"created_at": "2026-05-27T09:45:00Z",
"updated_at": "2026-05-27T09:45:00Z"
}
Human dialog (pending review):
"Your business verification (Level 3) has been submitted. This requires a compliance review that typically takes up to 72 hours. Meanwhile, your current Enhanced level limits ($1,000/txn) remain active. You'll be notified when the review is complete."
Level-to-Limit Mapping Reference
| KYC Level | Per-Transaction Cap | Daily Cap | Channels | Tiers Above |
|---|---|---|---|---|
| 0 (Anonymous) | $10 | $100 | Alipay, WeChat (limited) | — |
| 1 (Basic) | $100 | $1,000 | All consumer | Email + Phone OTP |
| 2 (Enhanced) | $1,000 | $10,000 | All consumer + selected business | Gov ID + Address |
| 3 (Business) | $10,000 | $100,000 | All + USDC/stablecoin | Full KYB + UBO |
Payment Gating — Error Response
When a payment attempt exceeds the current KYC level's limit:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": {
"code": "INSUFFICIENT_KYC",
"message": "Payment amount exceeds KYC level limit",
"details": {
"current_kyc_level": "anonymous",
"current_txn_limit": { "value": 10, "currency": "USD" },
"requested_amount": { "value": 50, "currency": "USD" },
"required_kyc_level": "basic",
"upgrade_url": "/v1/kyc/verify"
}
}
}
Endpoint
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/kyc/verify | Submit identity verification data |
Verification Levels
| Level | Name | Daily Limit (USD) | Per-Transaction Limit (USD) | Channels | Description |
|---|---|---|---|---|---|
| 0 | Anonymous | $100 | $10 | Alipay, WeChat (limited) | No verification required. Basic QR payments only. |
| 1 | Basic | $1,000 | $100 | All consumer channels | Email and phone verification. |
| 2 | Enhanced | $10,000 | $1,000 | All consumer + selected business channels | Government ID verification + address proof. |
| 3 | Business | $100,000 | $10,000 | All channels including USDC/stablecoin | Full KYB — business registration, UBO declaration, compliance review. |
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | yes | The agent or entity being verified |
level | string | yes | Target verification level — anonymous, basic, enhanced, or business |
data | object | conditional | Verification data. Required fields depend on the target level. |
data.email | string | basic+ | Email address for OTP verification |
data.phone | string | basic+ | Phone number for SMS OTP verification |
data.country | string | enhanced+ | ISO 3166-1 alpha-2 country code of residence/registration |
data.full_name | string | enhanced+ | Legal full name of the individual |
data.document_type | string | enhanced+ | ID document type — passport, national_id, drivers_license |
data.document_number | string | enhanced+ | ID document number |
data.business_name | string | business | Legal business name |
data.registration_number | string | business | Business registration or tax ID |
data.ubo_declaration | object | business | Ultimate Beneficial Owner declaration |
data.ubo_declaration.full_name | string | business | UBO full name |
data.ubo_declaration.ownership_pct | number | business | Ownership percentage |
channel_credentials | object | no | Pre-existing channel verification credentials to reduce friction |
channel_credentials.alipay_user_id | string | no | Alipay user ID (for Alipay-verified users) |
channel_credentials.wechat_open_id | string | no | WeChat Open ID (for WeChat-verified users) |
Request Example — Basic (Level 1)
POST /v1/kyc/verify
Content-Type: application/json
Authorization: Bearer ***
{
"agent_id": "agent_cli_a1b2c3d4",
"level": "basic",
"data": {
"email": "user@example.com",
"phone": "+861****8000"
}
}
Response Example — Basic
HTTP/1.1 201 Created
Content-Type: application/json
{
"verification_id": "kyc_01J7Z4A5B6C7D8E9F0G1H2I3J",
"agent_id": "agent_cli_a1b2c3d4",
"level": "basic",
"status": "pending",
"data": {
"email": "user@example.com",
"phone": "+861****8000"
},
"limits": {
"daily": { "value": 1000, "currency": "USD" },
"per_transaction": { "value": 100, "currency": "USD" }
},
"channels": ["alipay", "wechat", "promptpay", "paynow"],
"created_at": "2026-05-27T09:35:00Z",
"updated_at": "2026-05-27T09:35:00Z"
}
Request Example — Enhanced (Level 2) with Channel Credentials
POST /v1/kyc/verify
Content-Type: application/json
Authorization: Bearer ***
{
"agent_id": "agent_cli_b2c3d4e5",
"level": "enhanced",
"data": {
"email": "verified@example.com",
"phone": "+861****9000",
"country": "CN",
"full_name": "Zhang Wei",
"document_type": "national_id",
"document_number": "110101199001011234"
},
"channel_credentials": {
"alipay_user_id": "alipay_usr_abc_123",
"wechat_open_id": "wx_openid_xyz_789"
}
}
Response Example — Enhanced
HTTP/1.1 201 Created
Content-Type: application/json
{
"verification_id": "kyc_01J7Z4B6C7D8E9F0G1H2I3J4K",
"agent_id": "agent_cli_b2c3d4e5",
"level": "enhanced",
"status": "pending",
"limits": {
"daily": { "value": 10000, "currency": "USD" },
"per_transaction": { "value": 1000, "currency": "USD" }
},
"channels": ["alipay", "wechat", "promptpay", "paynow", "duitnow", "vietqr", "gcash"],
"channel_friction_reduced": true,
"friction_reduction_channels": ["alipay", "wechat"],
"created_at": "2026-05-27T09:40:00Z",
"updated_at": "2026-05-27T09:40:00Z"
}
Request Example — Business / KYB (Level 3)
POST /v1/kyc/verify
Content-Type: application/json
Authorization: Bearer ***
{
"agent_id": "agent_srv_9x8y7z6w",
"level": "business",
"data": {
"email": "legal@summarybot.ai",
"phone": "+165****1234",
"country": "US",
"full_name": "Jane Smith",
"business_name": "SummaryBot Inc.",
"registration_number": "US-123456789",
"ubo_declaration": {
"full_name": "Jane Smith",
"ownership_pct": 100
}
}
}
Response Example — Business
HTTP/1.1 201 Created
Content-Type: application/json
{
"verification_id": "kyc_01J7Z4C7D8E9F0G1H2I3J4K5L",
"agent_id": "agent_srv_9x8y7z6w",
"level": "business",
"status": "pending",
"limits": {
"daily": { "value": 100000, "currency": "USD" },
"per_transaction": { "value": 10000, "currency": "USD" }
},
"channels": ["alipay", "wechat", "promptpay", "paynow", "duitnow", "vietqr", "gcash", "usdc"],
"created_at": "2026-05-27T09:45:00Z",
"updated_at": "2026-05-27T09:45:00Z"
}
State Machine
Each verification request follows this lifecycle:
┌─────────────┐
│ unverified │
└──────┬──────┘
│ submit verification
▼
┌─────────────┐
│ pending │
└──────┬──────┘
┌─────┴─────┐
│ │
▼ ▼
┌─────────┐ ┌─────────┐
│ verified │ │ rejected│
└─────────┘ └─────────┘
Transitions
| From | To | Trigger |
|---|---|---|
unverified | pending | Verification data submitted |
pending | verified | Identity verification successful |
pending | rejected | Identity verification failed (invalid documents, data mismatch) |
verified | rejected | Periodic review found issues or documents expired |
rejected | pending | Re-submit with corrected data |
OAuth-Based Friction Reduction
When the payer already has a verified identity on a supported payment channel (e.g., Alipay real-name verified), those credentials can be reused to skip or accelerate the ItPay KYC process.
How It Works
- The agent includes
channel_credentialsin the KYC request. - ItPay cross-references the channel credentials with the channel's KYC status.
- If the channel has already performed equivalent or higher-level verification, ItPay may:
- Expedite the verification (reduced review time from days to minutes)
- Reduce friction (skip some document uploads)
- Accept directly (for Level 1 basic, if the channel KYC is equivalent)
- The response field
channel_friction_reducedindicates whether channel credentials were used to reduce friction.
Supported Channels for Friction Reduction
| Channel | Level Equivalent | Notes |
|---|---|---|
| Alipay | Basic (Level 1) | Real-name verified users can skip email/phone OTP |
| WeChat Pay | Basic (Level 1) | Real-name verified users can skip email/phone OTP |
| PromptPay (Thailand) | Basic (Level 1) | National ID-linked accounts |
| PayNow (Singapore) | Basic (Level 1) | NRIC/FIN-linked accounts |
Key Behaviors
- Progressive verification: An agent can start at any level and upgrade later by submitting a new verification request with a higher
level. - Channel limits: Unverified (Level 0) agents can only use limited channels and are capped at $10 per transaction. Higher levels unlock more channels and higher limits.
- Document retention: Submitted verification documents are stored encrypted for compliance purposes. Retention follows applicable regulations (typically 5–7 years).
- Periodic review: Enhanced (Level 2) and Business (Level 3) verifications are subject to periodic re-verification (annually for Level 2, semi-annually for Level 3).
Webhook Events
| Event | Description |
|---|---|
kyc.verified | Verification was approved at the requested level |
kyc.rejected | Verification was rejected (includes reason in payload) |
kyc.expiring | Verification is nearing its expiration date (sent 30 days before) |
kyc.expired | Verification period has ended, limits have been downgraded |
Next Steps
- Install — Configure auto-pay limits after KYC verification
- Broadcast & Discovery — Register a service with verified business identity
- Channel Matrix — See which channels are available at each KYC level