Documentation Index
Fetch the complete documentation index at: https://docs.pcxpay.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Virtual Accounts Service is the financial core of PCX. It provisions and manages currency accounts (fiat), internal bank accounts, and internal crypto accounts for customers across any number of organisations. Every account is identified by an account_id and tied to both an org_id and a user_id.
Funds move through the service via six primitives: deposit, withdrawal, crypto fund, crypto withdrawal, internal transfer, and cross-rail payout. NGN operations route through SquadCo (virtual account provisioning) and Sarepay (bank transfers); non-NGN fiat and crypto operations route through Bridge.
Customer Onboarding
Before any accounts can be created, a customer must be onboarded. The two-step flow is:
POST /virtual-accounts/kyc — Provide the customer’s email and type (individual or business). The response returns a customer_id and a Terms of Service link the customer must accept.
POST /virtual-accounts/onboard — Once KYC is accepted, submit the full customer profile including org_id, user_id, name, phone, and an optional initial_balance. This creates the customer record and seeds any provisioned accounts.
Account Types
| Type | Endpoint | Description |
|---|
| Currency | POST /virtual-accounts/currency | Fiat account in any supported currency |
| Internal Bank | POST /virtual-accounts/internal/bank | Admin-provisioned bank account |
| Internal Crypto | POST /virtual-accounts/internal/crypto | Admin-provisioned crypto account |
All three account types share the same VirtualAccount shape and can be fetched by organisation (GET /virtual-accounts/org/{org_id}) or by user (GET /virtual-accounts/user/{user_id}).
Fund Operations
Fiat Deposits and Withdrawals
- Deposit (
POST /virtual-accounts/deposit) — Admin-only. Credits an amount directly to an account. For NGN accounts this routes through SquadCo.
- Withdrawal (
POST /virtual-accounts/withdraw) — Available to internal-admin and org-admin. For NGN withdrawals, the transaction is placed in pending status and requires an admin approval step before the Sarepay bank transfer fires. Non-NGN withdrawals may target a pre-linked external_account_id or be directed with a bank_code + beneficiary_account_number pair.
Crypto Funding and Withdrawal
Bridge is the provider for all crypto operations. Specify the payment_rail (blockchain network, e.g. ethereum, solana) and currency (token symbol, e.g. usdc).
- Crypto deposit —
POST /virtual-accounts/fund/crypto
- Crypto withdrawal —
POST /virtual-accounts/withdraw/crypto (requires a to_address)
Internal Transfers
POST /virtual-accounts/transfer moves funds between two accounts on the platform. Supply from_account_id, to_account_id, amount, and user_id. Both accounts must be active.
NGN Account Lookup
Before initiating a manual NGN withdrawal, use POST /virtual-accounts/ngn/account-lookup to verify the destination bank account via Sarepay. The response includes the verified account_name for confirmation.
Transactions
Virtual account transactions are separate from the main PCX transaction ledger. Each record carries a type (credit or debit), status (pending, completed, failed), and — for crypto operations — a payment_rail.
| Endpoint | Description |
|---|
GET /virtual-accounts/transactions/{transaction_id} | Single transaction. User identity is resolved from credentials; optionally pass user_id as a query parameter. |
GET /virtual-accounts/{account_id}/transactions | Paginated list filtered by type, status, and date range. |
GET /virtual-accounts/sarepay/transactions/status | Check NGN transfer status in Sarepay by transaction_id or reference. |
Pagination uses DynamoDB cursors: pass last_evaluated_key from the previous meta block.
External Accounts
External bank accounts are linked via Bridge and stored per customer_id. They serve as withdrawal destinations without requiring raw account numbers at withdrawal time.
POST /virtual-accounts/link — Link an account. Supports all major rail fields: account_number, sort_code (GBP), routing_number (USD), iban + bic (EUR), and address details for compliance.
GET /virtual-accounts/link — List linked accounts for a customer (filtered optionally by currency).
DELETE /virtual-accounts/link — Unlink an account by customer_id + external_account_id.
Activity Logs
Account activity is recorded in an immutable log accessible at GET /virtual-accounts/logs. Filter by org_id, account_id, event type, and date range. Aggregated metrics are available at GET /virtual-accounts/logs/metrics.
Fee Configurations
Fees are configured per currency and transaction type. Each configuration defines:
| Field | Description |
|---|
fee_structure | percentage or fixed_amount |
fee_value | Percentage (0–100) or flat amount |
min_fee / max_fee | Cap / floor for percentage structures |
fee_type | Category label (e.g. platform_fee) |
Use POST /virtual-accounts/fees/preview to calculate the fee for a specific transaction_type, amount, and currency before executing the operation. This is useful for building pre-confirmation UIs that show users their total cost.
Admin Suite
All endpoints under /virtual-accounts/admin/ require the internal-admin role. They provide:
- Full account and customer listings with advanced filtering
- Transaction approval and rejection — NGN withdrawals queue here before reaching Sarepay
- Cross-rail payout trigger — manually advances a transaction that has been funded on one rail to disburse on another
- Platform analytics — aggregated volume and transaction counts
SquadCo Admin
The /virtual-accounts/admin/squadco/ group provides direct visibility and control over the NGN SquadCo layer:
- View and create SquadCo virtual accounts
- List and manage pending NGN withdrawal approvals
- Manually process approved withdrawals via Sarepay
- Monitor the SquadCo wallet balance
Webhooks
Provider events (Bridge, SquadCo) arrive at POST /virtual-accounts/webhook/{provider_name}. Authentication is handled internally using provider-specific secrets — this endpoint is not called by PCX API consumers directly.
Authentication
All endpoints (except the webhook receiver) require a Bearer JWT in the Authorization header. Admin endpoints additionally enforce the internal-admin role; withdrawal also accepts org-admin.
Authorization: Bearer <token>