Webhooks
Inbound webhook handlers for Stripe and Clerk events.
Overview
Praxiom AI receives inbound webhooks from Stripe (billing events) and Clerk (user lifecycle events). These endpoints have no user authentication -- they are verified by provider-specific signatures.
Stripe Webhook
POST /api/webhooks/stripe
Handle Stripe webhook events. Verified by Stripe signature (no JWT auth required).
Headers
| Name | Required | Description |
|---|---|---|
stripe-signature | Yes | Stripe webhook signature for payload verification |
Handled Event Types
| Event | Action |
|---|---|
checkout.session.completed | Links Stripe customer to workspace; provisions boost packs; grants referral credits |
customer.subscription.created | Creates/updates subscription record with plan and period |
customer.subscription.updated | Updates plan, status, and period dates |
customer.subscription.deleted | Marks subscription as cancelled |
invoice.payment_succeeded | Activates subscription, resets period |
invoice.payment_failed | Sets subscription to past_due status |
Idempotency
Webhook events are deduplicated using the ProcessedStripeEvent table. If the same event ID is received twice, the second delivery returns {"status": "already_processed"}. Old events are probabilistically cleaned up after 90 days.
Response (200 OK)
{
"status": "ok"
}
Error Responses
| Status | Description |
|---|---|
| 400 | Invalid payload or signature |
| 400 | Webhook secret not configured |
Clerk Webhook
POST /api/webhooks/clerk
Handle Clerk user lifecycle events. Verified by Clerk webhook signature (no JWT auth required).
Handled Event Types
| Event | Action |
|---|---|
user.created | Creates a new user record in the database |
user.updated | Updates user profile (name, email, avatar) |
How It Works
- Clerk fires a webhook when a user signs up or updates their profile.
- The endpoint verifies the Clerk webhook signature.
- For
user.created, a newUserrecord is created with the Clerk ID, email, and name. - For
user.updated, the existing user record is updated with the new profile data.
Response (200 OK)
{
"status": "ok"
}
Auth Endpoint
GET /api/auth/me
Returns the current authenticated user's profile. This is not a webhook but is included here as part of the auth flow.
Example Request
curl https://api.praxiomai.xyz/api/auth/me \
-H "Authorization: Bearer $TOKEN"
Response (200 OK)
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"clerk_id": "user_2abc...",
"email": "pm@example.com",
"name": "Jane Doe",
"avatar_url": "https://img.clerk.com/...",
"has_product_access": true,
"is_founder": false,
"created_at": "2026-03-15T08:00:00Z"
}Was this helpful?