Mobile Registration Module¶
Overview¶
Mobile onboarding and DIDIT identity-verification flow.
API Prefix: /api/v1/mobile/register
Route Verification Status¶
- Source Router:
app/api/v1/endpoints/mobile_register.py - Live Route Count: 12
- Verification State: Verified (2026-06-28)
- Canonical Tracking:
docs/API_ROUTE_DOCUMENTATION_TODO.md - Verification Method: Route decorators extracted from
@mobile_register_router.<method>(...)inmobile_register.py.
API Endpoints (Verified Against Live Router)¶
For the complete mobile registration endpoint inventory (method, effective path, source line), use:
- docs/API_ROUTE_LIVE_REFERENCE.md -> section mobile_register.py (12 routes)
Endpoint Purpose Map¶
| Method | Path | Purpose |
|---|---|---|
| POST | /api/v1/mobile/register/check-phone | Starts registration and creates a registration token after duplicate checks and CBS phone probing. |
| POST | /api/v1/mobile/register/start-identity-verification | Opens a DIDIT verification session and stores DIDIT session metadata on the registration token. |
| POST | /api/v1/mobile/register/didit-webhook | Public callback for DIDIT status updates; validates signature and updates registration verification state. |
| GET | /api/v1/mobile/register/didit-webhook | Browser redirect handler fallback for providers redirecting to callback URL with query params. |
| GET | /api/v1/mobile/register/didit-redirect | Browser redirect endpoint that resolves DIDIT query params and deep-links back to mobile app. |
| GET | /api/v1/mobile/register/verification-status/{session_id} | Polls DIDIT decision status when webhook delivery is delayed. |
| POST | /api/v1/mobile/register/send-otp | Sends staged OTP (phone first, email second) after identity prerequisites are satisfied. |
| POST | /api/v1/mobile/register/lookup-cbs | Resolves customer in CBS via national ID and stores CBS linkage on token for existing-customer flow. |
| POST | /api/v1/mobile/register/verify-otp | Verifies OTP and advances registration status machine. |
| POST | /api/v1/mobile/register/accept-terms | Records terms acceptance and advances registration status machine. |
| POST | /api/v1/mobile/register/set-pin | Saves customer PIN for registration token. |
| POST | /api/v1/mobile/register/complete | Completes registration, stages user/customer, and optionally auto-approves to login-ready state. |
Service/API Dependencies (Verified)¶
Primary service orchestrator:
- app/services/mobile_registration.py (MobileRegistrationService)
- Token lifecycle: uniqueness checks, token creation, token retrieval.
- Identity stage guards and OTP stage machine.
- Terms/PIN completion and registration completion logic.
Identity verification integration:
- app/services/didit_verification.py (DiditVerificationService)
- DIDIT hosted session creation.
- Webhook signature validation and event handling.
- Poll fallback (retrieve_decision, evaluation mapping).
External API clients:
- app/integrations/clients/http.py via get_api_client_with_issuer("cbs")
- Used for CBS phone probe, customer lookup, and registration completion account actions.
Approval/staging dependencies:
- app/services/customer.py (stage_customer_changes)
- app/services/users.py (stage_user, get_user_by_username)
- Used during optional auto-approval path in /complete.
Core persistence model used by this flow:
- RegistrationToken (status machine, DIDIT state, OTP progress, referral metadata).
Workflow Summary¶
- Phone pre-check and token creation (
/check-phone). - Existing customer path: CBS lookup (
/lookup-cbs) OR non-bank path: DIDIT session (/start-identity-verification). - DIDIT completion via webhook/redirect/poll (
/didit-webhook,/didit-redirect,/verification-status/{session_id}). - OTP verification sequence (
/send-otpthen/verify-otp; phone before email). - Terms acceptance and PIN setup (
/accept-terms,/set-pin). - Final staging and optional auto-approval (
/complete).
Workflow Diagrams¶
End-to-End Registration Sequence¶
sequenceDiagram
autonumber
participant App as Mobile App
participant API as Backend API
participant CBS as CBS Service
participant DIDIT as DIDIT Service
participant Admin as Admin Portal
App->>API: POST /mobile/register/check-phone
API->>CBS: Probe phone existence
CBS-->>API: Existing/Non-existing signal
API-->>App: registration_token_id
alt Existing CBS customer path
App->>API: POST /mobile/register/lookup-cbs
API->>CBS: Customer lookup by national ID
CBS-->>API: Customer data
API-->>App: customer_found=true
else Non-bank customer path
App->>API: POST /mobile/register/start-identity-verification
API->>DIDIT: Create verification session
DIDIT-->>API: session_id + session_url
API-->>App: didit_session_url
App->>DIDIT: Complete hosted verification
DIDIT->>API: POST /mobile/register/didit-webhook
DIDIT->>API: GET /mobile/register/didit-redirect
App->>API: GET /mobile/register/verification-status/{session_id}
API-->>App: APPROVED/DECLINED/PENDING
end
App->>API: POST /mobile/register/send-otp (phone)
App->>API: POST /mobile/register/verify-otp
App->>API: POST /mobile/register/send-otp (email)
App->>API: POST /mobile/register/verify-otp
App->>API: POST /mobile/register/accept-terms
App->>API: POST /mobile/register/set-pin
App->>API: POST /mobile/register/complete
alt Auto-approval enabled
API->>CBS: Stage/approve customer + account operations
API-->>App: next_step=login
else Manual approval
API-->>App: pending approval
Admin->>API: Approve staged registration
API->>CBS: Account operations on approval
end
DIDIT Callback and Redirect Control Flow¶
flowchart TD
A[User completes DIDIT hosted flow] --> B{DIDIT callback type}
B -->|POST webhook| C[/mobile/register/didit-webhook/]
B -->|GET browser redirect| D[/mobile/register/didit-redirect or didit-webhook/]
C --> E[Verify x-signature-v2]
E -->|invalid| F[401 Invalid signature]
E -->|valid| G[Process payload and update token status]
D --> H[Normalize query params session_id/status]
H --> I[RedirectResponse to mobile deep link]
G --> J[Mobile polls verification-status if needed]
I --> J
J --> K{Verification status}
K -->|APPROVED| L[Proceed to OTP]
K -->|DECLINED or EXPIRED| M[Show failure/retry path]
K -->|PENDING or IN_REVIEW| N[Continue polling with backoff]
Registration State Machine¶
stateDiagram-v2
[*] --> PHONE_CHECKED: check-phone success
PHONE_CHECKED --> IDENTITY_VERIFIED: lookup-cbs success
PHONE_CHECKED --> DIDIT_IN_PROGRESS: start-identity-verification
DIDIT_IN_PROGRESS --> IDENTITY_VERIFIED: didit APPROVED
DIDIT_IN_PROGRESS --> DIDIT_DECLINED: didit DECLINED/EXPIRED
IDENTITY_VERIFIED --> PHONE_OTP_SENT: send-otp (phone)
PHONE_OTP_SENT --> PHONE_OTP_VERIFIED: verify-otp
PHONE_OTP_VERIFIED --> EMAIL_OTP_SENT: send-otp (email)
EMAIL_OTP_SENT --> EMAIL_OTP_VERIFIED: verify-otp
EMAIL_OTP_VERIFIED --> TERMS_ACCEPTED: accept-terms
TERMS_ACCEPTED --> PIN_SET: set-pin
PIN_SET --> COMPLETION_REQUESTED: complete
COMPLETION_REQUESTED --> APPROVED: auto-approval success
COMPLETION_REQUESTED --> PENDING_APPROVAL: manual approval mode
PENDING_APPROVAL --> APPROVED: admin approval
DIDIT_DECLINED --> [*]
APPROVED --> [*]
Registration Workflows (Detailed)¶
A) Existing CBS Customer Workflow¶
- Client calls
POST /api/v1/mobile/register/check-phone. - Backend validates uniqueness and creates
RegistrationToken. - Client calls
POST /api/v1/mobile/register/lookup-cbswith national ID (and optional customer number). - Backend stores CBS linkage (
is_existing_customer=true,cbs_customer_id,cbs_data). - If DIDIT is enabled, client can still run identity verification before OTP.
- Client requests OTP with
POST /api/v1/mobile/register/send-otp(phone stage). - Client verifies OTP with
POST /api/v1/mobile/register/verify-otp. - Client requests OTP again for email stage and verifies it.
- Client accepts terms (
POST /accept-terms) and sets PIN (POST /set-pin). - Client completes flow via
POST /complete. - If auto-approval is enabled, staging is approved immediately; otherwise, pending admin approval.
B) Non-Bank Customer (DIDIT) Workflow¶
- Client calls
POST /api/v1/mobile/register/check-phone. - Backend creates
RegistrationTokenand confirms no active duplicate registration. - Client starts verification with
POST /api/v1/mobile/register/start-identity-verification. - User completes DIDIT hosted flow in browser/WebView.
- Backend receives DIDIT completion through webhook and/or redirect.
- Client polls
GET /api/v1/mobile/register/verification-status/{session_id}until approved if needed. - After DIDIT approval, client performs OTP sequence (phone then email).
- Client accepts terms and sets PIN.
- Client calls
POST /api/v1/mobile/register/complete. - Staging is created with DIDIT-verified identity data and marked as non-existing-customer flow.
- Approval path:
- Auto-approval: backend stages customer/user and opens CBS account in approval pipeline.
- Manual approval: admin approval triggers the same staging pipeline and CBS account opening.
C) DIDIT Callback and Redirect Workflow¶
- DIDIT sends server callback to
POST /api/v1/mobile/register/didit-webhook. - Backend verifies
x-signature-v2, parses payload, updates token/session verification state. - Browser redirect lands on:
GET /api/v1/mobile/register/didit-redirect, orGET /api/v1/mobile/register/didit-webhook(provider-dependent).
- Redirect handler normalizes query parameter variants and deep-links user back to mobile app.
- Mobile app resumes flow and confirms final status through verification-status polling.
D) Completion and Approval Workflow¶
POST /api/v1/mobile/register/completefinalizes registration staging payload.- If referral code exists, it is attached before completion logic.
- Backend checks auto-approval configuration:
- Enabled: executes customer + user stage operations in same flow.
- Disabled: returns pending state and waits for admin approval workflow.
- Approval path provisions customer artifacts and performs CBS account operations where applicable.
Registration State Machine (Operational)¶
The registration flow is guarded by token state transitions and stage checks: - Initial: phone checked and token created. - Identity stage: CBS lookup and/or DIDIT verification completed. - OTP stage: phone OTP then email OTP. - Terms stage: terms accepted. - PIN stage: PIN set. - Completed: registration completion requested and staged/approved.
Operational rule:
- Requests that skip required prior stages are rejected with 4xx status (most commonly 400 or 403).
Failure and Retry Workflows¶
Duplicate or in-progress registration¶
- Condition: active token exists for same phone and not expired/completed.
- Result:
409conflict from/check-phone. - Retry path: wait for token expiry or complete/cancel existing flow.
DIDIT service unavailable¶
- Condition: DIDIT disabled or unavailable.
- Result:
503from DIDIT-dependent endpoints. - Retry path: operator remediation; client retries when service is restored.
Webhook signature failure¶
- Condition: invalid signature on DIDIT callback.
- Result:
401from/didit-webhook. - Retry path: verify webhook secret/configuration and resend callback.
OTP stage mismatch¶
- Condition: OTP requested or verified out of order.
- Result:
403or400depending on stage guard. - Retry path: continue from last valid stage (phone OTP before email OTP).
Completion/staging failure¶
- Condition: internal staging or external dependency failure during
/complete. - Result:
500. - Retry path: repeat completion or continue through admin approval/recovery path.
Cross-Reference Guides¶
For deeper implementation specifics used by this module:
- NON_BANK_ACCOUNT_REGISTRATION.md (non-bank account creation and approval strategy).
- DIDIT_WEBHOOK_REDIRECT_GUIDE.md (callback/redirect dual-path behavior).
- DIDIT_INTEGRATION_GUIDE.md (DIDIT configuration, payloads, and runtime integration).
User Stories¶
US-01: Start Registration With Phone Number¶
As a new user, I want to start registration using my phone number so that I can create a mobile banking account.
Acceptance criteria:
- POST /api/v1/mobile/register/check-phone returns a valid registration_token_id for eligible phone numbers.
- Duplicate or in-progress registrations for the same phone return 409.
- Response clearly indicates whether CBS phone linkage exists (has_cbs_account, cbs_phone_exists).
US-02: Existing CBS Customer Registration¶
As an existing bank customer, I want to verify my identity via CBS lookup so that I can complete mobile registration quickly.
Acceptance criteria:
- POST /api/v1/mobile/register/lookup-cbs with valid national ID returns customer_found=true.
- Registration token is updated with CBS linkage and existing-customer context.
- User can proceed to OTP stages without onboarding dead-ends.
US-03: Non-Bank Customer Registration Via DIDIT¶
As a non-bank customer, I want to verify identity through DIDIT so that I can be onboarded securely.
Acceptance criteria:
- POST /api/v1/mobile/register/start-identity-verification returns didit_session_id and didit_session_url when DIDIT is enabled.
- DIDIT webhook/redirect flow updates token verification state.
- Approved DIDIT users can continue to OTP and completion stages.
US-04: Resume App Flow After DIDIT Browser Redirect¶
As a user returning from DIDIT verification, I want the app to reopen in the correct step so that I can continue registration seamlessly.
Acceptance criteria:
- Redirect handler supports /didit-redirect and GET /didit-webhook callback variants.
- Deep link includes normalized session_id and status context when available.
- App can poll GET /verification-status/{session_id} and continue on APPROVED.
US-05: Complete Two-Stage OTP Verification¶
As a registrant, I want to verify phone OTP then email OTP so that my contacts are validated before account activation.
Acceptance criteria:
- POST /send-otp enforces stage order (phone OTP before email OTP).
- POST /verify-otp updates registration stage and returns actionable next-step messages.
- Out-of-order OTP attempts return 400/403 with clear error detail.
US-06: Accept Terms and Set PIN¶
As a registrant, I want to accept terms and set my PIN so that I can securely access mobile banking.
Acceptance criteria:
- POST /accept-terms records terms acceptance only when prerequisite stages are satisfied.
- POST /set-pin stores PIN only when allowed by registration state.
- Stage-incompatible calls return appropriate 4xx responses.
US-07: Complete Registration and Receive Activation Outcome¶
As a registrant, I want a clear completion outcome so that I know whether I can log in immediately or await approval.
Acceptance criteria:
- POST /complete returns next_step and success message with deterministic status.
- Auto-approval path returns login-ready outcome when staging succeeds.
- Manual-approval path returns pending status until admin approval is performed.
US-08: Admin Approves Pending Registration¶
As an operations/admin user, I want to approve staged registrations so that pending users can be activated safely.
Acceptance criteria: - Manual approval triggers the same customer/user staging pipeline as auto-approval. - Non-bank approved users receive CBS account provisioning via approval workflow. - Approval failures are auditable and retriable via operational procedures.
US-09: Handle DIDIT Service Downtime Gracefully¶
As a registrant, I want understandable feedback when identity verification services are unavailable so that I can retry later.
Acceptance criteria:
- DIDIT-dependent endpoints return 503 when DIDIT is disabled/unavailable.
- Error responses include actionable message for retry/support.
- Flow does not silently stall; status remains recoverable.
US-10: Prevent Fraudulent or Invalid Webhook Updates¶
As a platform security stakeholder, I want webhook callbacks verified so that only trusted DIDIT events can mutate registration state.
Acceptance criteria:
- POST /didit-webhook rejects invalid signatures with 401.
- Valid callbacks update token decision/status fields consistently.
- Failed webhook processing returns 422/500 with traceable logs.
Permission Dependency Notes (Verified)¶
Observed implementation posture in mobile_register.py:
- No explicit permission_required("...") checks.
- Endpoints are designed for pre-auth/public onboarding and rely on:
- Registration token state machine checks.
- DIDIT signature verification for webhook integrity.
- Flow-step gating (identity prerequisites before OTP; OTP before terms/PIN/complete).
Operational recommendation: - Keep these routes intentionally public but enforce strict throttling/rate limits and replay protections at API gateway/middleware level.
Standard Error Response Matrix¶
{
"status_code": 400,
"error_code": "MOBILE_REGISTRATION_ERROR",
"message": "Human-readable summary",
"details": {}
}
Common mappings:
- 400 invalid input or stage-incompatible request.
- 401 invalid DIDIT webhook signature.
- 403 flow-gating failure (for example identity not complete before OTP).
- 404 registration token/session not found.
- 409 duplicate registration in progress or already-registered phone.
- 422 webhook payload or OTP verification processing failure.
- 429 registration/OTP throttling.
- 500 internal registration orchestration failure.
- 503 DIDIT service disabled/unavailable.