Transaction record that is linked to every payment, loan, and payout. Where the Payment Service tracks how money moves (provider, method, routing), the Transaction Service tracks what moved and its outcome from a financial reporting perspective.
What it does
Transaction creation — A new transaction is normally created by the Payment Service via an internal Lambda invocation before the payment record is persisted. This ensures that a transaction always exists as a linked financial record for every payment. Thepayment_id field on the transaction connects the two records.
Transaction lifecycle — TransactionStatus progresses through initiated → pending → completed or failed. Status updates arrive via PATCH /transactions/{transaction_id} (admin only). The service normalises legacy status values (e.g. initialized maps to initiated) on read.
Transaction types — Three types exist: inbound (funds received by the user), outbound (funds sent by the user), and loan (instalment-based financial product). Loan transactions carry additional fields: compound_amount, duration, installment_amount, total_installments, installments_completed, outstanding_balance, next_due_date, start_date, and frequency.
Look-ups — A transaction can be resolved by its own transaction_id (GET /transactions/{transaction_id}) or by the linked payment_id (GET /transactions/payment/{payment_id}).
Filter endpoint — POST /transactions/filter accepts a multi-dimensional filter body (country, currency, payment method, status, user, org, date range) and returns matching transactions with a timestamp-based cursor for pagination.
Org loans and payouts — GET /transactions/org/{org_id} returns loan and payout transactions for an organisation. It accepts a type filter (loan or payout) and optional currency filter. Setting includeMetrics=true returns an additional metrics object with aggregate figures.
Analytics — The service exposes three tiers of analytics, all requiring internal-admin unless noted:
- User-scoped (
/analytics/user/{user_id},/analytics/payment-method-distribution/{user_id},/analytics/currency-distribution/{user_id},/analytics/status-distribution/{user_id}) — metrics for a single user. - Global — 16 endpoints covering aggregate counts, value distributions, failure analysis, trends, peak hours, domestic vs cross-border splits, 24-hour snapshots, and overall success rate. The
/analytics/success_rateendpoint is accessible to all authenticated users; it calculates success only over transactions that have reached a conclusive terminal state. - Org-scoped (
/analytics/org/{org_id}) — aggregate metrics scoped to a specific organisation.
Key concepts
| Concept | Description |
|---|---|
TransactionStatus | initiated → pending → completed / failed |
TransactionType | inbound, outbound, loan |
PaymentMethodType | bank_transfer, mobile_money, crypto, card |
Frequency | Loan repayment cadence: weekly, bi_weekly, monthly |
| Cursor pagination | User-facing list endpoints use last_evaluated_key (base64); admin list-all uses nextToken (JSON-encoded DynamoDB key) |
| Timestamp cursor | POST /transactions/filter uses a plain ISO timestamp string as last_evaluated_key |
entity_type | Defaults to "payment" — reserved for future entity types |
Authentication
All endpoints require a valid Bearer token. Admin endpoints additionally enforce theinternal-admin role via roles_required middleware. The GET /transactions/org/{org_id} endpoint also accepts org-admin. The GET /transactions/analytics/success_rate endpoint is open to all authenticated roles.