Read the transactions view
Payments → Transactions shows every completed or in-flight payment across all 5 rails in one table. This is the finance surface of the app.
The 5 rails
Section titled “The 5 rails”TwistCue’s payment stack is multi-rail. Every transaction lands here regardless of source:
| Rail | Platform tag | What it is |
|---|---|---|
| Store IAP | apple / google | Apple / Google in-app purchase for coin packs or subscriptions. Recognized via RevenueCat. |
| Cards (web) | card_web | Direct credit/debit via Charbel’s own card MID. Subs + top-ups, recurring via tokenization. |
| dLocal | dlocal_* (e.g. dlocal_fawry_eg) | Local wallets & cash vouchers: Fawry (EG), OVO/DANA (ID), GCash (PH). |
| pawaPay | pawapay_* (e.g. pawapay_mpesa_ke) | Mobile money: M-Pesa, MTN MoMo, Airtel Money. |
| VAS / DCB | vas_* (e.g. vas_etisalat_eg) | Direct-carrier-billing via adbilling.me stack: MSISDN + PIN funnel grants app entitlements. |
Filters
Section titled “Filters”Side panel:
| Filter | Values |
|---|---|
| Rail | multi-select from the 5 rails |
| Status | completed / pending / refunded / failed / disputed |
| Country | ISO-2 |
| Date range | UTC |
| Currency | USD, IDR, EGP, PHP, KES, … |
| User | search by user id / email |
Every filter is URL-state. Shareable views.
Columns
Section titled “Columns”| Column | Meaning |
|---|---|
| Created | Purchase/subscription event timestamp (UTC, local on hover). |
| User | Email or phone, clickable → User 360. Guest = “Guest (device:…)”. |
| Rail | Platform tag. |
| Kind | coin_pack / subscription / vas_entitlement / refund |
| Product | Product ID / SKU. |
| Amount | Native currency + USD equivalent in parens. |
| Coins granted | For coin packs: base coins + bonus coins. |
| Status | See below. |
| Transaction ID | Provider-side ID (Apple original_transaction_id, Stripe pi_…, dLocal payment_id, etc.). |
Statuses
Section titled “Statuses”| Status | Meaning |
|---|---|
completed | Payment cleared. Ledger credited. User has coins/access. |
pending | Webhook received but not confirmed (rare: usually a stuck async provider). |
failed | Payment rejected. No ledger movement. |
refunded | Full refund executed. Ledger reversed via sink_refund. |
partial_refunded | Partial refund (rare; some providers). Ledger reversed by the refunded amount. |
disputed | Chargeback opened at the card MID. Investigation pending. |
Detail view
Section titled “Detail view”Click a row → transaction detail:
- All fields from the list
- User 360 link
- Full webhook payload (for debugging)
- Ledger entries created by this transaction (double-entry pairs)
- Related unlocks (if the user spent from this purchase)
- Refund history if applicable
CSV export
Section titled “CSV export”Export CSV button (top-right), downloads the current filtered view. Uses /v1/admin/payments/transactions/export.csv. Rows are streamed, even a year of history is fine.
Reconciliation
Section titled “Reconciliation”Compare our view against provider reports at Reconciliation CSV.
Gotchas
Section titled “Gotchas”- Store IAP transactions can arrive minutes late: RevenueCat webhook delivery isn’t instant. If a support ticket says “I bought coins but they’re missing”, wait 2 minutes and refresh before assuming failure.
- VAS entitlements may not have a
transaction_id: adbilling.me passes an opaque token instead. The link back to the LP funnel is via theregion+subscription_idfields. - Currency conversion uses a daily rate stored server-side. USD amounts on the list page are informational; the ledger stores native cents.
API calls
Section titled “API calls”| Action | Endpoint |
|---|---|
| List transactions | GET /v1/admin/payments/transactions |
| Export CSV | GET /v1/admin/payments/transactions/export.csv |
| Transaction detail | GET /v1/admin/payments/transactions/:id |
Full details in API: Payments.