---
id: sm-clerk-webhooks
name: "clerk-webhooks"
url: https://skills.yangsir.net/skill/sm-clerk-webhooks
author: clerk
domain: ai-backend-engineering
tags: ["clerk", "webhooks", "api-integration", "event-driven-architecture", "backend-development"]
install_count: 7100
rating: 4.50 (50 reviews)
github: https://github.com/clerk/skills
---

# clerk-webhooks

> 掌握Clerk后端Webhook配置与管理，利用AI技能增强Clerk事件通知，实现系统间高效集成与响应。

**Stats**: 7,100 installs · 4.5/5 (50 reviews)

## Before / After 对比

### 增强Clerk集成，实现事件自动化

## Readme

# clerk-webhooks

# Webhooks

**Prerequisite**: Webhooks are asynchronous. Use for background tasks (sync, notifications), not synchronous flows.

## Documentation Reference

Task
Link

Overview
[https://clerk.com/docs/guides/development/webhooks/overview](https://clerk.com/docs/guides/development/webhooks/overview)

Sync to database
[https://clerk.com/docs/guides/development/webhooks/syncing](https://clerk.com/docs/guides/development/webhooks/syncing)

Debugging
[https://clerk.com/docs/guides/development/webhooks/debugging](https://clerk.com/docs/guides/development/webhooks/debugging)

Event catalog
[https://dashboard.clerk.com/~/webhooks](https://dashboard.clerk.com/~/webhooks) (Event Catalog tab)

## Quick Start

- Create endpoint at `app/api/webhooks/route.ts`

- Use `verifyWebhook(req)` from `@clerk/nextjs/webhooks`

- Dashboard → Webhooks → Add Endpoint

- Set `CLERK_WEBHOOK_SIGNING_SECRET` in env

- Make route public (not protected by middleware)

## Supported Events

**User**: `user.created` `user.updated` `user.deleted`

**Organization**: `organization.created` `organization.updated` `organization.deleted`

**Organization Domain**: `organizationDomain.created` `organizationDomain.updated` `organizationDomain.deleted`

**Organization Invitation**: `organizationInvitation.created` `organizationInvitation.accepted` `organizationInvitation.revoked`

**Organization Membership**: `organizationMembership.created` `organizationMembership.updated` `organizationMembership.deleted`

**Roles**: `role.created` `role.updated` `role.deleted`

**Permissions**: `permission.created` `permission.updated` `permission.deleted`

**Session**: `session.created` `session.updated` `session.ended` `session.removed` `session.revoked` `session.pending`

**Communication**: `email.created` `sms.created`

**Invitations**: `invitation.created` `invitation.accepted` `invitation.revoked`

**Waitlist**: `waitlistEntry.created` `waitlistEntry.updated`

Full catalog: Dashboard → Webhooks → Event Catalog

## When to Sync

**Do sync when:**

- Need other users' data (social features, profiles)

- Storing extra custom fields (birthday, country, bio)

- Building notifications or integrations

**Don't sync when:**

- Only need current user data (use session token)

- No custom fields (Clerk has everything)

- Need immediate access (webhooks are eventual consistency)

## Key Patterns

### Make Route Public

Webhooks come unsigned. Route must be public:

Ensure `clerkMiddleware()` doesn't protect `/api/webhooks(.*)` path.

### Verify Webhook

Use correct import and single parameter:

```
import { verifyWebhook } from '@clerk/nextjs/webhooks'
const evt = await verifyWebhook(req)  // Pass request directly

```

### Type-Safe Events

Narrow to specific event:

```
if (evt.type === 'user.created') {
  // TypeScript knows evt.data structure
}

```

### Handle All Three Events

Don't only listen to `user.created`. Also handle `user.updated` and `user.deleted`.

### Queue Async Work

Return 200 immediately, queue long operations:

```
await queue.enqueue('process-webhook', evt)
return new Response('Received', { status: 200 })

```

## Webhook Reliability

**Retries**: Svix retries failed webhooks for up to 3 days. Return 2xx to succeed, 4xx/5xx to retry.

**Replay**: Failed webhooks can be replayed from Dashboard.

## Common Pitfalls

Symptom
Cause
Fix

Verification fails
Wrong import or usage
Use `@clerk/nextjs/webhooks`, pass `req` directly

Route not found (404)
Wrong path
Use `/api/webhooks`

Not authorized (401)
Route is protected
Make route public

No data in DB
Async job pending
Wait/check logs

Duplicate entries
Only handling `user.created`
Also handle `user.updated`

Timeouts
Handler too slow
Queue async work

## Testing & Deployment

**Local**: Use ngrok to tunnel `localhost:3000` to internet. Add ngrok URL to Dashboard endpoint.

**Production**: Update webhook endpoint URL to production domain. Copy signing secret to production env vars.
Weekly Installs2.2KRepository[clerk/skills](https://github.com/clerk/skills)GitHub Stars27First SeenJan 30, 2026Security Audits[Gen Agent Trust HubPass](/clerk/skills/clerk-webhooks/security/agent-trust-hub)[SocketPass](/clerk/skills/clerk-webhooks/security/socket)[SnykPass](/clerk/skills/clerk-webhooks/security/snyk)Installed oncodex1.9Kopencode1.9Kgithub-copilot1.9Kgemini-cli1.9Kamp1.8Kkimi-cli1.8K

---
*Source: https://skills.yangsir.net/skill/sm-clerk-webhooks*
*Markdown mirror: https://skills.yangsir.net/api/skill/sm-clerk-webhooks/markdown*