RRelo Docs
ApiGuides

Stripe

Integración de Stripe vía webhooks server-side: eventos soportados, verificación de firma, atribución de compras y suscripciones.

Integration Guide

Stripe Webhooks

Connect Stripe to RELO's data backbone for CPA tracking, purchase attribution, and subscription lifecycle monitoring via server-side webhooks.

Overview

RELO's data backbone accepts Stripe webhooks for CPA (Cost Per Action) tracking. When a customer completes a purchase or a subscription event occurs, Stripe sends the event payload to our Go ingest service. These are processed as model.Event records and written to ClickHouse for analytics.

The integration supports one-time purchases, subscription checkouts, and full subscription lifecycle tracking (creation, updates, cancellations).

Supported Events

checkout.session.completed

Fired when a customer completes a Stripe Checkout session. Covers both one-time purchases and initial subscription checkouts. Revenue is extracted from the session's amount_total.

invoice.paid

Fired when a subscription invoice is paid. The handler skips invoices with billing_reason: subscription_create to avoid double-counting the initial checkout (already captured by checkout.session.completed). Only subsequent renewal invoices are processed.

customer.subscription.created / updated / deleted

Subscription lifecycle events. Tracked as custom events for analytics (churn analysis, plan changes, etc.). These events do not carry revenue and do not trigger identity resolution.

Setup

  1. Webhook URL
    Configure your Stripe webhook endpoint to point to:

    POST https://ingest.relo.mx/postback/stripe

  2. Signing Secret
    Retrieve the webhook signing secret from Stripe and set it as the STRIPE_WEBHOOK_SECRET environment variable on the backbone server. Without this, all incoming requests will be rejected.

  3. Events to Subscribe
    Select the following events when configuring the webhook:

    • checkout.session.completed
    • invoice.paid
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted

Important The signing secret must be configured before any events will be accepted. If STRIPE_WEBHOOK_SECRET is empty or missing, the service rejects all Stripe webhook requests with a signature verification failure.

How It Works

Diagrama interactivo
Cargando diagrama…

Purchase Events

For checkout.session.completed and invoice.paid, the handler extracts revenue from the event payload (amount_total or amount_paid, converted from cents to the base currency unit). Identity resolution links the customer email to a unified device ID via DragonflyDB.

Subscription Lifecycle Events

For customer.subscription.* events, the handler records the plan, status, and billing interval as custom event properties. These events do not include customer email in the subscription object, so identity resolution is skipped.

Identity Resolution

Events with Identity Resolution

  • checkout.session.completed — Email extracted from the session's customer_email or customer_details.email
  • invoice.paid — Email extracted from the invoice's customer_email

Events without Identity Resolution

  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted

The Stripe subscription object does not contain the customer's email address. These events are recorded without a linked device ID.

The identity resolution flow for purchase events:

Customer email (from Stripe event)
  -> SHA-256 hash
  -> DragonflyDB lookup: id:email:{hash} -> unified device_id
  -> Event written with resolved device_id

Event Mapping

Stripe events are mapped to RELO's universal event schema as follows:

Stripe Event

RELO event_name

event_type

channel

checkout.session.completed

purchase

purchase

stripe

invoice.paid (subscription_cycle)

subscription_renewal

custom

stripe

invoice.paid (subscription_create)

Skipped — already captured by checkout.session.completed

customer.subscription.created

subscription_created

custom

stripe

customer.subscription.updated

subscription_updated

custom

stripe

customer.subscription.deleted

subscription_cancelled

custom

stripe

Note All events are written to the ClickHouse events table with media_source = 'stripe' and channel = 'stripe'. The order_id field is populated with the Stripe session ID, invoice ID, or subscription ID depending on the event type.

Testing

Stripe CLI (Local Development)

Forward Stripe test events to your local backbone instance:

stripe listen --forward-to localhost:4080/postback/stripe

Then trigger test events from another terminal:

stripe trigger checkout.session.completed
stripe trigger invoice.paid
stripe trigger customer.subscription.created

Stripe Test Mode

You can also configure the webhook endpoint in Stripe's test mode to point to your staging or production URL. Use the Stripe test card for generating purchase events:

Test Card

4242 4242 4242 4242

Any future expiry date, any CVC, any billing postal code.

Verifying Events

After triggering a test event, verify it was ingested by querying ClickHouse:

SELECT event_id, event_name, event_type, revenue, order_id
FROM events
WHERE media_source = 'stripe'
ORDER BY event_time DESC
LIMIT 10;

Security

  • HMAC-SHA256 signature verification on every incoming request using the Stripe-Signature header
  • 5-minute timestamp tolerance — events with a timestamp older than 5 minutes are rejected to prevent replay attacks
  • Empty or missing signing secret causes all requests to be rejected — the service never accepts unverified payloads
  • No sensitive data stored — customer emails are SHA-256 hashed before being used in identity resolution; raw emails are never persisted

On this page