Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.streamkap.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Stripe Webhook source receives events from your Stripe account at a dedicated HTTPS endpoint and routes each event to a Kafka topic based on its resource type (customers, payment intents, charges, invoices, subscriptions, products, prices, payouts, refunds, etc.). You point Stripe at the Streamkap-generated webhook URL, register the events you care about, and Streamkap takes care of parsing, key extraction, schema inference, and routing. For initial loads or ad-hoc backfills, the source can also snapshot data directly from the Stripe REST API using your Stripe secret key.
This connector is in Beta. Behaviors and defaults may change before general availability.

Prerequisites

  • A Stripe account with Administrator access (required to manage webhooks and API keys).
  • Your Stripe Secret key (sk_live_xxx for production or sk_test_xxx for test mode), available at dashboard.stripe.com/apikeys.
  • A Streamkap workspace with permission to create source connectors.
  • A clear list of the Stripe resources you want to capture (customers, payment intents, invoices, etc.).

How It Works

  1. Endpoint provisioning — When you create the source, Streamkap generates a unique HTTPS webhook URL and an API key.
  2. Stripe subscriptions — In Stripe Workbench, you register a webhook destination pointing at the Streamkap URL with the API key passed as a query parameter, and select the events to deliver.
  3. Event-type routing — Each incoming request carries an event in its JSON body with a type field (customer.created, payment_intent.succeeded, etc.). The Stripe payload router takes the first segment as the resource — customer.* events go to the customer topic, payment_intent.* events go to payment_intent, and so on. The connector extracts data.object as the Kafka record value.
  4. Key extraction — The router pulls the resource id (e.g. cus_abc123, pi_xyz789) from data.object and uses it as the Kafka message key, enabling upsert-style consumption downstream.
  5. Signature verification (recommended) — When you provide the Stripe signing secret (whsec_xxx), each payload is verified against the Stripe-Signature header using HMAC-SHA256. Invalid payloads are rejected and (if configured) routed to the DLQ.
  6. Optional fan-out — Stripe’s list objects (line items, refunds, subscription items) can be fanned out into their own topics.
  7. Optional snapshot — For initial loads or ad-hoc backfills, the source queries the Stripe REST API with cursor pagination and emits records alongside the live webhook stream.

Streamkap Setup

1. Create the Source

  1. Navigate to Sources and choose Stripe.
  2. Give the source a memorable Name (for example, stripe-prod).

2. Connection Settings (Auth tab)

FieldRequiredDescription
Webhook URLAutoRead-only. Endpoint that Stripe posts events to. Generated on save. Append ?api_key=<API_KEY> when registering the webhook destination in Stripe.
API KeyAutoRead-only and encrypted. Sent by Stripe as the api_key query parameter to authenticate each request. Generated on save.
Signing SecretStrongly recommendedStripe webhook signing secret (whsec_xxx) from the webhook destination in Stripe Workbench. When set, every payload is verified against the Stripe-Signature header. Leave empty to skip verification (testing only).
Stripe API KeyRequired for snapshotsStripe Secret key (sk_live_xxx or sk_test_xxx) from dashboard.stripe.com/apikeys. Used by Streamkap to call the Stripe REST API during snapshots. Encrypted at rest.

3. Schema (Stripe Resources)

In the Schema tab, choose the resources you want to capture. The default is customer,payment_intent,charge,invoice. A resource is the first segment of the Stripe event type field — for example customer.created, customer.updated, and customer.subscription.created all map to the customer resource. Each resource becomes a Kafka topic of the same name. The dropdown is pre-loaded with the resources most commonly used in billing / SaaS CDC scenarios:
CategoryResources
Customers and subscriptionscustomer, subscription_schedule, setup_intent, payment_method, mandate
Payments and chargespayment_intent, charge, refund, payout, transfer, topup, application_fee, balance_transaction
Billinginvoice, invoiceitem, credit_note, coupon, promotion_code, plan, quote, tax_rate
Checkout and storefrontproduct, price, checkout
Otherreview, source
Any fan-out topics you configure (see Fan-out) are added automatically.
Advanced — other Stripe resources. Stripe has many more event types than listed above (Issuing, Financial Connections, Identity, Treasury, Climate, Terminal, etc.). The Schema field accepts any resource name — just type the first-segment of the Stripe event type and Streamkap will route it.
Snapshot support is narrower than webhook routing. Only customer, charge, payment_intent, invoice, subscription, product, price, payout, refund, payment_method, balance_transaction, coupon, plan, and setup_intent can be snapshotted via the Stripe REST API. All other resources stream via webhooks only.

4. Settings

FieldDefaultDescription
Unselected Resource BehaviorDEFAULT_TOPICWhat to do when an event arrives for a resource not in your Schema list. DEFAULT_TOPIC, SKIP, or FAIL.
Default Topic for Unselected ResourcesunknownTopic used when behavior is DEFAULT_TOPIC. Only shown when the option above is set to DEFAULT_TOPIC.
Include Event MetadatatrueKeep Stripe event metadata (_event_id, _event_type, _event_created, _api_version, _livemode, _previous_attributes) on the output record. Disable for upsert / state-table mode; keep enabled for audit-log mode and for deduplication on _event_id.
Fan-out Fields (advanced)(empty)Comma-separated list of nested lists to fan out into their own topics. Allowed values: invoice.lines, charge.refunds, subscription.items. See Fan-out.
Enable Dead Letter Queue (advanced)trueFailed records are written to a DLQ topic instead of crashing the connector.

5. Save and Copy the Endpoint

Save the source. Copy the Webhook URL and API Key — you will need them in the next section to configure Stripe.

Stripe Setup

Stripe does not support custom headers on webhook deliveries. Pass the Streamkap API key in the destination URL as a query parameter:
https://<webhook-url>?api_key=<API_KEY>

1. Get Your API Keys

  1. Go to dashboard.stripe.com/apikeys.
  2. Copy your Secret key (sk_test_xxx for test mode, sk_live_xxx for production).
  3. Use the toggle at the top of the dashboard to switch between test and live mode.
  4. Paste the Secret key into the Streamkap source’s Stripe API Key field in the Auth tab — this lets Streamkap call the Stripe REST API when you run a snapshot.
Note: Stripe replaced the old “Developers → Webhooks” page with Workbench. New accounts use Workbench by default.
  1. Go to dashboard.stripe.com and open Developers → Workbench (or dashboard.stripe.com/webhooks).
  2. Click Add destination (or Create new destination).
  3. Enter your endpoint URL: https://<webhook-url>?api_key=<API_KEY> using the values copied from Streamkap.
  4. Important — choose the “Snapshot” payload format, NOT “Thin” payload. Streamkap requires the full resource object in data.object. Thin-payload events (events whose object is v2.core.event) are not supported and should be left unselected.
  5. Select the events you want to deliver. Recommended starting set:
CategoryEvents
Customerscustomer.created, customer.updated, customer.deleted
Subscriptionscustomer.subscription.created, customer.subscription.updated, customer.subscription.deleted
Payment intentspayment_intent.succeeded, payment_intent.payment_failed, payment_intent.canceled
Chargescharge.succeeded, charge.refunded, charge.captured, charge.failed
Invoicesinvoice.created, invoice.finalized, invoice.paid, invoice.payment_failed
Products and pricesproduct.created, product.updated, product.deleted, price.created, price.updated, price.deleted
Payoutspayout.created, payout.paid, payout.failed
Refundsrefund.created, refund.updated
Checkoutcheckout.session.completed, checkout.session.expired
  1. Click Create.
  2. Open the destination’s detail page and copy the Signing secret (whsec_xxx). Paste it into Streamkap’s Signing Secret field in the Auth tab.

2 (Alternative). Register the Webhook via the Stripe API

For scripted setup, use curl with your Secret key:
curl https://api.stripe.com/v1/webhook_endpoints \
  -u sk_live_YOUR_SECRET_KEY: \
  -d url="https://<webhook-url>?api_key=<API_KEY>" \
  -d "enabled_events[]"="customer.created" \
  -d "enabled_events[]"="customer.updated" \
  -d "enabled_events[]"="customer.deleted" \
  -d "enabled_events[]"="customer.subscription.created" \
  -d "enabled_events[]"="customer.subscription.updated" \
  -d "enabled_events[]"="customer.subscription.deleted" \
  -d "enabled_events[]"="payment_intent.succeeded" \
  -d "enabled_events[]"="payment_intent.payment_failed" \
  -d "enabled_events[]"="charge.succeeded" \
  -d "enabled_events[]"="charge.refunded" \
  -d "enabled_events[]"="invoice.paid" \
  -d "enabled_events[]"="invoice.finalized" \
  -d "enabled_events[]"="product.created" \
  -d "enabled_events[]"="product.updated" \
  -d "enabled_events[]"="price.created" \
  -d "enabled_events[]"="price.updated"
The response includes a secret field (whsec_xxx) — copy it into Streamkap’s Signing Secret field. Or subscribe to all snapshot-payload events:
curl https://api.stripe.com/v1/webhook_endpoints \
  -u sk_live_YOUR_SECRET_KEY: \
  -d url="https://<webhook-url>?api_key=<API_KEY>" \
  -d "enabled_events[]"="*"

Local Testing with the Stripe CLI

stripe listen --forward-to "https://<webhook-url>?api_key=<API_KEY>"
The CLI prints a whsec_xxx signing secret on startup — paste it into Streamkap’s Signing Secret field. Trigger test events with:
stripe trigger customer.created
stripe trigger payment_intent.succeeded

Event Routing Reference

The payload router inspects the event type field on each incoming request and routes by the first segment.
Stripe Event TypeKafka TopicDefault Key
customer.created, customer.updated, customer.deletedcustomer{ id: cus_xxx }
customer.subscription.*customer{ id: sub_xxx }
payment_intent.succeeded, payment_intent.payment_failed, payment_intent.canceledpayment_intent{ id: pi_xxx }
charge.succeeded, charge.refunded, charge.captured, charge.failedcharge{ id: ch_xxx }
charge.dispute.*charge{ id: dp_xxx }
invoice.created, invoice.finalized, invoice.paid, invoice.payment_failedinvoice{ id: in_xxx }
product.*, price.*product / price{ id: prod_xxx } / { id: price_xxx }
payout.*, refund.*payout / refund{ id: po_xxx } / { id: re_xxx }
checkout.session.completed, checkout.session.expiredcheckout{ id: cs_xxx }
Events whose action ends in .deleted set __deleted: true on the output record so downstream sinks can issue tombstones. __op is emitted as a Kafka header (c create, u update, d delete, r snapshot). Each record additionally carries __changeType (CREATE, UPDATE, DELETE, SUCCEEDED, FAILED, REFUNDED, PAID, FINALIZED, SNAPSHOT, …) in the value.

Fan-out

Stripe resources contain nested list objects ({object: "list", data: [...]}) for line items, refunds, and subscription items. Most warehouse destinations can’t store these cleanly as a single column. Fan-out emits one record per list element to a dedicated topic so each child becomes its own row. Set Fan-out Fields to a comma-separated list from the allowed set:
invoice.lines, charge.refunds, subscription.items
Fan-out entryGenerated topicKey shape
invoice.linesinvoice_lines{ id: invoice_id, item_id: line_id }
charge.refundscharge_refunds{ id: charge_id, item_id: refund_id }
subscription.itemssubscription_items{ id: subscription_id, item_id: si_id }
Fan-out topics are added to the Schema list automatically — you do not need to register them manually. Each fan-out record contains the list element’s fields plus a _ctx_event_id for correlation back to the parent Stripe event.
Fan-out topics do not emit tombstone records when list items are removed (for example when a line item is removed from an invoice). To handle deletions, configure the downstream sink for delete-and-reinsert on each parent event, or treat each parent record as the source of truth and full-replace the child rows.

Signature Verification

Stripe signs every webhook with HMAC-SHA256. Streamkap parses the Stripe-Signature header (t=timestamp,v1=hex_signature) and verifies the payload against the signing secret you provide. To enable verification, paste your destination’s signing secret (whsec_xxx) into the Auth tab’s Signing Secret field. The connector checks all v1 signatures sent during secret rotation, so you can rotate without downtime. Leave the field empty only when testing — anyone who knows the connector URL could otherwise submit fake events.

Snapshot

Once your source is live, you can run a snapshot from the Streamkap UI to load historical data for selected resources. Webhook streaming continues to run in parallel — snapshot is a one-time backfill, not an alternative to live events.

Snapshottable Resources

Only these resources can be snapshotted via the Stripe REST API:
ResourceAPI Endpoint
customer/v1/customers
charge/v1/charges
payment_intent/v1/payment_intents
invoice/v1/invoices
subscription/v1/subscriptions
product/v1/products
price/v1/prices
payout/v1/payouts
refund/v1/refunds
payment_method/v1/payment_methods
balance_transaction/v1/balance_transactions
coupon/v1/coupons
plan/v1/plans
setup_intent/v1/setup_intents
All other resources you select in the Schema tab (checkout, quote, credit_note, transfer, etc.) cannot be snapshotted — they only receive live events via webhooks once you register them in Stripe. This is a limitation of the Stripe REST API, which exposes historical-fetch endpoints only for the resources above.

Troubleshooting

IssueCheck
401 Unauthorized on webhook deliveryVerify the URL registered in Stripe includes ?api_key=<API_KEY> with the value from the Streamkap source. Stripe does not pass custom headers, so the key must be in the query string.
Webhook not firingIn Stripe Workbench, open the destination and check delivery attempts. Stripe retries with exponential backoff up to 3 days in live mode (3 attempts in test mode).
Callback URL is not allowedThe callback URL must be HTTPS in live mode. For local testing, use the Stripe CLI’s stripe listen --forward-to command.
Snapshot does not startConfirm Stripe API Key is set in the Auth tab. The key needs read access for the resources you want to snapshot.
Access denied on snapshotVerify the Stripe API key is in the correct mode (live vs test) for the data you expect, and that it has not been revoked.
Events arrive in the unknown topicThe resource segment in the Stripe event type is not in your Schema list. Add it, or set Unselected Resource Behavior to SKIP.
Signature verification failedVerify the Signing Secret matches the whsec_xxx shown on the destination’s detail page in Stripe Workbench. Re-copy it if you regenerated it.
Thin-payload events rejectedStreamkap only supports Snapshot (v1) payloads. Events with "object": "v2.core.event" in their body are thin and won’t be processed. Deselect thin-only events in Workbench.
Retry stormsStripe retries up to 3 days in live mode. If the connector was down, expect a burst when it recovers. Check the destination’s delivery attempts in Workbench.

Limitations

  • The Stripe Webhook source is currently Beta.
  • Stripe expects a 2xx response promptly. The connector responds immediately and processes asynchronously; failures are captured in the DLQ when enabled.
  • Snapshot supports only the 14 resources listed above. Other resources (checkout, quote, credit_note, transfer, etc.) are streamed via webhooks only.
  • Only Stripe’s Snapshot (v1) payload format is supported. Thin payloads (v2.core.event) are not processed.
  • Stripe does not guarantee event ordering. Use the _event_created timestamp for ordering and _event_id for deduplication.
  • Maximum payload size is 50 MB and maximum header size is 64 KB.
  • The connector runs as a single task; horizontal scaling requires multiple source instances.

See Also