Getting started
PandaPayLens explains payment errors and reconstructs event timelines from the JSON you already have.
1. Provide input
Open the analyzer and paste JSON, drop .json or .jsonl files, or load an example. You can mix several files in one session; events from different files are correlated if they share identifiers.
Accepted shapes:
- A single JSON object (an API error, a PaymentIntent, a webhook body).
- A JSON array of such objects.
- JSON Lines: one object per line.
- URL-encoded form data, as many postbacks and callbacks are sent.
- A raw HTTP request or response, including its status line and headers, or a callback URL with the data in its query string.
- Plain text with one
name: valuepair per line, as some legacy APIs answer. - An XML document. Documents with a DOCTYPE or entity declarations are rejected for safety.
Default limits: 5 MB per file, 20 MB per session, 5,000 records, nesting depth 64. Larger or deeper input fails with a clear message instead of freezing the page.
Recording when you received a webhook
Providers include when an event was created, but not when your system received it. To analyze arrival order, wrap each record in the PandaPayLens envelope:
{ "receivedAt": "2026-10-25T10:00:03Z", "payload": { …the webhook body… } }Without it, PandaPayLens assumes the order of records in your input is the arrival order and says so in every affected finding.
2. Read the results
- Error decoder: the code, category, explanation, suggested next step, retry guidance, confidence and documentation link. Stripe's
code,decline_codeandadvice_codestay separate; the advice code takes precedence for retry guidance. - Timeline: events grouped into transactions by explicit identifiers (PaymentIntent, charge, pspReference, originalReference). Switch between event time and receipt order, and filter by provider, type, status, reference or time range.
- Data inspector: each input record after redaction, with the reasons it was or wasn't recognized.
- Findings: deterministic rules with severity, confidence, evidence, limitations and a recommended next step.
Retry guidance
| Value | Meaning |
|---|---|
do_not_retry | The same request will fail again, or retrying could be penalized. |
customer_action_required | The customer must authenticate, correct details, or choose another method first. |
retry_conditionally | A later attempt may succeed. When the original outcome is unknown, verify it first and reuse the idempotency key. |
safe_to_retry_technical_request | A technical retry (with backoff and the same idempotency key) is appropriate. |
manual_review / unknown | No safe automatic conclusion is possible. |
These are diagnostic categories, not instructions to send a payment.
Findings
| Rule | What it reports |
|---|---|
DUPLICATE_DELIVERY | The same provider event appears more than once. Expected provider behavior, not proof of double processing. |
OUT_OF_ORDER_ARRIVAL | An event arrived after one created later. Not a defect by itself. |
CONFLICTING_OBSERVATIONS | Copies of one event report different states. |
PAYMENT_FAILURE | The provider reported a failed payment, capture or refund. |
UNRESOLVED_OUTCOME | No final success or failure is visible in the supplied events. |
POTENTIAL_STATE_INCONSISTENCY | States contradict documented transitions (e.g. a PaymentIntent changing after succeeded). |
POSSIBLE_RETRY_RISK | Unknown-outcome errors, repeated attempts after do-not-retry declines, or several authorised payments for one merchantReference. |
MISSING_REFERENCE | Events that cannot be linked to a payment. |
UNKNOWN_EVENT_TYPE | Event types PandaPayLens has no semantics for yet. |
3. Export
Download a JSON or Markdown report, or a PNG of the timeline. Reports include the analysis time, PandaPayLens and rule-catalog versions, recognized formats, events, findings, confidence, limitations and redaction status. Identifiers are masked unless you opt in; blocked fields such as card data and secrets are never exported.
Command line
npx pandapaylens analyze events.json
npx pandapaylens decode error.json --format markdown
npx pandapaylens timeline - < webhooks.jsonl
npx pandapaylens analyze log.json --fail-on medium # exit 1 on medium+ findings
npx pandapaylens examples # list bundled samplesExit codes: 0 ok, 1 findings at or above --fail-on, 2 invalid input, 3 unsupported provider or format, 4 internal error.
Library
// npm install pandapaylens
import { analyze, toMarkdownReport } from "pandapaylens";
const r = analyze(text); // or analyze(text, { provider: "adyen" })
if (r.ok) console.log(r.result.findings, toMarkdownReport(r.result));
else console.error(r.error.message);One package, pandapaylens, holds the command line tool and the library with every adapter. It has no runtime dependencies, runs offline and needs Node.js 22 or later.