MyBotBoxMyBotBox

Stripe

Trigger workflows on Stripe payment, subscription, and invoice events.

The Stripe trigger receives any of Stripe's 200+ event types — payment intents, subscription lifecycle, invoice paid/failed, customer events — and starts a workflow with the affected Stripe object available downstream.

How to configure

  1. In your Stripe Dashboard open Developers → Webhooks → Add endpoint. Paste the Webhook URL as the endpoint URL. Test-mode keys deliver test-mode events; live-mode requires a separate endpoint.
  2. Pick the Events to send you care about (e.g. payment_intent.succeeded, customer.subscription.created, invoice.paid) — or Receive all events for general routing. After clicking Add endpoint, Stripe shows the endpoint's Signing secret (whsec_...). Copy it and paste into the trigger's signing-secret field — without it the trigger default-denies with 401.
  3. Stripe signs requests as Stripe-Signature: t=<ts>,v1=<hex> where v1 is HMAC-SHA256 of <ts>.<raw_body> using the whsec. The platform enforces a 5-minute timestamp tolerance to prevent replays. Read <stripe1.type> for the event name and <stripe1.data> for the affected object — e.g. <stripe1.data.object.amount> on a payment_intent.succeeded.
  4. Verify with Stripe's built-in tester — open the endpoint, click Send test webhook, choose payment_intent.succeeded, and confirm a 200 in the delivery log. Stripe retries failed deliveries with exponential backoff for up to 3 days; the trigger ACKs 200 immediately and fans out asynchronously.

Signature format

HeaderValue
Stripe-Signaturet=<unix-seconds>,v1=<hex> — v1 is HMAC-SHA256 of <t>.<raw_body> with the whsec_... secret

Replay window: 5 minutes from t. The Stripe event.id (e.g. evt_3OabCDe…) is used as the webhook_event_dedup key, so Stripe's automatic retry behaviour produces zero duplicate workflow runs.

Sample payload (payment_intent.succeeded)

{
  "id": "evt_3OabCDeFgHiJkLmN1234",
  "object": "event",
  "api_version": "2025-09-30.clover",
  "created": 1745700000,
  "type": "payment_intent.succeeded",
  "livemode": false,
  "pending_webhooks": 1,
  "request": {
    "id": "req_aBcDeFgHiJkLmNo",
    "idempotency_key": "idem_2026-04-26_pi_12345"
  },
  "data": {
    "object": {
      "id": "pi_3OabCDeFgHiJkLmN5678",
      "object": "payment_intent",
      "amount": 4999,
      "amount_capturable": 0,
      "amount_received": 4999,
      "currency": "usd",
      "customer": "cus_QXyzABCDEFG",
      "description": "Pro plan — monthly",
      "metadata": { "workspaceId": "ws_42", "planId": "pro_monthly" },
      "payment_method": "pm_1OabCDeFgHiJkLmN",
      "payment_method_types": ["card"],
      "receipt_email": "alex@example.com",
      "status": "succeeded",
      "latest_charge": "ch_3OabCDeFgHiJkLmN1234",
      "created": 1745699998
    }
  }
}

Verify with the bundled scripts

bun apps/sat/tests/staging/triggers/stripe/verify.ts \
  https://mybotbox.com/api/webhooks/trigger/<path> \
  --secret=whsec_<your-test-secret>
python3 apps/sat/tests/staging/triggers/stripe/verify.py \
  https://mybotbox.com/api/webhooks/trigger/<path> \
  --secret=whsec_<your-test-secret>

Source: apps/sat/tests/staging/triggers/stripe/.

Troubleshooting

  • 401 on every event — wrong whsec_... pasted in the trigger. Each endpoint has its own signing secret — copy the one for the endpoint Stripe is calling. Live-mode and test-mode endpoints have separate secrets.
  • 401 timestamp out of tolerance — caller clock drift, or you replayed a captured event much later. The platform enforces a 5-minute window; re-fire from the Stripe dashboard's tester to mint a fresh t.
  • Workflow doesn't fire on a real charge — check the Events filter on the endpoint. Send all events is broad but expensive; the more common Send specific events won't fire for event types you didn't tick.
  • Duplicate runs — extremely unlikely; Stripe rarely re-delivers the same evt_... and webhook_event_dedup would catch it. If you see them, confirm migration 0109 has been applied and check the delivery log for distinct event IDs.