Via One — Live Transaction Console¶
User Manual¶
Version: 1.0
Document date: May 2026
Audience: Internal operations, on-call engineers, partner-facing support
1. What is the Live Transaction Console?¶
The Live Transaction Console (the "cockpit") is a single web page that shows everything moving through the Via One platform in real time. Think of it as Wireshark for business transactions, but business-friendly: no protocol jargon, no command line, no SSH.
It answers three questions in one place:
| Question | Tab |
|---|---|
| Who is calling us right now? (every API hit, every login, every topup attempt) | Inbound |
| Who are we calling right now? (every TEMM, Altamira, PPN, CellPay, Pockyt, etc. call we make) | Outbound (Providers) |
| Are our webhook deliveries to partners landing? | Webhooks |
The page auto-refreshes every 2 seconds, so you watch traffic happen as it happens. Click any row to expand and see the full request body, headers, and response — with sensitive fields automatically masked.
When to use it¶
- A partner says "my call failed" → open the console, filter by their tenant, find their request in seconds, see exactly what they sent and what we returned.
- A provider integration acts up → open the Outbound tab, filter by provider name, see the response codes and latency profile.
- You want a sanity check that traffic is flowing → open it during a launch window, watch the heartbeat.
- You're auditing what happened in a 30-day window → use the time filter and the search box to scope down to the events that matter.
2. How to access it¶
URL¶
| Environment | URL |
|---|---|
| Production | https://app.via.one/console/ (when live — check with engineering before relying on this) |
| Staging | https://latcom-fix-staging-staging.up.railway.app/console/ |
Authentication¶
The console requires an admin JWT token (the same admin gate as /api/admin/*). Tokens are short-lived (1 hour) for security.
To get a fresh staging token, an engineer can run:
…and paste the output into the Admin JWT field at the top of the page, then click Save. The token is stored in your browser's local storage and used automatically for every subsequent call until you click Clear or it expires.
If you see "Auth needed" or 401 errors, your token has expired — get a fresh one.
3. Tour of the interface¶
Header strip¶
┌─ Live Transaction Console ──────────────── ● Live ☑ Auto-refresh 2s ─┐
│ Inbound API hits, outbound provider calls, and webhook deliveries. │
└────────────────────────────────────────────────────────────────────────┘
- ● Live indicator — pulses green when polling is active, grey when paused, amber when authentication is needed, red when there's a backend error.
- Auto-refresh checkbox — toggle the 2-second polling. Turn off if you want the view to freeze (e.g., taking a screenshot or studying a specific row).
Auth bar¶
Paste, save, done. The dots are the masked token (it's a password input, not a security risk).
Summary cards¶
┌─ Inbound (5 min) ──┐ ┌─ Outbound providers (5 min) ┐ ┌─ Webhooks (5 min) ┐
│ 142 120 ok 22 err │ │ 47 41 ok 6 err │ │ 18 15 ok 3 err │
└─────────────────────┘ └─────────────────────────────┘ └───────────────────┘
Three live counters showing the last 5 minutes of activity in each stream. Updates every 2 seconds.
Tab navigation¶
Three tabs along the top — Inbound, Outbound (Providers), Webhooks. Click to switch. The currently-selected tab is highlighted blue with an underline.
Filter row¶
| Control | What it does |
|---|---|
| Search box | Free-text filter. Matches the path (/api/dislogin), partner code (latcomdigital), provider name (TELEFONICA), or webhook event name. Case-insensitive. |
| Status dropdown | "Any" / "OK" (2xx-equivalent) / "Errors only" (anything that failed). |
| Time window | "Last 15 min" / "Last 1 hour" / "Last 6 hours" / "Last 24 hours". The summary cards always show 5 minutes regardless. |
| Refresh now | Force-fetch even if auto-refresh is paused. |
| Row counter | Shows how many rows match your current filters. |
Table¶
The columns differ per tab; details below. Rows are listed newest-first. Click any row to expand it — an inline panel opens showing the full request and response as formatted JSON.
4. The three tabs in detail¶
4.1 Inbound tab — every API request hitting us¶
| Column | Example | What it means |
|---|---|---|
| Time | 21:12:47.280 |
Request timestamp (UTC, sub-second precision) |
| Partner | latcomdigital |
Tenant code if the request was authenticated; — if anonymous (e.g., login attempts or attacks) |
| Method | POST |
HTTP verb (GET, POST, etc.) |
| Path | /api/dislogin |
Request path (no query string) |
| Status | 200 (green) 401 (yellow) 500 (red) |
HTTP response code |
| Latency | 17 ms |
How long the request took, end-to-end |
| IP | 5.78.104.144 |
Best-effort client IP (handles Fastly + Railway forwarding chain) |
Click a row to expand — you'll see:
- Full request headers (with Authorization, x-api-key, etc. redacted to [REDACTED] or first-8-chars + …)
- Full request body (with card numbers, CVVs, PINs, passwords masked)
- Full response summary (top-level fields, nested objects shown as [object] to bound size)
- Request ID and correlation ID if the client sent one
Useful patterns:
- "Show me only Latcom Digital's traffic" → type latcomdigital in search
- "Show me only failures" → status filter = "Errors only"
- "Show me only login attempts" → search dislogin or login
- "Show me brute-force attempts" → search dislogin + status = "Errors only"
4.2 Outbound (Providers) tab — every call we make to providers¶
| Column | Example | What it means |
|---|---|---|
| Time | 20:02:04 |
When we initiated the call |
| Provider | TELEFONICA, ALTAMIRA, PPN, CELLPAY, POCKYT, MUWE, etc. |
Which provider we hit |
| Type | TAE, PAQUETE, BILLPAY, BALANCE, REVERSAL |
What kind of operation |
| SKU | TFE_150_MXN, GLO01B_6M2D_P1, PQRI6M2DP |
Product SKU sent (or wire SKU after translation) |
| Destination | 5537686648 |
Phone number, account, or beneficiary identifier (last-4 visible only) |
| Amount | 30.00 MXN, 1.75 USD |
Transaction value |
| Status | SUCCESS (green) FAILED (red) TIMEOUT (red) PENDING (grey) |
Outcome |
| Latency | 3044 ms |
Provider round-trip time |
Click a row to see the full ISO8583 fields (STAN, RRN, auth code, MTI request/response, processing code), provider-specific metadata, and the full request and response payloads from the provider.
Useful patterns:
- "Are TEMM cert calls succeeding?" → search TELEFONICA, time window = last hour
- "Why did Latcom Digital's last paquete fail?" → search the destination phone number, expand the row, look at the response code in the response_payload
- "Provider X has been slow today" → search the provider name, look at the latency column trend
4.3 Webhooks tab — every callback we deliver to partners¶
| Column | Example | What it means |
|---|---|---|
| Time | 19:30:00 |
Delivery attempt timestamp |
| Partner | latcomdigital |
Customer ID receiving the webhook |
| Endpoint | order_fulfillment_callbacks |
Which configured webhook endpoint |
| Event | order.delivered, order.failed, cashapp.success |
Event name |
| State | delivered (green) pending (info) retrying (yellow) dead (red) |
Delivery state from the queue |
| Last code | 200, 404, 500 |
HTTP code from the partner's last delivery attempt |
| Attempts | 1, 3, 5 |
How many tries we've made |
Click a row to see the full payload we sent, the partner's response body, and the retry history (per-attempt timestamps and error messages).
Useful patterns:
- "Are partner webhooks landing?" → time window = last hour, status = OK only
- "Show me all dead-letter webhooks" → status = errors only
- "Did Pockyt's order callback ever reach us?" → search pockyt
5. Privacy & redaction¶
The console never stores raw secrets. Before any data hits the database, the request-logger middleware automatically redacts:
| Field type | Treatment |
|---|---|
| Authorization headers, API keys, tokens, cookies, passwords, secrets | Replaced with [REDACTED] (first 8 chars kept for tracing only) |
| Card numbers (PAN) — any 13–19 digit run | ****<last4> (e.g., ****5832) |
| CVV / CVC / PIN fields | [REDACTED] |
| Phone numbers in known phone fields | Last 4 digits visible only (e.g., ********5678) |
| Email addresses | First char + domain (e.g., r***@gmail.com) |
| Bodies larger than 32 KB | Stored as a placeholder { _truncated: true, _original_size_bytes: N } |
What's still fully visible: transaction amounts, currencies, status codes, partner/provider IDs, transaction IDs, error messages, paths, latency profiles, IP addresses.
Retention: Inbound rows expire after 30 days. Outbound and webhook tables have their own retention managed by their respective subsystems.
6. Common workflows / playbooks¶
"Partner says my call failed at 14:32"¶
- Set time window to Last 1 hour.
- Switch to Inbound tab.
- Type the partner's tenant code (
latcomdigital,HAZ_001,RISE_HOLDINGS_001, etc.) in search. - Find the timestamp matching their report.
- Click the row to expand — read the request body and the response.
- If the inbound is fine but the partner saw an error, switch to Outbound (Providers) for the same time window — find the matching provider call.
"Why did this transaction not get processed?"¶
- Find the transaction's
dist_transid(from the partner's report or your own logs). - Inbound tab → search the dist_transid (it appears in the request body summary).
- Click → confirm we received the request and what we returned.
- Outbound (Providers) tab → find the same time window → look for the matching provider call.
- Webhooks tab → did we send the partner a callback? Did it land?
"Show me what's happening right now during this launch test"¶
- Open the console.
- Auto-refresh ON.
- Filter by the test partner if you only want their traffic.
- Watch the summary cards — total counts and OK/error split update every 2 seconds.
- New rows appear at the top of the table as they happen.
"Audit the last 24 hours of provider failures"¶
- Switch to Outbound (Providers) tab.
- Time window = Last 24 hours.
- Status = Errors only.
- Sort/scan by provider — anomalies stand out fast.
7. Limitations & known gaps¶
This is v1, internal-only. Things it deliberately doesn't do (yet):
| Limitation | Why / when it'll change |
|---|---|
| No partner-shareable read-only links | v2 — once internal version is proven |
| No SSE / WebSocket push (uses 2-second polling) | Polling is good enough for v1 — adding SSE is ~50 lines if needed |
| No CSV / PDF export from the UI | Use the underlying SQL queries directly for now |
| No alerting / threshold rules | Console is observability only — alerting lives in NOC + WhatsApp ops bot |
/api/tn/latcom doesn't fully exercise the new payments-iso8583 path |
The payments_iso8583_enabled customer flag only short-circuits /api/v1/topup. /api/tn/latcom always routes via Optimus router. Console captures everything regardless. |
8. Troubleshooting¶
"My JWT was accepted but no rows appear"¶
Either: - Time window too narrow — bump to "Last 1 hour" or "Last 24 hours". - Filter too restrictive — clear the search box, set status to "Any". - No traffic in the window — generate some yourself by hitting any endpoint. - Wrong environment — staging and production are separate; you're not seeing prod data on staging or vice versa.
"JWT keeps getting rejected"¶
- Tokens are 1-hour. Generate a fresh one.
- Make sure you're using the staging secret on the staging URL, prod secret on the prod URL — they're different.
- Confirm you didn't accidentally copy a trailing space or paste a wrong character.
"Console URL returns 404"¶
- The console may not be deployed to that environment yet. Production deploy is gated on go-live readiness; check with engineering.
"Auto-refresh seems stuck"¶
- Click the ● Live indicator area. If it's grey or red, polling is paused or errored.
- Click Refresh now to force-fetch.
- Check the browser console (F12 → Console) for any JavaScript errors.
"I see eyJhbGci... showing up as if it were a partner key"¶
- That's the bug from May 5 2026 — the middleware was treating admin JWTs as partner API keys. Fixed in commit
54779cad. If you still see it, your environment may be running an older build.
9. Glossary¶
| Term | Meaning |
|---|---|
| F39 | ISO8583 response code field. 00 = approved. Others = various decline / error states (e.g., 05 "Do not honor", 51 "Insufficient funds", 83 "Respuesta desconocida") |
| STAN | System Trace Audit Number — a 6-digit ID Telefónica's gateway assigns to each transaction |
| RRN | Retrieval Reference Number — 12-digit reference for tracking |
| MSISDN | Mobile Subscriber ISDN — phone number in international format (we store 10-digit MX numbers without country code) |
| Cert mode | Telefónica's certification environment (vs production). When PAYMENTS_CERT_MODE=true, paquete attempts get rewritten at the wire to known-good cert SKU + amount (code=21, amount=150 MXN) |
| Tenant | A logical partner organization. OPTIMUS, HAZ_GROUP, RISE FINANCE, VIAONE, VIAONE_MASTER. Each tenant has its own customers, route mappings, balances |
| Customer / distributor | An individual API consumer within a tenant. latcomdigital is a customer under the OPTIMUS tenant |
| Partner | Used loosely as a synonym for tenant or customer, depending on context |
| Provider | An external upstream we call to fulfill transactions: TELEFONICA, ALTAMIRA, PPN, CELLPAY, POCKYT, MUWE, TAECEL, ALTAN, etc. |
10. Technical reference (for engineers)¶
| Component | Location |
|---|---|
| Console UI | public/console/index.html |
| Backend API | routes/consoleRoutes.js (mounted at /api/console/*) |
| Inbound capture | middleware/request-logger.js |
| Database table | api_requests (migration 1779200000000_api_request_log.sql) |
| Other data sources | provider_transactions, webhook_deliveries, webhook_endpoints |
API endpoints (all admin-auth gated):
GET /api/console/summary — 5-minute counters per tab
GET /api/console/inbound?since=&q=&limit= — inbound table query
GET /api/console/outbound?since=&q=&limit= — outbound table query
GET /api/console/webhooks?since=&q=&limit= — webhooks table query
GET /api/console/{type}/:id — single-row detail (full JSON)
Skip-paths excluded from logging (to avoid noise):
/health, /favicon, /console, /api/console/, /app/, /operator/, /customer/, /static/, /assets/, /o/.
11. Document history¶
| Version | Date | Notes |
|---|---|---|
| 1.0 | 2026-05-06 | Initial release. Covers staging deployment + 2 May 5 bugfixes (self-poll noise, admin JWT-as-partner-key). |