replay re-sends a captured request to your local server. It reads the request from the capture log and sends it straight to the local target, with no tunnel round trip and no credits spent. Use it to re-test a webhook handler after a fix without waiting for the provider to fire again.
# Re-send the latest captured request
npx otterkit replay hook-a1b2c3d4
# Re-send request #3 (1 = oldest, -1 = latest)
npx otterkit replay hook-a1b2c3d4 --index 3
# Explicit local target (needed for webhook captures and stopped tunnels)
npx otterkit replay hook-a1b2c3d4 --target 127.0.0.1:3000
# Machine-readable response for agents (body base64-encoded)
npx otterkit replay hook-a1b2c3d4 --jsonFor a running tunnel, the target defaults to that tunnel's host:port, so after otterkit tunnel 3000 --daemon a plain otterkit replay <subdomain> just works. Webhook endpoints have no local target, so pass --target. The exit code is 0 whenever the local server responds, even with a 4xx or 5xx, and 1 if it can't be reached.
Edit before sending#
npx otterkit replay hook-a1b2c3d4 --method PUT --path /v2/hook \
-H "X-Debug: 1" --body '{"event":"payment.failed"}'
# Edit individual JSON body fields instead of replacing the whole body
# (repeatable; values parse as JSON, so numbers stay numbers)
npx otterkit replay hook-a1b2c3d4 --set data.amount=999 --set data.livemode=falseEditing a signed request breaks its signature. Add --resign <provider> and --secret to sign the edited body again so your handler still accepts it. This works for Stripe, GitHub, Shopify, and Slack. See Send & Verify Events.