> ## Documentation Index
> Fetch the complete documentation index at: https://docs.searchcompany.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Stripe Webhook

> Handle Stripe webhook events to sync subscription status with Clerk

This endpoint receives webhook events from Stripe and updates the corresponding Clerk organization and user metadata to keep subscription status in sync.

<Note>
  **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.
</Note>

## Headers

<ParamField header="stripe-signature" type="string" required>
  Stripe webhook signature for verifying the request authenticity
</ParamField>

## 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

<ResponseField name="status" type="string">
  `"success"` when the webhook was processed successfully
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  # 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"
        }
      }
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "status": "success"
  }
  ```
</ResponseExample>

## Errors

| Status | Description                                 |
| ------ | ------------------------------------------- |
| 400    | Invalid payload or invalid Stripe signature |

## Stripe Dashboard Configuration

To configure this webhook in Stripe:

1. Go to [Stripe Dashboard → Developers → Webhooks](https://dashboard.stripe.com/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

| Variable                | Description                                     |
| ----------------------- | ----------------------------------------------- |
| `STRIPE_API_KEY`        | Stripe API secret key                           |
| `STRIPE_WEBHOOK_SECRET` | Webhook signing secret from Stripe Dashboard    |
| `CLERK_SECRET_KEY`      | Clerk secret key for updating user/org metadata |
