Architecture Diagrams

Visual Architecture Diagrams

These diagrams show how UrbanPayX systems work together. Use them to understand the full lifecycle of payments, verification, authentication, and webhooks before you write a single line of code.


Payment flow

This is the complete journey from payment link creation to webhook confirmation.

  Your Backend                  UrbanPayX                 Payer's Browser            Payer's Bank
       │                            │                            │                        │
       │  POST /checkout/paylink    │                            │                        │
       │ ────────────────────────►  │                            │                        │
       │                            │                            │                        │
       │  {transaction_id,          │                            │                        │
       │   checkout_url,            │                            │                        │
       │   status: pending}         │                            │                        │
       │  ◄──────────────────────── │                            │                        │
       │                            │                            │                        │
       │         Send checkout_url to payer                      │                        │
       │ ──────────────────────────────────────────────────────► │                        │
       │                            │                            │                        │
       │                            │    Open hosted checkout    │                        │
       │                            │  ◄──────────────────────── │                        │
       │                            │                            │                        │
       │                            │    Show bank selection     │                        │
       │                            │  ────────────────────────► │                        │
       │                            │                            │                        │
       │                            │                            │   Authorize payment    │
       │                            │                            │ ─────────────────────► │
       │                            │                            │                        │
       │                            │                            │   Payment confirmed    │
       │                            │  ◄──────────────────────────────────────────────────│
       │                            │                            │                        │
       │  Webhook:                  │                            │                        │
       │  payment.status_changed    │                            │                        │
       │  ◄──────────────────────── │                            │                        │
       │                            │                            │                        │
       ▼  Verify signature,         │                            │                        │
          fulfill order             │                            │                        │

Transaction status state machine

                          ┌──────────────────────┐
                          │                      │
    Payment link ──────►  │      pending         │
    created                │                      │
                          └──┬───────┬────────┬──┘
                             │       │        │
                Bank auth    │       │        │   TTL elapsed
                started      │       │        │   or user abandoned
                             ▼       │        ▼
                     ┌────────────┐  │  ┌──────────┐
                     │ processing │  │  │ expired / │
                     └──┬─────┬──┘  │  │ cancelled │
                        │     │     │  └───────────┘
              Bank      │     │     │
            confirmed   │     │  Bank rejected
                        ▼     ▼
                 ┌───────┐  ┌────────┐
                 │succeed│  │ failed │
                 └───────┘  └────────┘
StatusTerminal?What happened
pendingNoPayment link created, waiting for user action
processingNoUser started bank authorization
succeededYesBank confirmed the payment
failedYesBank rejected the payment
expiredYesCheckout window elapsed without completion
cancelledYesUser abandoned the checkout flow

KYC verification flow

UrbanPayX supports two verification modes. Choose based on whether you want UrbanPayX to handle identity checks or bring your own verification.

Mode A: UrbanPayX KYC

  Your Backend                  UrbanPayX                     User
       │                            │                           │
       │  POST /kyc/users           │                           │
       │ ────────────────────────►  │                           │
       │                            │                           │
       │  {user_id,                 │                           │
       │   kyc_status: none}        │                           │
       │  ◄──────────────────────── │                           │
       │                            │                           │
       │  POST /kyc/verify          │                           │
       │ ────────────────────────►  │                           │
       │                            │                           │
       │  {kyc_status: pending,     │                           │
       │   verification_url}        │                           │
       │  ◄──────────────────────── │                           │
       │                            │                           │
       │       Send verification_url to user                    │
       │ ─────────────────────────────────────────────────────► │
       │                            │                           │
       │                            │   Complete identity check │
       │                            │  ◄──────────────────────  │
       │                            │                           │
       │                            │   Review and verify       │
       │                            │   (internal)              │
       │                            │                           │
       │  Webhook:                  │                           │
       │  kyc.status_changed        │                           │
       │  ◄──────────────────────── │                           │
       │                            │                           │
       ▼  User now eligible         │                           │
          for payments              │                           │

Mode B: External attestation

  Your Backend                  UrbanPayX              Your KYC Provider
       │                            │                        │
       │  POST /kyc/users           │                        │
       │ ────────────────────────►  │                        │
       │                            │                        │
       │  {user_id,                 │                        │
       │   status: pending}         │                        │
       │  ◄──────────────────────── │                        │
       │                            │                        │
       │  Run your own verification                          │
       │ ─────────────────────────────────────────────────►  │
       │                            │                        │
       │  Verification result       │                        │
       │  ◄───────────────────────────────────────────────── │
       │                            │                        │
       │  POST /kyc/external/       │                        │
       │  status/USER_ID          │                        │
       │ ────────────────────────►  │                        │
       │                            │                        │
       │  {status: verified}        │                        │
       │  ◄──────────────────────── │                        │
       │                            │                        │
       │  Webhook:                  │                        │
       │  kyc.status_changed        │                        │
       │  ◄──────────────────────── │                        │

KYC status state machines

UrbanPayX KYC mode:

  [user created] ──► none ──► pending ──┬──► approved  ✓
                       ▲                │
                       │                └──► rejected
                       │                       │
                       └───── reset (retry) ───┘

External attestation mode:

  [user created] ──► pending ──┬──► verified  ✓
                               │
                               └──► rejected

Payment eligibility

Before generating a payment link, UrbanPayX checks the user's verification status:

Active modePayment-eligible statusBlocked statuses
urbanpayx_kyckyc_status = approvednone, pending, rejected
external_attestationexternal_verification_status = verifiedpending, rejected

Authentication flow

UrbanPayX supports two authentication methods: API key (server-to-server) and email/password (dashboard).

API key authentication

  Your Backend                  UrbanPayX
       │                            │
       │  POST /auth/api-token      │
       │  {api_key, api_secret}     │
       │ ────────────────────────►  │
       │                            │
       │  {access_token, TTL: 2h}   │
       │  ◄──────────────────────── │
       │                            │
       │  GET /transactions/{id}    │
       │  Authorization: Bearer     │
       │  {access_token}            │
       │ ────────────────────────►  │
       │                            │
       │  Transaction data          │
       │  ◄──────────────────────── │
       │                            │
       │    ... 2 hours later ...   │
       │                            │
       │  POST /auth/api-token      │
       │ ────────────────────────►  │
       │                            │
       │  {new access_token}        │
       │  ◄──────────────────────── │

Email/password login with MFA

  Dashboard User                UrbanPayX
       │                            │
       │  POST /auth/login          │
       │  {email, password}         │
       │ ────────────────────────►  │
       │                            │
       │         ┌──────────────────┤
       │         │ Verify password  │
       │         └──────────────────┤
       │                            │
       ├─── If MFA NOT required ────┤
       │                            │
       │  {access_token,            │
       │   refresh_token}           │
       │  ◄──────────────────────── │
       │                            │
       ├─── If MFA required ────────┤
       │                            │
       │  {otp_pending,             │
       │   challenge_token}         │
       │  ◄──────────────────────── │
       │                            │
       │  POST /auth/login/         │
       │  verify-otp                │
       │  {otp_code,                │
       │   challenge_token}         │
       │ ────────────────────────►  │
       │                            │
       │  {access_token,            │
       │   refresh_token}           │
       │  ◄──────────────────────── │
       │                            │
       ├─── Token refresh ──────────┤
       │                            │
       │  POST /auth/refresh        │
       │  {refresh_token}           │
       │ ────────────────────────►  │
       │                            │
       │  {new access_token,        │
       │   new refresh_token}       │
       │  ◄──────────────────────── │

Token comparison

API key authEmail/password login
Access token TTL2 hours30 minutes
Refresh tokenNot issued30-day TTL, rotated on use
RoleAlways operationsUser's assigned role
MFANot applicableEmail OTP or TOTP
Best forServer-to-serverDashboard and admin

OpCo lifecycle

Operating Companies (OpCos) represent the regulated entities that process payments. Every OpCo must be registered and activated before it can process transactions.

  Your Backend                  UrbanPayX
       │                            │
       │  ── Phase 1: Create ────── │
       │                            │
       │  POST /opcos/create        │
       │ ────────────────────────►  │
       │                            │
       │  {opco_id,                 │
       │   status: draft}           │
       │  ◄──────────────────────── │
       │                            │
       │  PATCH /opcos/{id}         │
       │  (optional edits)          │
       │ ────────────────────────►  │
       │                            │
       │  ── Phase 2: Submit ────── │
       │                            │
       │  PATCH /opcos/{id}/submit  │
       │ ────────────────────────►  │
       │                            │
       │  {status:                  │
       │   awaiting_approval}       │
       │  ◄──────────────────────── │
       │                            │
       │  ── Phase 3: Approval ──── │
       │                            │
       │         ┌──────────────────┤
       │         │ Upstream         │
       │         │ registration     │
       │         │ + polling        │
       │         └──────────────────┤
       │                            │
       │  Webhook:                  │
       │  opco.status_changed       │
       │  {status: activated}       │
       │  ◄──────────────────────── │
       │                            │
       ▼  OpCo ready for payments   │

OpCo status state machine

  POST /opcos/create
         │
         ▼
      ┌───────┐     Submit     ┌───────────────────┐    Approved    ┌───────────┐
      │ draft │ ─────────────► │ awaiting_approval │ ─────────────► │ activated │
      └───────┘                └───────────────────┘                └─────┬─────┘
                                        │                                 │
                                        │ Rejected                        │ Admin action
                                        ▼                                 ▼
                                  ┌──────────┐                     ┌─────────────┐
                                  │ rejected │                     │ deactivated │
                                  └──────────┘                     └─────────────┘

Approval timeline

EnvironmentTypical wait time
SandboxMinutes
Production3–5 business days

In production, subscribe to the opco.status_changed webhook rather than polling.


Webhook delivery flow

When a business event occurs, UrbanPayX delivers a signed webhook to your endpoint with automatic retries.

  UrbanPayX                     Your Endpoint
       │                            │
       │  Event occurs              │
       │  (e.g. payment succeeded)  │
       │                            │
       │  POST {your_webhook_url}   │
       │  Signed: HMAC-SHA256       │
       │ ────────────────────────►  │
       │                            │
       ├─── If 2xx response ────────┤
       │                            │
       │  200 OK                    │
       │  ◄──────────────────────── │
       │  ✓ Delivered               │
       │                            │
       ├─── If non-2xx / timeout ───┤
       │                            │
       │  500 / timeout             │
       │  ◄──────────────────────── │
       │                            │
       │  Retry with exponential    │
       │  backoff (up to 8 times)   │
       │ ────────────────────────►  │

Webhook event lifecycle

                           ┌─────────────────────┐
  Event created ─────────► │      PENDING        │ ◄─── Retry (non-2xx)
                           └──┬──────────────┬───┘        │
                              │              │             │
                        2xx   │              │  Max        │
                     response │              │ attempts    │
                              ▼              ▼             │
                       ┌───────────┐  ┌─────────────┐     │
                       │ DELIVERED │  │ DEAD_LETTER │     │
                       └───────────┘  └─────────────┘     │

Your handler checklist

  1. Receive POST request
         │
         ▼
  2. Verify HMAC-SHA256 signature
         │
    ┌────┴────┐
    │ Invalid │ ──► Return 401
    └────┬────┘
         │ Valid
         ▼
  3. Check timestamp freshness (< 5 min)
         │
    ┌────┴────┐
    │  Stale  │ ──► Return 401
    └────┬────┘
         │ Fresh
         ▼
  4. Check event ID for duplicates
         │
    ┌────┴──────┐
    │ Duplicate │ ──► Return 200 (skip processing)
    └────┬──────┘
         │ New
         ▼
  5. Process the event
         │
         ▼
  6. Store event ID (for dedup)
         │
         ▼
  7. Return 200

System overview

  ┌─────────────────────────────────────────────────────────────────────┐
  │                       YOUR INFRASTRUCTURE                          │
  │                                                                    │
  │   ┌──────────────┐                    ┌────────────────────────┐   │
  │   │ Your Backend │ ── REST API ─────► │                        │   │
  │   └──────────────┘                    │                        │   │
  │                                       │   UrbanPayX Platform   │   │
  │   ┌──────────────────────┐            │                        │   │
  │   │ Your Webhook         │ ◄── Webhooks ──│  API Gateway       │   │
  │   │ Endpoint             │            │   │  Background Workers│   │
  │   └──────────────────────┘            │                        │   │
  │                                       └────────────────────────┘   │
  └─────────────────────────────────────────────────────────────────────┘

  ┌─────────────────────────────────────────────────────────────────────┐
  │                          END USER                                   │
  │                                                                    │
  │   ┌──────────┐  Hosted checkout   ┌────────────────────────┐       │
  │   │ Browser  │ ────────────────►  │   UrbanPayX Platform   │       │
  │   │          │  KYC verification  │                        │       │
  │   └────┬─────┘                    └────────────────────────┘       │
  │        │                                                           │
  │        │  Bank auth                                                │
  │        ▼                                                           │
  │   ┌──────────┐                                                     │
  │   │ Bank App │                                                     │
  │   └──────────┘                                                     │
  └─────────────────────────────────────────────────────────────────────┘

Related guides