Test mode is a full mirror of production - every endpoint and every webhook works identically. The main differences are that outcomes are synthetic, no live funds move, and data expires after 30 days.

Test mode keys

Test keys are distinguished by prefix:
pk_test_...   sk_test_...   whsec_test_...
You can’t accidentally run a test-mode call against live data - the key prefix and base URL both enforce isolation.

Verification test data

Test mode supports deterministic verification outcomes so you can exercise approval, review, and failure paths without touching live users. Use the test profiles configured for your account rather than live customer data.

Payment test data

When payments are enabled in test mode, use the designated test instruments for your account to simulate success, decline, and additional confirmation flows. Keep those values in internal runbooks rather than shipping them in production code.

Replay events from the dashboard

The webhook delivery log under Developers → Webhooks → Deliveries lets you replay any past event with one click. Use this to iterate on your handler without needing to trigger real user actions.

Local webhook development

Webhooks need a public URL. For local dev, tunnel your server with ngrok or Cloudflare Tunnel and register the tunnel URL as a test-mode webhook endpoint:
ngrok http 3000
# → https://abc123.ngrok-free.app
Register that URL in the dashboard, then re-run the API call that emits the event you want to test. You can also hit Replay in the delivery log to re-send without a user action.

Automated test patterns

1

Create a short-lived tenant per test run

Platform-tier accounts can create tenants programmatically. Use a per-suite tenant so tests don’t interfere with each other; tear it down in afterAll.
2

Record fixture events

Capture a real webhook payload once from test mode, then stub it as a POST in your unit tests. That way you don’t need the tunnel running in CI.
3

Use idempotency keys

Tests that re-run should produce the same state. Idempotency keys make retries safe and repeatable.

CI recipe

GitHub Actions
name: integration
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    env:
      GELDSTUCK_PUBLIC_KEY:     ${{ secrets.GELDSTUCK_TEST_PUBLIC_KEY }}
      GELDSTUCK_SECRET_KEY:     ${{ secrets.GELDSTUCK_TEST_SECRET_KEY }}
      GELDSTUCK_WEBHOOK_SECRET: ${{ secrets.GELDSTUCK_TEST_WEBHOOK_SECRET }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci
      - run: npm test