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": "user@example.com",
        "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.
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": "user@example.com",
        "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