Request Router

Routes deposit and withdrawal requests. Input validation before the Orchestrator.

Phase 2
Spec
Request Router is the first component in the API Gateway that understands business logic. It receives already-authenticated requests from Auth middleware and Rate Limiter, validates input, enriches context (geo, session), and forwards a normalized request to the Orchestrator. It performs no payment operations itself.
The POST /payments/withdrawal endpoint returns 501 Not Implemented in Phase 2. The stub exists so the frontend can build without type errors. Full implementation is Phase 3.
1.

Endpoints

POST
/payments/deposit
JWT required

Initiates a new deposit. Validates the request, then forwards to the Orchestrator.

Request Body

FieldTypeRequiredDescription
amountnumber
Yes
Amount in the smallest currency unit (e.g. cents)
currencystring
Yes
ISO 4217 code, e.g. "USD"
methodstring
Yes
Payment method slug, e.g. "btc"
metadataobject
No
Arbitrary key-value pairs passed through to transaction.metadata

Response (200 OK)

FieldTypeDescription
transaction_idstringUUID of the created transaction
statusstring"INITIATED" -- initial status
wallet_addressstringCrypto address to show the player
destination_tagstring | nullRequired memo for XRP/TON, null otherwise
expires_atstringISO 8601 datetime when the invoice expires
amount_cryptostringExact crypto amount the player must send
POST
/payments/withdrawal
JWT required

Initiates a withdrawal. Requires KYC gate and balance check before forwarding to Orchestrator. Phase 3 feature -- stub in Phase 2.

Request Body

FieldTypeRequiredDescription
amountnumber
Yes
Amount to withdraw in the smallest currency unit
currencystring
Yes
ISO 4217 currency code
methodstring
Yes
Payment method slug
wallet_addressstring
Yes
Player's destination wallet address
destination_tagstring
No
Memo / destination tag for XRP, TON

Response (200 OK)

FieldTypeDescription
transaction_idstringUUID of the created transaction
statusstring"INITIATED" -- pending KYC/manual review in Phase 3
GET
/payments/:transaction_id/status
JWT required

Returns current transaction status. Polled by the frontend. See Status Polling spec.

Response (200 OK)

FieldTypeDescription
transaction_idstringTransaction UUID
statusstringCurrent UnifiedStatus
directionstring"deposit" | "withdrawal"
amount_requestednumberOriginal requested amount (smallest unit)
amount_creditednumber | nullCredited amount, null until COMPLETED
wallet_addressstring | nullFor deposits: address to show player
expires_atstring | nullInvoice expiry, null if already expired/completed
created_atstringISO 8601 transaction creation time
updated_atstringISO 8601 last status change time
GET
/payments/methods
JWT required

Returns available payment methods for the player's brand + geo. Read from payment_methods cache table.

Response (200 OK)

FieldTypeDescription
methodsMethod[]Array of available methods: { slug, name, network, min_amount, max_amount, fee_pct, logo_url, requires_tag }
2.

Validation Pipeline

Checks run in sequence. The first failing check stops the pipeline and returns an error. The Orchestrator is called only if all checks pass.

1
JWT present & valid
401
UNAUTHORIZED

Auth middleware already ran -- Router trusts the injected user context

2
Brand resolved
400
BRAND_NOT_RESOLVED

brand_id must be present in JWT claims. Router rejects requests without a resolved brand.

3
Required fields present
422
VALIDATION_ERROR

Checks that amount, currency, method are non-null and match expected types

4
Currency supported
422
CURRENCY_NOT_SUPPORTED

ISO 4217 code must be in the brand's allowed currency list

5
Method available for geo
422
METHOD_NOT_AVAILABLE

Checks payment_methods cache: method must be active for the player's country

6
Amount within PSP limits
422
AMOUNT_OUT_OF_RANGE

amount must be ≥ min_amount and ≤ max_amount from payment_methods cache

7
Balance check (withdrawal)
422
INSUFFICIENT_BALANCE
Phase 3

For withdrawals only: player balance must be ≥ amount. Phase 3 -- stub returns 501 in Phase 2.

All checks passed → forward to Orchestrator
3.

Request Context

The Router enriches every request before forwarding it downstream. These fields are available to the Orchestrator, Adapters, and State Machine without additional calls.

FieldSourceDescription
user_idJWT claimAuthenticated player identifier
brand_idJWT claimTenant that owns this request
session_idJWT claimSession ID for fraud correlation
geoIP geolocationISO 3166-1 alpha-2 country code resolved from client IP
ipRequest headerClient IP (X-Forwarded-For or socket, sanitized)
directionRoute path"deposit" | "withdrawal" -- derived from which endpoint was called

Geolocation is resolved once in the Router and cached in the request context. It is not re-resolved in the Orchestrator or Adapters.

4.

Error Codes

HTTPCodeWhenRetry?
401
UNAUTHORIZEDJWT missing, expired, or invalid signatureNo
400
BRAND_NOT_RESOLVEDbrand_id not found in JWT claimsNo
422
VALIDATION_ERRORRequired fields missing or wrong typeNo
422
CURRENCY_NOT_SUPPORTEDCurrency not in brand's allowed listNo
422
METHOD_NOT_AVAILABLEMethod inactive for player's geoNo
422
AMOUNT_OUT_OF_RANGEamount < min_amount or > max_amountNo
429
RATE_LIMIT_EXCEEDEDRate limiter blocked the request (see Rate Limiting spec)Yes (after retry_after)
422
INSUFFICIENT_BALANCEWithdrawal amount exceeds player balance (Phase 3)No
501
NOT_IMPLEMENTEDWithdrawal endpoint stub in Phase 2No
DEPO44 | REQUEST ROUTER SPEC v1 | PHASE 2