Skip to main content
POST
https://searchcompany-main.up.railway.app
/
webhooks
/
stripe
# This is typically called by Stripe, not manually
curl -X POST "https://searchcompany-main.up.railway.app/webhooks/stripe" \
  -H "Content-Type: application/json" \
  -H "stripe-signature: t=1234567890,v1=abc123..." \
  -d '{
    "type": "checkout.session.completed",
    "data": {
      "object": {
        "id": "cs_test_abc123",
        "customer": "cus_xyz789",
        "customer_email": "[email protected]",
        "subscription": "sub_def456",
        "client_reference_id": "nike"
      }
    }
  }'
{
  "status": "success"
}
This endpoint receives webhook events from Stripe and updates the corresponding Clerk organization and user metadata to keep subscription status in sync.
No authentication required - This is a public webhook endpoint. This endpoint is called by Stripe, not by your application directly. You must configure this URL in your Stripe Dashboard under Developers β†’ Webhooks.

Headers

stripe-signature
string
required
Stripe webhook signature for verifying the request authenticity

Request Body

The request body is a raw Stripe webhook event payload. The endpoint handles the following event types:

checkout.session.completed

Triggered when a customer completes a checkout session. Actions:
  • Links Stripe customer ID to Clerk organization via client_reference_id
  • Stores stripeCustomerId, stripeSubscriptionId, and subscriptionStatus in organization metadata
  • Updates user metadata for backwards compatibility
  • Clears subscription cache for immediate status update

customer.subscription.updated

Triggered when a subscription is updated (e.g., plan change, renewal). Actions:
  • Updates subscriptionStatus in Clerk user metadata
  • Sets status to "active" for active or trialing subscriptions
  • Sets status to "inactive" for other states

customer.subscription.deleted

Triggered when a subscription is cancelled or expires. Actions:
  • Updates subscriptionStatus to "cancelled" in Clerk user metadata

Response

status
string
"success" when the webhook was processed successfully
# This is typically called by Stripe, not manually
curl -X POST "https://searchcompany-main.up.railway.app/webhooks/stripe" \
  -H "Content-Type: application/json" \
  -H "stripe-signature: t=1234567890,v1=abc123..." \
  -d '{
    "type": "checkout.session.completed",
    "data": {
      "object": {
        "id": "cs_test_abc123",
        "customer": "cus_xyz789",
        "customer_email": "[email protected]",
        "subscription": "sub_def456",
        "client_reference_id": "nike"
      }
    }
  }'
{
  "status": "success"
}

Errors

StatusDescription
400Invalid payload or invalid Stripe signature

Stripe Dashboard Configuration

To configure this webhook in Stripe:
  1. Go to Stripe Dashboard β†’ Developers β†’ Webhooks
  2. Click β€œAdd endpoint”
  3. Enter the endpoint URL: https://searchcompany-main.up.railway.app/webhooks/stripe
  4. Select events to listen for:
    • checkout.session.completed
    • customer.subscription.updated
    • customer.subscription.deleted
  5. Copy the signing secret and set it as STRIPE_WEBHOOK_SECRET environment variable

Environment Variables

VariableDescription
STRIPE_API_KEYStripe API secret key
STRIPE_WEBHOOK_SECRETWebhook signing secret from Stripe Dashboard
CLERK_SECRET_KEYClerk secret key for updating user/org metadata