From 44866ccfac09c579539d565f51569ba43030b46d Mon Sep 17 00:00:00 2001 From: vi Date: Fri, 25 Oct 2024 16:05:03 +0200 Subject: [PATCH 01/44] wip --- docs/integrations/webhooks/sync-data.mdx | 68 ++++++++++++------------ 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index aaef1a0e4e..f0d3c75589 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -1,58 +1,60 @@ --- -title: Sync Clerk data to your application with webhooks -description: Learn how to sync Clerk data to your application with webhooks. +title: Sync Clerk data to your app with webhooks +description: Learn how to sync Clerk data to your app with webhooks. --- - - Listen for an event in the Clerk Dashboard - - Create a webhook handler that: - - uses Svix to verify the webhook signature - - receives the webhook's payload - - Test the webhook locally using ngrok and the Clerk Dashboard - - Add logic to your application to trigger the webhook + - Set up ngrok + - Set up a webhook endpoint + - Create a webhook + - Test the webhook + - Trigger the webhook -The recommended way to sync data between Clerk and your application is to use webhooks. +The recommended way to sync Clerk data to your app is through webhooks. -In this guide, you will learn how to create a Clerk webhook in your Next.js application. You will listen for the `user.updated` event by creating a webhook endpoint in the Clerk Dashboard, creating a webhook handler in your Next.js application, and testing the webhook locally using ngrok and the Clerk Dashboard. +In this guide, you'll set up a webhook in your Next.js app to listen for the `user.updated` event, create an endpoint in the Clerk Dashboard, build a handler, and test it locally using ngrok and the Clerk Dashboard. -This guide can be adapted to listen for any Clerk event. +These steps apply to any Clerk event. - ### Set up ngrok + ### Setup ngrok - To test a webhook locally, you will need to expose your local server to the internet. For this guide, you will use [ngrok](https://ngrok.com/). ngrok will create a **forwarding URL** that you can send your webhook payload to and it will forward the payload to your local server. + To test a webhook locally, you need to expose your local server to the internet. This guide uses [ngrok](https://ngrok.com/) which creates a **forwarding URL** that sends the webhook payload to your local server. - 1. Go to the [ngrok website](https://ngrok.com/) and create an account. - 1. Once you have made it to the [ngrok dashboard](https://dashboard.ngrok.com/get-started/setup/macos), in navigation sidebar, select [**Domains**](https://dashboard.ngrok.com/cloud-edge/domains). - 1. Select **Create domain**. - 1. Install ngrok and add your auth token by following steps 1 and 2 in their [install guide](https://ngrok.com/docs/getting-started/#step-1-install). - 1. ngrok will generate a free, non-ephemeral domain for you and a command to start a tunnel with that domain. The command should look something like this: - - `ngrok http --domain=fawn-two-nominally.ngrok-free.app 3000` - 1. Change the port number to whatever your server is running on. For this guide, ensure it is set to 3000 and then run the command in your terminal. - 1. Copy your **forwarding URL**. It should look something like `https://fawn-two-nominally.ngrok-free.app`. + 1. Follow steps 1 and 2 in the [ngrok's install guide](https://ngrok.com/docs/getting-started/#step-1-install). + 1. Navigate to the [ngrok website](https://dashboard.ngrok.com/signup) to create an account. + 1. In the [ngrok dashboard](https://dashboard.ngrok.com/get-started/setup/macos), select [**Domains**](https://dashboard.ngrok.com/domains) from the sidebar. + 1. Select **Create Domain**. After the page refreshes, you'll see a newly created domain and an open panel. + 1. In the **Start a Tunnel** panel, select the command generated by ngrok. This command provides a free, non-ephemeral domain and starts a tunnel with that domain. The command should resemble `ngrok http --domain=fawn-two-nominally.ngrok-free.app 3000`. + 1. Adjust the port number to match your server's port. For this guide, set it to `3000`, then run the command in your terminal. + 1. Save your **forwarding URL** somewhere secure. It should resemble `https://fawn-two-nominally.ngrok-free.app`. - ### Create an endpoint in the Clerk Dashboard + ### Setup a webhook endpoint - To create a webhook endpoint, you must provide the **Endpoint URL** and then choose the events you want to listen to. For this guide, you will listen to the `user.updated` event. + To create a webhook endpoint, you must provide the **Endpoint URL** and choose the events you want to listen to. For this guide, select the `user.updated` event. - 1. Navigate to the [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=webhooks). - 1. In the navigation sidenav, select **Webhooks**. - 1. Select the **Add Endpoint** button. - 1. In the **Endpoint URL** field, paste the ngrok URL you copied earlier followed by `/api/webhooks`. This is the endpoint that you will later create, that Svix will send the webhook payload to. The full URL should look something like `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. - 1. In the **Message Filtering** section, select the `user.updated` event. - 1. Select the **Create** button. - 1. You will be redirected to your endpoint's settings page. Leave this page open. + 1. In the Clerk Dashboard, navigate to the [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page. + 1. Select **Add Endpoint**. + 1. In the **Endpoint URL** field, paste the ngrok URL you copied earlier followed by `/api/webhooks`. This is the endpoint that you'll for Svix to send the webhook payload to. The full URL should resemble `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. + 1. In the **Subscribe to events** section, scroll down and select `user.updated`. + 1. Select **Create**. You'll be redirected to your endpoint's settings page. Keep this page open. - ### Add your signing secret to your `.env.local` file + ### @TODO-VI Add your signing secret to your `.env.local` file To verify the webhook payload, you will need your endpoint's signing secret. However, you do not want to expose this secret in your codebase, so you will want to provide it as an environment variable. In local development, this can be done by storing the secret in the `.env.local` file. From 8ca140567b303a0a2cf45b65c4071fd71cfe1927 Mon Sep 17 00:00:00 2001 From: vi Date: Tue, 29 Oct 2024 18:16:45 +0100 Subject: [PATCH 02/44] wip --- docs/integrations/webhooks/sync-data.mdx | 184 +++++++---------------- 1 file changed, 57 insertions(+), 127 deletions(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index f0d3c75589..d6a2f94f25 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -19,8 +19,13 @@ description: Learn how to sync Clerk data to your app with webhooks. ]} > - Set up ngrok + - Development vs. Production setup - Set up a webhook endpoint - - Create a webhook + - Add signing secret to .env.local + - Configure public webhook route in Middleware + - Install svix for signature verification + - Create the endpoint + - Narrow webhook events for typing (optional) - Test the webhook - Trigger the webhook @@ -29,10 +34,10 @@ The recommended way to sync Clerk data to your app is through webhooks. In this guide, you'll set up a webhook in your Next.js app to listen for the `user.updated` event, create an endpoint in the Clerk Dashboard, build a handler, and test it locally using ngrok and the Clerk Dashboard. -These steps apply to any Clerk event. +These steps apply to any Clerk event. To make the setup process easier, it's recommended to keep two browser tabs open: one for your Clerk [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page and one for your [ngrok](https://dashboard.ngrok.com) Dashboard. - ### Setup ngrok + ### Set up ngrok To test a webhook locally, you need to expose your local server to the internet. This guide uses [ngrok](https://ngrok.com/) which creates a **forwarding URL** that sends the webhook payload to your local server. @@ -41,25 +46,25 @@ These steps apply to any Clerk event. 1. In the [ngrok dashboard](https://dashboard.ngrok.com/get-started/setup/macos), select [**Domains**](https://dashboard.ngrok.com/domains) from the sidebar. 1. Select **Create Domain**. After the page refreshes, you'll see a newly created domain and an open panel. 1. In the **Start a Tunnel** panel, select the command generated by ngrok. This command provides a free, non-ephemeral domain and starts a tunnel with that domain. The command should resemble `ngrok http --domain=fawn-two-nominally.ngrok-free.app 3000`. - 1. Adjust the port number to match your server's port. For this guide, set it to `3000`, then run the command in your terminal. - 1. Save your **forwarding URL** somewhere secure. It should resemble `https://fawn-two-nominally.ngrok-free.app`. + 1. Paste the command in your terminal and change the port number to match your server's port. For this guide, replace `80` with `3000`, then run the command in your terminal. + 1. Save your **forwarding URL** somewhere secure. It should resemble `https://fawn-two-nominally.ngrok-free.app`. Close the panel. - ### Setup a webhook endpoint + ### Set up a webhook endpoint - To create a webhook endpoint, you must provide the **Endpoint URL** and choose the events you want to listen to. For this guide, select the `user.updated` event. + To set up a webhook endpoint, you must provide the **Endpoint URL** and choose the events you want to listen to. For this guide, select the `user.updated` event. 1. In the Clerk Dashboard, navigate to the [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page. 1. Select **Add Endpoint**. - 1. In the **Endpoint URL** field, paste the ngrok URL you copied earlier followed by `/api/webhooks`. This is the endpoint that you'll for Svix to send the webhook payload to. The full URL should resemble `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. + 1. In the **Endpoint URL** field, paste the ngrok URL you copied earlier followed by `/api/webhooks`. This is the endpoint that svix uses to send the webhook payload. The full URL should resemble `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. 1. In the **Subscribe to events** section, scroll down and select `user.updated`. 1. Select **Create**. You'll be redirected to your endpoint's settings page. Keep this page open. - ### @TODO-VI Add your signing secret to your `.env.local` file + ### Add your signing secret to `.env.local` - To verify the webhook payload, you will need your endpoint's signing secret. However, you do not want to expose this secret in your codebase, so you will want to provide it as an environment variable. In local development, this can be done by storing the secret in the `.env.local` file. + To verify the webhook payload, you'll need your endpoint's signing secret. Since you don't want this secret exposed in your codebase, store it as an environment variable in your `.env.local` file during local development. - 1. On the endpoint's settings page, copy the **Signing Secret**. It should be on the right side of the page with an eye icon next to it. - 1. In your project's root directory, you should have an `.env.local` file that includes your Clerk API keys. Here, assign your signing secret to `WEBHOOK_SECRET`. Your file should look something like this: + 1. On the endpoint's settings page, copy the **Signing Secret**. + 1. In your project's root directory, open or create an `.env.local` file, which should already include your Clerk API keys. Assign your signing secret to `WEBHOOK_SECRET`. The file should resemble: ```env {{ filename: '.env.local' }} NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY={{pub_key}} @@ -67,14 +72,14 @@ These steps apply to any Clerk event. WEBHOOK_SECRET=whsec_123 ``` - ### Set webhook route as public in your Middleware + ### Set the webhook route as public in your Middleware - Incoming webhook events will never be signed in -- they are coming from a source outside of your application. Since they will be in a signed out state, the route should be public. + Incoming webhook events won't be signed in—they come from an external source and are therefore always in a signed-out state. To allow access, the route should be public. - The following example shows the recommended Middleware configuration for your webhook routes. + The following example shows the recommended Middleware configuration for webhook routes. - ```tsx {{ filename: 'middleware.tsx' }} + ```tsx {{ filename: 'middleware.ts' }} import { clerkMiddleware } from '@clerk/nextjs/server' // Make sure that the `/api/webhooks(.*)` route is not protected here @@ -90,7 +95,7 @@ These steps apply to any Clerk event. } ``` - ```tsx {{ filename: 'middleware.tsx', mark: [4] }} + ```tsx {{ filename: 'middleware.ts', mark: [4] }} import { authMiddleware } from '@clerk/nextjs/server' export default authMiddleware({ @@ -110,7 +115,7 @@ These steps apply to any Clerk event. ### Install `svix` - You will use [`svix`](https://www.npmjs.com/package/svix) to verify the webhook signature. Install it by running the following command in your terminal: + You'll use [`svix`](https://www.npmjs.com/package/svix) to verify the webhook signature. Run the following command in your terminal to install it: ```bash {{ filename: 'terminal' }} @@ -126,34 +131,33 @@ These steps apply to any Clerk event. ``` - ### Create the endpoint in your application + ### Create the endpoint - Create a Route Handler that uses `svix` to verify the webhook signature and that receives the webhook's payload. + Set up a Route Handler that uses `svix` to verify the webhook signature and process the payload. - For the sake of this guide, you will only log the payload to the console. In a real world application, you would use the payload to trigger some action. For example, you are listening for the `user.updated` event, so you could perform a database `update` or `upsert` to update the user's details. + For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.updated` event, you might perform a database `update` or `upsert` to refresh the user's details. - Your webhook will need to return either an error code, or a success code, like `200` or `201`. If it returns an error code, the webhook will reflect that in the Dashboard log and it will [retry](/docs/integrations/webhooks/overview#retry). When the webhook returns a success code, there will be no retries and the webhook will show a success status in the Dashboard. + The webhook must return either an error code or a success code, such as `200` or `201`. An error code will appear in the Dashboard log and trigger a [retry](/docs/integrations/webhooks/overview#retry). A success code will stop further retries and show a success status in the Dashboard. > [!NOTE] - > The following Route Handler is not specific to the `user.updated` event and can be used for any webhook event you choose to listen to. + > The following Route Handler can be used for any webhook event you choose to listen to, not just `user.updated`. - + ```ts {{ filename: 'app/api/webhooks/route.ts' }} import { Webhook } from 'svix' import { headers } from 'next/headers' import { WebhookEvent } from '@clerk/nextjs/server' export async function POST(req: Request) { - // You can find this in the Clerk Dashboard -> Webhooks -> choose the endpoint const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET if (!WEBHOOK_SECRET) { throw new Error('Please add WEBHOOK_SECRET from Clerk Dashboard to .env or .env.local') } - // Get the headers + // Get headers const headerPayload = headers() const svix_id = headerPayload.get('svix-id') const svix_timestamp = headerPayload.get('svix-timestamp') @@ -161,21 +165,21 @@ These steps apply to any Clerk event. // If there are no headers, error out if (!svix_id || !svix_timestamp || !svix_signature) { - return new Response('Error occured -- no svix headers', { + return new Response('Missing svix headers', { status: 400, }) } - // Get the body + // Get body const payload = await req.json() const body = JSON.stringify(payload) - // Create a new Svix instance with your secret. + // Create new svix instance with secret const wh = new Webhook(WEBHOOK_SECRET) let evt: WebhookEvent - // Verify the payload with the headers + // Verify payload with headers try { evt = wh.verify(body, { 'svix-id': svix_id, @@ -184,88 +188,20 @@ These steps apply to any Clerk event. }) as WebhookEvent } catch (err) { console.error('Error verifying webhook:', err) - return new Response('Error occured', { + return new Response('Verification error', { status: 400, }) } - // Do something with the payload - // For this guide, you simply log the payload to the console + // Log payload to console const { id } = evt.data const eventType = evt.type - console.log(`Webhook with and ID of ${id} and type of ${eventType}`) - console.log('Webhook body:', body) + console.log(`Received webhook with ID ${id} and event type of ${eventType}`) + console.log('Webhook payload:', body) return new Response('', { status: 200 }) } ``` - - ```ts {{ filename: 'pages/api/webhooks.ts' }} - import { Webhook } from 'svix' - import { WebhookEvent } from '@clerk/nextjs/server' - import { NextApiRequest, NextApiResponse } from 'next' - import { buffer } from 'micro' - - export const config = { - api: { - bodyParser: false, - }, - } - - export default async function handler(req: NextApiRequest, res: NextApiResponse) { - if (req.method !== 'POST') { - return res.status(405) - } - // You can find this in the Clerk Dashboard -> Webhooks -> choose the webhook - const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET - - if (!WEBHOOK_SECRET) { - throw new Error('Please add WEBHOOK_SECRET from Clerk Dashboard to .env or .env.local') - } - - // Get the Svix headers for verification - const svix_id = req.headers['svix-id'] as string - const svix_timestamp = req.headers['svix-timestamp'] as string - const svix_signature = req.headers['svix-signature'] as string - - // If there are no headers, error out - if (!svix_id || !svix_timestamp || !svix_signature) { - return res.status(400).json({ error: 'Error occured -- no svix headers' }) - } - - console.log('headers', req.headers, svix_id, svix_signature, svix_timestamp) - // Get the body - const body = (await buffer(req)).toString() - - // Create a new Svix instance with your secret. - const wh = new Webhook(WEBHOOK_SECRET) - - let evt: WebhookEvent - - // Attempt to verify the incoming webhook - // If successful, the payload will be available from 'evt' - // If the verification fails, error out and return error code - try { - evt = wh.verify(body, { - 'svix-id': svix_id, - 'svix-timestamp': svix_timestamp, - 'svix-signature': svix_signature, - }) as WebhookEvent - } catch (err) { - console.error('Error verifying webhook:', err) - return res.status(400).json({ Error: err }) - } - - // Do something with the payload - // For this guide, you simply log the payload to the console - const { id } = evt.data - const eventType = evt.type - console.log(`Webhook with and ID of ${id} and type of ${eventType}`) - console.log('Webhook body:', body) - - return res.status(200).json({ response: 'Success' }) - } - ``` @@ -291,19 +227,19 @@ These steps apply to any Clerk event. const headers = req.headers const payload = req.body - // Get the Svix headers for verification + // Get the svix headers for verification const svix_id = headers['svix-id'] const svix_timestamp = headers['svix-timestamp'] const svix_signature = headers['svix-signature'] - // If there are no Svix headers, error out + // If there are no svix headers, error out if (!svix_id || !svix_timestamp || !svix_signature) { return new Response('Error occured -- no svix headers', { status: 400, }) } - // Create a new Svix instance with your secret. + // Create a new svix instance with your secret. const wh = new Webhook(WEBHOOK_SECRET) let evt @@ -342,22 +278,22 @@ These steps apply to any Clerk event. - ### Narrow the webhook event to get typing + ### Narrow the webhook event for type inference - The `WebhookEvent` reflects all possible webhook types. You can narrow down the event to get the types inferred correctly for the event type you are working with. + `WebhookEvent` encompasses all possible webhook types. Narrow down the event type for accurate typing for specific events. - In the following example, the `if` statement will narrow the type to the `user.created` type and using `evt.data` will give you autocompletion and type safety for that event. + In the following example, the `if` statement narrows the type to `user.created`, enabling type-safe access to evt.data with autocompletion. ```ts {{ filename: 'app/api/webhooks/route.ts', del: [1, 2], ins: [[4, 6]] }} - console.log(`Webhook with and ID of ${id} and type of ${eventType}`) - console.log('Webhook body:', body) + console.log(`Received webhook with ID ${id} and event type of ${eventType}`) + console.log('Webhook payload:', body) if (evt.type === 'user.created') { console.log('userId:', evt.data.id) } ``` - If you want to handle types yourself, you can import the following types from your backend SDK, such as `@clerk/nextjs/server`. + To handle types manually, import the following package from your backend SDK (e.g., `@clerk/nextjs/server`): - `DeletedObjectJSON` - `EmailJSON` @@ -371,30 +307,24 @@ These steps apply to any Clerk event. ### Test your webhook 1. Start your Next.js server. - 1. On your endpoint's settings page in the Clerk Dashboard, select the **Testing** tab. + 1. In your endpoint's settings page in the Clerk Dashboard, select the **Testing** tab. 1. In the **Select event** dropdown, select `user.updated`. - 1. Select the **Send Example** button. - 1. Below that section, in the **Message Attempts** section, you should see a successful attempt with a status of `200`. + 1. Select **Send Example**. + 1. In the **Message Attempts** section, confirm that the event is labeled with `Succeeded`. - #### Message failed + #### Handling failed messages - If the message failed: - - 1. Select the message. + 1. In the **Message Attempts** section, select the event labeled with `Failed`. 1. Scroll down to the **Webhook Attempts** section. - 1. Select the arrow icon the left side. - 1. Investigate the error. Your solution is going to depend on the error message. See the [Debug your webhooks](/docs/integrations/webhooks/debug-your-webhooks) guide for more information. + 1. Toggle the arrow next to the **Status** column. + 1. Review the error. Solutions vary by error type. For more information, refer to the [Debug your webhooks](/docs/integrations/webhooks/debug-your-webhooks) guide. ### Trigger your webhook - To trigger the `user.updated` event, you can do one of the following: + To trigger the `user.updated` event, you can do either one of the following: - 1. You can edit your user in the Dashboard. - 1. You can use the `` component in your application to edit your profile. + 1. Edit your user in the Clerk Dashboard. + 1. Select the `` component in your app to edit your profile. Once you have updated a user, you should be able to see the webhook's payload logged to your terminal. You can also check the Clerk Dashboard to see the webhook attempt, the same way you did when [testing the webhook](#test-your-webhook). - - ### Wrap up - - In this guide, you learned how to create a Clerk webhook using Svix. You created a webhook in the Clerk Dashboard to listen for the `user.updated` event and created a Route Handler for your webhook endpoint to verify the webhook signature and receive the payload. You tested the webhook locally using ngrok and the Clerk Dashboard to ensure it was configured properly. And lastly, you added logic to your application to actually trigger the `user.updated` event. Now, you can do whatever you want with the webhook payload, such as sending a notification to your users, updating a database, or anything else you can think of. From ca3c5e44698ab9a98999ae1945f05779c397dc01 Mon Sep 17 00:00:00 2001 From: vi Date: Tue, 29 Oct 2024 20:09:03 +0100 Subject: [PATCH 03/44] wip --- docs/integrations/webhooks/sync-data.mdx | 105 ++++++++++++----------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index d6a2f94f25..812f03f4b0 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -19,15 +19,11 @@ description: Learn how to sync Clerk data to your app with webhooks. ]} > - Set up ngrok - - Development vs. Production setup - Set up a webhook endpoint - - Add signing secret to .env.local - - Configure public webhook route in Middleware - - Install svix for signature verification - - Create the endpoint - - Narrow webhook events for typing (optional) + - Create the webhook + - Get type inference for your webhook events - Test the webhook - - Trigger the webhook + - Configure your production instance The recommended way to sync Clerk data to your app is through webhooks. @@ -55,21 +51,21 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. In the Clerk Dashboard, navigate to the [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page. 1. Select **Add Endpoint**. - 1. In the **Endpoint URL** field, paste the ngrok URL you copied earlier followed by `/api/webhooks`. This is the endpoint that svix uses to send the webhook payload. The full URL should resemble `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. + 1. In the **Endpoint URL** field, paste the ngrok URL you copied earlier followed by `/api/webhooks`. This is the endpoint that Svix uses to send the webhook payload. The full URL should resemble `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. 1. In the **Subscribe to events** section, scroll down and select `user.updated`. 1. Select **Create**. You'll be redirected to your endpoint's settings page. Keep this page open. - ### Add your signing secret to `.env.local` + ### Add your Signing Secret to `.env.local` - To verify the webhook payload, you'll need your endpoint's signing secret. Since you don't want this secret exposed in your codebase, store it as an environment variable in your `.env.local` file during local development. + To verify the webhook payload, you'll need your endpoint's Signing Secret. Since you don't want this secret exposed in your codebase, store it as an environment variable in your `.env.local` file during local development. 1. On the endpoint's settings page, copy the **Signing Secret**. - 1. In your project's root directory, open or create an `.env.local` file, which should already include your Clerk API keys. Assign your signing secret to `WEBHOOK_SECRET`. The file should resemble: + 1. In your project's root directory, open or create an `.env.local` file, which should already include your Clerk API keys. Assign your Signing Secret to `SIGNING_SECRET`. The file should resemble: ```env {{ filename: '.env.local' }} NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY={{pub_key}} CLERK_SECRET_KEY={{secret}} - WEBHOOK_SECRET=whsec_123 + SIGNING_SECRET=whsec_123 ``` ### Set the webhook route as public in your Middleware @@ -133,7 +129,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Create the endpoint - Set up a Route Handler that uses `svix` to verify the webhook signature and process the payload. + Set up a Route Handler that uses `Svix` to verify the webhook signature and process the payload. For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.updated` event, you might perform a database `update` or `upsert` to refresh the user's details. @@ -142,7 +138,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec > [!NOTE] > The following Route Handler can be used for any webhook event you choose to listen to, not just `user.updated`. - + ```ts {{ filename: 'app/api/webhooks/route.ts' }} @@ -151,12 +147,15 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec import { WebhookEvent } from '@clerk/nextjs/server' export async function POST(req: Request) { - const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET + const SIGNING_SECRET = process.env.SIGNING_SECRET - if (!WEBHOOK_SECRET) { - throw new Error('Please add WEBHOOK_SECRET from Clerk Dashboard to .env or .env.local') + if (!SIGNING_SECRET) { + throw new Error('Please add SIGNING_SECRET from Clerk Dashboard to .env or .env.local') } + // Create new Svix instance with secret + const wh = new Webhook(SIGNING_SECRET) + // Get headers const headerPayload = headers() const svix_id = headerPayload.get('svix-id') @@ -165,7 +164,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec // If there are no headers, error out if (!svix_id || !svix_timestamp || !svix_signature) { - return new Response('Missing svix headers', { + return new Response('Error: Missing Svix headers', { status: 400, }) } @@ -174,9 +173,6 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec const payload = await req.json() const body = JSON.stringify(payload) - // Create new svix instance with secret - const wh = new Webhook(WEBHOOK_SECRET) - let evt: WebhookEvent // Verify payload with headers @@ -193,82 +189,82 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec }) } + // Do something with the payload // Log payload to console const { id } = evt.data const eventType = evt.type console.log(`Received webhook with ID ${id} and event type of ${eventType}`) console.log('Webhook payload:', body) - return new Response('', { status: 200 }) + return new Response('Webhook received', { status: 200 }) } ``` - ```js {{ filename: 'clerkWebhookHandler.js' }} - import { Webhook } from 'svix' - import bodyParser from 'body-parser' - + ```ts {{ filename: 'index.ts' }} app.post( '/api/webhooks', // This is a generic method to parse the contents of the payload. // Depending on the framework, packages, and configuration, this may be // different or not required. bodyParser.raw({ type: 'application/json' }), - async function (req, res) { - // You can find this in the Clerk Dashboard -> Webhooks -> choose the webhook - const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET - if (!WEBHOOK_SECRET) { - throw new Error('You need a WEBHOOK_SECRET in your .env') + + async (req, res) => { + const SIGNING_SECRET = process.env.SIGNING_SECRET + + if (!SIGNING_SECRET) { + throw new Error('Please add SIGNING_SECRET from Clerk Dashboard to .env') } - // Get the headers and body + // Create new Svix instance with secret + const wh = new Webhook(SIGNING_SECRET) + + // Get headers and body const headers = req.headers const payload = req.body - // Get the svix headers for verification + // Get Svix headers for verification const svix_id = headers['svix-id'] const svix_timestamp = headers['svix-timestamp'] const svix_signature = headers['svix-signature'] - // If there are no svix headers, error out + // If there are no headers, error out if (!svix_id || !svix_timestamp || !svix_signature) { - return new Response('Error occured -- no svix headers', { - status: 400, + return void res.status(400).json({ + success: false, + message: 'Error: Missing svix headers', }) } - // Create a new svix instance with your secret. - const wh = new Webhook(WEBHOOK_SECRET) - let evt // Attempt to verify the incoming webhook // If successful, the payload will be available from 'evt' - // If the verification fails, error out and return error code + // If verification fails, error out and return error code try { evt = wh.verify(payload, { - 'svix-id': svix_id, - 'svix-timestamp': svix_timestamp, - 'svix-signature': svix_signature, + 'svix-id': svix_id as string, + 'svix-timestamp': svix_timestamp as string, + 'svix-signature': svix_signature as string, }) } catch (err) { console.log('Error verifying webhook:', err.message) - return res.status(400).json({ + return void res.status(400).json({ success: false, message: err.message, }) } // Do something with the payload - // For this guide, you simply log the payload to the console + // Log payload to console const { id } = evt.data const eventType = evt.type - console.log(`Webhook with an ID of ${id} and type of ${eventType}`) - console.log('Webhook body:', evt.data) + console.log(`Received webhook with ID ${id} and event type of ${eventType}`) + console.log('Webhook payload:', evt.data) - return res.status(200).json({ + return void res.status(200).json({ success: true, message: 'Webhook received', }) @@ -278,7 +274,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec - ### Narrow the webhook event for type inference + ### Narrow to a webhook event for type inference `WebhookEvent` encompasses all possible webhook types. Narrow down the event type for accurate typing for specific events. @@ -304,7 +300,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec - `SMSMessageJSON` - `UserJSON` - ### Test your webhook + ### Test the webhook 1. Start your Next.js server. 1. In your endpoint's settings page in the Clerk Dashboard, select the **Testing** tab. @@ -319,7 +315,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. Toggle the arrow next to the **Status** column. 1. Review the error. Solutions vary by error type. For more information, refer to the [Debug your webhooks](/docs/integrations/webhooks/debug-your-webhooks) guide. - ### Trigger your webhook + ### Trigger the webhook To trigger the `user.updated` event, you can do either one of the following: @@ -328,3 +324,10 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec Once you have updated a user, you should be able to see the webhook's payload logged to your terminal. You can also check the Clerk Dashboard to see the webhook attempt, the same way you did when [testing the webhook](#test-your-webhook). + +### Configure your production instance + +1. When you're ready to deploy your app to production, follow [the guide on deploying your Clerk app to production](/docs/deployments/overview). +1. Create your production webhook by following the steps in the previous [Set up a webhook endpoint](#set-up-a-webhook-endpoint) section. In the **Endpoint URL** field, instead of pasting the ngrok URL, paste your production app URL. +1. After you've set up your webhook endpoint, you'll be redirected to your endpoint's settings page. Copy the **Signing Secret** and update your `.env.local` file with the new **Signing Secret**. +1. On your hosting platform, update your environment variables with the new **Signing Secret**. Redeploy your app. From 110fbe70d55f17cbc807b1b8c27ca53672aa21d3 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:19:52 +0100 Subject: [PATCH 04/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 1d31ab9fb2..5be54fb412 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -30,7 +30,7 @@ The recommended way to sync Clerk data to your app is through webhooks. In this guide, you'll set up a webhook in your Next.js app to listen for the `user.updated` event, create an endpoint in the Clerk Dashboard, build a handler, and test it locally using ngrok and the Clerk Dashboard. -These steps apply to any Clerk event. To make the setup process easier, it's recommended to keep two browser tabs open: one for your Clerk [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page and one for your [ngrok](https://dashboard.ngrok.com) Dashboard. +These steps apply to any Clerk event. To make the setup process easier, it's recommended to keep two browser tabs open: one for your Clerk [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page and one for your [ngrok dashboard](https://dashboard.ngrok.com). ### Set up ngrok From a9ee9171c55332f13ddb53566a08344aa46c5d4d Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:20:01 +0100 Subject: [PATCH 05/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 5be54fb412..4a8e25df7d 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -170,7 +170,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec }) } - // Do something with the payload + // Do something with payload // Log payload to console const { id } = evt.data const eventType = evt.type From 2bf4fc5febe4465fd6f188a5cb081d93e215319c Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:20:11 +0100 Subject: [PATCH 06/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 4a8e25df7d..a1422546f5 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -238,7 +238,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec }) } - // Do something with the payload + // Do something with payload // Log payload to console const { id } = evt.data const eventType = evt.type From c037c391b762bea2022501e398174168092abc2f Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:21:03 +0100 Subject: [PATCH 07/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index a1422546f5..eca43cf07c 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -37,8 +37,8 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec To test a webhook locally, you need to expose your local server to the internet. This guide uses [ngrok](https://ngrok.com/) which creates a **forwarding URL** that sends the webhook payload to your local server. - 1. Follow steps 1 and 2 in the [ngrok's install guide](https://ngrok.com/docs/getting-started/#step-1-install). 1. Navigate to the [ngrok website](https://dashboard.ngrok.com/signup) to create an account. + 1. Follow steps 1 and 2 in [ngrok's install guide](https://ngrok.com/docs/getting-started/#step-1-install). 1. In the [ngrok dashboard](https://dashboard.ngrok.com/get-started/setup/macos), select [**Domains**](https://dashboard.ngrok.com/domains) from the sidebar. 1. Select **Create Domain**. After the page refreshes, you'll see a newly created domain and an open panel. 1. In the **Start a Tunnel** panel, select the command generated by ngrok. This command provides a free, non-ephemeral domain and starts a tunnel with that domain. The command should resemble `ngrok http --domain=fawn-two-nominally.ngrok-free.app 3000`. From a7871d0b1a7ad729723ca90bd10741c563f371a8 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:22:18 +0100 Subject: [PATCH 08/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index eca43cf07c..bf769c04ee 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -39,7 +39,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. Navigate to the [ngrok website](https://dashboard.ngrok.com/signup) to create an account. 1. Follow steps 1 and 2 in [ngrok's install guide](https://ngrok.com/docs/getting-started/#step-1-install). - 1. In the [ngrok dashboard](https://dashboard.ngrok.com/get-started/setup/macos), select [**Domains**](https://dashboard.ngrok.com/domains) from the sidebar. + 1. In the ngrok dashboard, select [**Domains**](https://dashboard.ngrok.com/domains) from the sidebar. 1. Select **Create Domain**. After the page refreshes, you'll see a newly created domain and an open panel. 1. In the **Start a Tunnel** panel, select the command generated by ngrok. This command provides a free, non-ephemeral domain and starts a tunnel with that domain. The command should resemble `ngrok http --domain=fawn-two-nominally.ngrok-free.app 3000`. 1. Paste the command in your terminal and change the port number to match your server's port. For this guide, replace `80` with `3000`, then run the command in your terminal. From 0887bb0a4ec5cfcb3ec8d5823b02156e0edb9521 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:22:38 +0100 Subject: [PATCH 09/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index bf769c04ee..0de9b01060 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -40,7 +40,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. Navigate to the [ngrok website](https://dashboard.ngrok.com/signup) to create an account. 1. Follow steps 1 and 2 in [ngrok's install guide](https://ngrok.com/docs/getting-started/#step-1-install). 1. In the ngrok dashboard, select [**Domains**](https://dashboard.ngrok.com/domains) from the sidebar. - 1. Select **Create Domain**. After the page refreshes, you'll see a newly created domain and an open panel. + 1. Select **Create Domain**. After the page refreshes, the **Start a Tunnel** panel will open. 1. In the **Start a Tunnel** panel, select the command generated by ngrok. This command provides a free, non-ephemeral domain and starts a tunnel with that domain. The command should resemble `ngrok http --domain=fawn-two-nominally.ngrok-free.app 3000`. 1. Paste the command in your terminal and change the port number to match your server's port. For this guide, replace `80` with `3000`, then run the command in your terminal. 1. Save your **forwarding URL** somewhere secure. It should resemble `https://fawn-two-nominally.ngrok-free.app`. Close the panel. From 13adc1ea5437c9a98db1dfabf7ec10eeb8c2c7b9 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:24:54 +0100 Subject: [PATCH 10/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 0de9b01060..b19f966d5e 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -41,7 +41,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. Follow steps 1 and 2 in [ngrok's install guide](https://ngrok.com/docs/getting-started/#step-1-install). 1. In the ngrok dashboard, select [**Domains**](https://dashboard.ngrok.com/domains) from the sidebar. 1. Select **Create Domain**. After the page refreshes, the **Start a Tunnel** panel will open. - 1. In the **Start a Tunnel** panel, select the command generated by ngrok. This command provides a free, non-ephemeral domain and starts a tunnel with that domain. The command should resemble `ngrok http --domain=fawn-two-nominally.ngrok-free.app 3000`. + 1. In the **Start a Tunnel** panel, select the command generated by ngrok. This command provides a free, non-ephemeral domain and starts a tunnel with that domain. The command should resemble `ngrok http --url=fawn-two-nominally.ngrok-free.app 80`. 1. Paste the command in your terminal and change the port number to match your server's port. For this guide, replace `80` with `3000`, then run the command in your terminal. 1. Save your **forwarding URL** somewhere secure. It should resemble `https://fawn-two-nominally.ngrok-free.app`. Close the panel. From 822516f00899c633343ffca095fdf8a1222da677 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:25:05 +0100 Subject: [PATCH 11/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index b19f966d5e..0ed7129148 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -259,7 +259,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec `WebhookEvent` encompasses all possible webhook types. Narrow down the event type for accurate typing for specific events. - In the following example, the `if` statement narrows the type to `user.created`, enabling type-safe access to evt.data with autocompletion. + In the following example, the `if` statement narrows the type to `user.updated`, enabling type-safe access to evt.data with autocompletion. ```ts {{ filename: 'app/api/webhooks/route.ts', del: [1, 2], ins: [[4, 6]] }} console.log(`Received webhook with ID ${id} and event type of ${eventType}`) From a61a726a1a07f6980579a942dbc0f7dff675965b Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:26:00 +0100 Subject: [PATCH 12/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 0ed7129148..9f1d47bdab 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -265,7 +265,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec console.log(`Received webhook with ID ${id} and event type of ${eventType}`) console.log('Webhook payload:', body) - if (evt.type === 'user.created') { + if (evt.type === 'user.updated') { console.log('userId:', evt.data.id) } ``` From 2ed560ee01d75a8744f0e0d8d32c258c56eb17eb Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:26:07 +0100 Subject: [PATCH 13/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 9f1d47bdab..0af758a7b5 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -303,7 +303,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. Edit your user in the Clerk Dashboard. 1. Select the `` component in your app to edit your profile. - Once you have updated a user, you should be able to see the webhook's payload logged to your terminal. You can also check the Clerk Dashboard to see the webhook attempt, the same way you did when [testing the webhook](#test-your-webhook). + Once you have updated a user, you should be able to see the webhook's payload logged to your terminal. You can also check the Clerk Dashboard to see the webhook attempt, the same way you did when [testing the webhook](#test-the-webhook). ### Configure your production instance From 313d288159485768072b545882b1c66d35a858c2 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:27:31 +0100 Subject: [PATCH 14/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 0af758a7b5..d43e05a165 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -239,7 +239,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec } // Do something with payload - // Log payload to console + // For this guide, log payload to console const { id } = evt.data const eventType = evt.type console.log(`Received webhook with ID ${id} and event type of ${eventType}`) From 57373579315261ef42634604504160d3ce1caa0c Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:28:14 +0100 Subject: [PATCH 15/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index d43e05a165..e0db4eda28 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -42,8 +42,8 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. In the ngrok dashboard, select [**Domains**](https://dashboard.ngrok.com/domains) from the sidebar. 1. Select **Create Domain**. After the page refreshes, the **Start a Tunnel** panel will open. 1. In the **Start a Tunnel** panel, select the command generated by ngrok. This command provides a free, non-ephemeral domain and starts a tunnel with that domain. The command should resemble `ngrok http --url=fawn-two-nominally.ngrok-free.app 80`. - 1. Paste the command in your terminal and change the port number to match your server's port. For this guide, replace `80` with `3000`, then run the command in your terminal. - 1. Save your **forwarding URL** somewhere secure. It should resemble `https://fawn-two-nominally.ngrok-free.app`. Close the panel. + 1. Paste the command in your terminal and change the port number to match your server's port. For this guide, replace `80` with `3000`, then run the command in your terminal. It will generate a **Forwarding** URL. It should resemble `https://fawn-two-nominally.ngrok-free.app`. + 1. Save your **Forwarding** URL somewhere secure. Close the panel. ### Set up a webhook endpoint From 9e8746430dc217ee916a2deb2d88929a1cc39703 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:28:24 +0100 Subject: [PATCH 16/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index e0db4eda28..6f4f0604c8 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -51,7 +51,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. In the Clerk Dashboard, navigate to the [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page. 1. Select **Add Endpoint**. - 1. In the **Endpoint URL** field, paste the ngrok URL you copied earlier followed by `/api/webhooks`. This is the endpoint that Svix uses to send the webhook payload. The full URL should resemble `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. + 1. In the **Endpoint URL** field, paste the ngrok **Forwarding** URL you saved earlier, followed by `/api/webhooks`. This is the endpoint that Svix uses to send the webhook payload. The full URL should resemble `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. 1. In the **Subscribe to events** section, scroll down and select `user.updated`. 1. Select **Create**. You'll be redirected to your endpoint's settings page. Keep this page open. From c016f9a313dc7bd3cf540337e6db6fdd66013279 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:28:45 +0100 Subject: [PATCH 17/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 6f4f0604c8..3697af7d8f 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -114,7 +114,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.updated` event, you might perform a database `update` or `upsert` to refresh the user's details. - The webhook must return either an error code or a success code, such as `200` or `201`. An error code will appear in the Dashboard log and trigger a [retry](/docs/integrations/webhooks/overview#retry). A success code will stop further retries and show a success status in the Dashboard. + The webhook must return either an error code or a success code, such as `200` or `201`. An error code will appear in the Clerk Dashboard log and trigger a [retry](/docs/integrations/webhooks/overview#retry). A success code will stop further retries and show a success status in the Clerk Dashboard log. > [!NOTE] > The following Route Handler can be used for any webhook event you choose to listen to, not just `user.updated`. From 5d2f44fe84ba58fbc720583d31fbc4c42daf3283 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:29:34 +0100 Subject: [PATCH 18/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 3697af7d8f..c410dc1989 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -171,7 +171,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec } // Do something with payload - // Log payload to console + // For this guide, log payload to console const { id } = evt.data const eventType = evt.type console.log(`Received webhook with ID ${id} and event type of ${eventType}`) From 7cd914de23078b2848cf5b3ae8976f3a86c4bad4 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:29:46 +0100 Subject: [PATCH 19/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index c410dc1989..51d3bfd389 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -60,7 +60,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec To verify the webhook payload, you'll need your endpoint's Signing Secret. Since you don't want this secret exposed in your codebase, store it as an environment variable in your `.env.local` file during local development. 1. On the endpoint's settings page, copy the **Signing Secret**. - 1. In your project's root directory, open or create an `.env.local` file, which should already include your Clerk API keys. Assign your Signing Secret to `SIGNING_SECRET`. The file should resemble: + 1. In your project's root directory, open or create an `.env.local` file, which should already include your Clerk API keys. Assign your **Signing Secret** to `SIGNING_SECRET`. The file should resemble: ```env {{ filename: '.env.local' }} NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY={{pub_key}} From 4ee95345b790df85e2692f99e1daf737743a6884 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:29:57 +0100 Subject: [PATCH 20/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 51d3bfd389..7f70be2d9a 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -57,7 +57,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Add your Signing Secret to `.env.local` - To verify the webhook payload, you'll need your endpoint's Signing Secret. Since you don't want this secret exposed in your codebase, store it as an environment variable in your `.env.local` file during local development. + To verify the webhook payload, you'll need your endpoint's **Signing Secret**. Since you don't want this secret exposed in your codebase, store it as an environment variable in your `.env.local` file during local development. 1. On the endpoint's settings page, copy the **Signing Secret**. 1. In your project's root directory, open or create an `.env.local` file, which should already include your Clerk API keys. Assign your **Signing Secret** to `SIGNING_SECRET`. The file should resemble: From d69119dc0a30b2c56837ca6ef7e9685b7bbf8f85 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:30:20 +0100 Subject: [PATCH 21/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 7f70be2d9a..2ecbae9f7c 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -223,7 +223,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec // Attempt to verify the incoming webhook // If successful, the payload will be available from 'evt' - // If verification fails, error out and return error code + // If verification fails, error out and return error code try { evt = wh.verify(payload, { 'svix-id': svix_id as string, From c249cb220b4cebaac6eccf9976b1e45834e9e271 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:32:14 +0100 Subject: [PATCH 22/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 2ecbae9f7c..fcf6a9b0b4 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -112,7 +112,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec Set up a Route Handler that uses `Svix` to verify the webhook signature and process the payload. - For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.updated` event, you might perform a database `update` or `upsert` to refresh the user's details. + For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.updated` event, you might perform a database `update` or `upsert` to update the user's details. The webhook must return either an error code or a success code, such as `200` or `201`. An error code will appear in the Clerk Dashboard log and trigger a [retry](/docs/integrations/webhooks/overview#retry). A success code will stop further retries and show a success status in the Clerk Dashboard log. From 88e34c10d0f655aa2c4dd6f1369946d8ec66779a Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 30 Oct 2024 13:32:32 +0100 Subject: [PATCH 23/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index fcf6a9b0b4..7ac0346a2d 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -110,7 +110,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Create the endpoint - Set up a Route Handler that uses `Svix` to verify the webhook signature and process the payload. + Set up a Route Handler that uses `svix` to verify the webhook signature and process the payload. For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.updated` event, you might perform a database `update` or `upsert` to update the user's details. From c29a20bfb9f4b71aea6ce4214621d08ae2e31a00 Mon Sep 17 00:00:00 2001 From: vi Date: Wed, 30 Oct 2024 15:37:17 +0100 Subject: [PATCH 24/44] lint --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 7ac0346a2d..819d637d71 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -42,7 +42,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. In the ngrok dashboard, select [**Domains**](https://dashboard.ngrok.com/domains) from the sidebar. 1. Select **Create Domain**. After the page refreshes, the **Start a Tunnel** panel will open. 1. In the **Start a Tunnel** panel, select the command generated by ngrok. This command provides a free, non-ephemeral domain and starts a tunnel with that domain. The command should resemble `ngrok http --url=fawn-two-nominally.ngrok-free.app 80`. - 1. Paste the command in your terminal and change the port number to match your server's port. For this guide, replace `80` with `3000`, then run the command in your terminal. It will generate a **Forwarding** URL. It should resemble `https://fawn-two-nominally.ngrok-free.app`. + 1. Paste the command in your terminal and change the port number to match your server's port. For this guide, replace `80` with `3000`, then run the command in your terminal. It will generate a **Forwarding** URL. It should resemble `https://fawn-two-nominally.ngrok-free.app`. 1. Save your **Forwarding** URL somewhere secure. Close the panel. ### Set up a webhook endpoint From 47262405c02c6ae3544d0145a5b535c39ecce18b Mon Sep 17 00:00:00 2001 From: vi Date: Thu, 31 Oct 2024 17:42:45 +0100 Subject: [PATCH 25/44] fix --- docs/integrations/webhooks/sync-data.mdx | 29 +++++++++++++++--------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 819d637d71..f688839759 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -28,7 +28,13 @@ description: Learn how to sync Clerk data to your app with webhooks. The recommended way to sync Clerk data to your app is through webhooks. -In this guide, you'll set up a webhook in your Next.js app to listen for the `user.updated` event, create an endpoint in the Clerk Dashboard, build a handler, and test it locally using ngrok and the Clerk Dashboard. +In this guide, you'll set up a webhook in your Next.js app to listen for the `user.created` event, create an endpoint in the Clerk Dashboard, build a handler, and test it locally using ngrok and the Clerk Dashboard. + +Clerk offers many user events, but three key events include: + +- `user.created`: Triggers when a new user registers in the app or is created via the Clerk Dashboard or Backend API. Listening to this event allows the initial insertion of user information in your database. +- `user.updated`: Triggers when user information is updated via Clerk components, the Clerk Dashboard, or Backend API. Listening to this event keeps data synced between Clerk and your external database. It is recommended to only sync what you need to simplify this process. +- `user.deleted`: Triggers when a user deletes their account, or their account is removed via the Clerk Dashboard or Backend API. Listening to this event allows you to delete the user from your database or add a `deleted: true` flag. These steps apply to any Clerk event. To make the setup process easier, it's recommended to keep two browser tabs open: one for your Clerk [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page and one for your [ngrok dashboard](https://dashboard.ngrok.com). @@ -47,12 +53,12 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Set up a webhook endpoint - To set up a webhook endpoint, you must provide the **Endpoint URL** and choose the events you want to listen to. For this guide, select the `user.updated` event. + To set up a webhook endpoint, you must provide the **Endpoint URL** and choose the events you want to listen to. For this guide, select the `user.created` event. 1. In the Clerk Dashboard, navigate to the [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page. 1. Select **Add Endpoint**. 1. In the **Endpoint URL** field, paste the ngrok **Forwarding** URL you saved earlier, followed by `/api/webhooks`. This is the endpoint that Svix uses to send the webhook payload. The full URL should resemble `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. - 1. In the **Subscribe to events** section, scroll down and select `user.updated`. + 1. In the **Subscribe to events** section, scroll down and select `user.created`. 1. Select **Create**. You'll be redirected to your endpoint's settings page. Keep this page open. ### Add your Signing Secret to `.env.local` @@ -112,12 +118,12 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec Set up a Route Handler that uses `svix` to verify the webhook signature and process the payload. - For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.updated` event, you might perform a database `update` or `upsert` to update the user's details. + For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.created` event, you might perform a database `update` or `upsert` to update the user's details. The webhook must return either an error code or a success code, such as `200` or `201`. An error code will appear in the Clerk Dashboard log and trigger a [retry](/docs/integrations/webhooks/overview#retry). A success code will stop further retries and show a success status in the Clerk Dashboard log. > [!NOTE] - > The following Route Handler can be used for any webhook event you choose to listen to, not just `user.updated`. + > The following Route Handler can be used for any webhook event you choose to listen to, not just `user.created`. @@ -259,13 +265,13 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec `WebhookEvent` encompasses all possible webhook types. Narrow down the event type for accurate typing for specific events. - In the following example, the `if` statement narrows the type to `user.updated`, enabling type-safe access to evt.data with autocompletion. + In the following example, the `if` statement narrows the type to `user.created`, enabling type-safe access to evt.data with autocompletion. ```ts {{ filename: 'app/api/webhooks/route.ts', del: [1, 2], ins: [[4, 6]] }} console.log(`Received webhook with ID ${id} and event type of ${eventType}`) console.log('Webhook payload:', body) - if (evt.type === 'user.updated') { + if (evt.type === 'user.created') { console.log('userId:', evt.data.id) } ``` @@ -285,7 +291,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. Start your Next.js server. 1. In your endpoint's settings page in the Clerk Dashboard, select the **Testing** tab. - 1. In the **Select event** dropdown, select `user.updated`. + 1. In the **Select event** dropdown, select `user.created`. 1. Select **Send Example**. 1. In the **Message Attempts** section, confirm that the event is labeled with `Succeeded`. @@ -298,7 +304,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Trigger the webhook - To trigger the `user.updated` event, you can do either one of the following: + To trigger the `user.created` event, you can do either one of the following: 1. Edit your user in the Clerk Dashboard. 1. Select the `` component in your app to edit your profile. @@ -310,5 +316,6 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. When you're ready to deploy your app to production, follow [the guide on deploying your Clerk app to production](/docs/deployments/overview). 1. Create your production webhook by following the steps in the previous [Set up a webhook endpoint](#set-up-a-webhook-endpoint) section. In the **Endpoint URL** field, instead of pasting the ngrok URL, paste your production app URL. -1. After you've set up your webhook endpoint, you'll be redirected to your endpoint's settings page. Copy the **Signing Secret** and update your `.env.local` file with the new **Signing Secret**. -1. On your hosting platform, update your environment variables with the new **Signing Secret**. Redeploy your app. +1. After you've set up your webhook endpoint, you'll be redirected to your endpoint's settings page. Copy the **Signing Secret**. +1. On your hosting platform, update your environment variables by adding **Signing Secret** with the key of `SIGNING_SECRET`. +1. Redeploy your app. From 99ccb1cdf51b70c88c1a3769a60861cca2c6bd54 Mon Sep 17 00:00:00 2001 From: victoria Date: Thu, 31 Oct 2024 17:46:01 +0100 Subject: [PATCH 26/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index f688839759..f8cbc85b58 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -170,7 +170,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 'svix-signature': svix_signature, }) as WebhookEvent } catch (err) { - console.error('Error verifying webhook:', err) + console.error('Error: Could not verify webhook:', err) return new Response('Verification error', { status: 400, }) From 831f35423a21bc26e4e889791f22ab2d21866ada Mon Sep 17 00:00:00 2001 From: victoria Date: Thu, 31 Oct 2024 17:46:13 +0100 Subject: [PATCH 27/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index f8cbc85b58..5c31d00ddc 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -237,7 +237,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 'svix-signature': svix_signature as string, }) } catch (err) { - console.log('Error verifying webhook:', err.message) + console.log('Error: Could not verify webhook:', err.message) return void res.status(400).json({ success: false, message: err.message, From 770f3c73131b406cf59406d095b444d75f8ecc4d Mon Sep 17 00:00:00 2001 From: victoria Date: Thu, 31 Oct 2024 17:49:25 +0100 Subject: [PATCH 28/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 5c31d00ddc..6350fac377 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -76,7 +76,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Set the webhook route as public in your Middleware - Incoming webhook events won't be signed in—they come from an external source and are therefore always in a signed-out state. To allow access, the route should be public. + Incoming webhook events have no auth information. They come from an external source and will not be signed in or signed out. To allow access, the route should be public. The following example shows the recommended Middleware configuration for webhook routes. From 273c94d921d23b2728a56c0f8465d887935926d4 Mon Sep 17 00:00:00 2001 From: victoria Date: Thu, 31 Oct 2024 17:55:26 +0100 Subject: [PATCH 29/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 6350fac377..16a0dc4ebb 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -116,7 +116,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Create the endpoint - Set up a Route Handler that uses `svix` to verify the webhook signature and process the payload. + Set up a Route Handler that uses `svix` to verify the webhook and process the payload. For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.created` event, you might perform a database `update` or `upsert` to update the user's details. From 7f47a3e6bf5c024cd7696f9677bcb3ba7d26e9e9 Mon Sep 17 00:00:00 2001 From: victoria Date: Thu, 31 Oct 2024 17:55:39 +0100 Subject: [PATCH 30/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 16a0dc4ebb..851708ce02 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -202,7 +202,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec const SIGNING_SECRET = process.env.SIGNING_SECRET if (!SIGNING_SECRET) { - throw new Error('Please add SIGNING_SECRET from Clerk Dashboard to .env') + throw new Error('Error: Please add SIGNING_SECRET from Clerk Dashboard to .env') } // Create new Svix instance with secret From 683fd7ea7788386defc551ede89d2f49a9544d0f Mon Sep 17 00:00:00 2001 From: vi Date: Thu, 31 Oct 2024 17:57:57 +0100 Subject: [PATCH 31/44] fix msg and add link --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 851708ce02..9cfe3bf30c 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -120,7 +120,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.created` event, you might perform a database `update` or `upsert` to update the user's details. - The webhook must return either an error code or a success code, such as `200` or `201`. An error code will appear in the Clerk Dashboard log and trigger a [retry](/docs/integrations/webhooks/overview#retry). A success code will stop further retries and show a success status in the Clerk Dashboard log. + The webhook must return either an [error code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses) such as `405` or `403` or a [success code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses), such as `200` or `201`. An error code will appear in the Clerk Dashboard log and trigger a [retry](/docs/integrations/webhooks/overview#retry). A success code will stop further retries and show a success status in the Clerk Dashboard log. > [!NOTE] > The following Route Handler can be used for any webhook event you choose to listen to, not just `user.created`. From 996983b1674b5a506181100bf954ad996b3d7f45 Mon Sep 17 00:00:00 2001 From: victoria Date: Thu, 31 Oct 2024 18:06:43 +0100 Subject: [PATCH 32/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 9cfe3bf30c..3db02e28c6 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -171,7 +171,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec }) as WebhookEvent } catch (err) { console.error('Error: Could not verify webhook:', err) - return new Response('Verification error', { + return new Response('Error: Verification error', { status: 400, }) } From df7e4429f6ef7c98a13b4f05df0cb45e3645c224 Mon Sep 17 00:00:00 2001 From: victoria Date: Thu, 31 Oct 2024 18:06:52 +0100 Subject: [PATCH 33/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 3db02e28c6..7e5bd38f15 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -137,7 +137,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec const SIGNING_SECRET = process.env.SIGNING_SECRET if (!SIGNING_SECRET) { - throw new Error('Please add SIGNING_SECRET from Clerk Dashboard to .env or .env.local') + throw new Error('Error: Please add SIGNING_SECRET from Clerk Dashboard to .env or .env.local') } // Create new Svix instance with secret From 85e9856f64e9b0af8cfc31154111c58443c773ad Mon Sep 17 00:00:00 2001 From: victoria Date: Fri, 1 Nov 2024 17:19:40 +0100 Subject: [PATCH 34/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 7e5bd38f15..3742a21547 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -30,7 +30,7 @@ The recommended way to sync Clerk data to your app is through webhooks. In this guide, you'll set up a webhook in your Next.js app to listen for the `user.created` event, create an endpoint in the Clerk Dashboard, build a handler, and test it locally using ngrok and the Clerk Dashboard. -Clerk offers many user events, but three key events include: +Clerk offers many events, but three key events include: - `user.created`: Triggers when a new user registers in the app or is created via the Clerk Dashboard or Backend API. Listening to this event allows the initial insertion of user information in your database. - `user.updated`: Triggers when user information is updated via Clerk components, the Clerk Dashboard, or Backend API. Listening to this event keeps data synced between Clerk and your external database. It is recommended to only sync what you need to simplify this process. From eb60c2928ae54733f368c99e3b604a171250b6e4 Mon Sep 17 00:00:00 2001 From: victoria Date: Fri, 1 Nov 2024 19:41:40 +0100 Subject: [PATCH 35/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 3742a21547..aefea09592 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -76,7 +76,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Set the webhook route as public in your Middleware - Incoming webhook events have no auth information. They come from an external source and will not be signed in or signed out. To allow access, the route should be public. + Incoming webhook events have no auth information. They come from an external source and will not be signed in or signed out. To allow access, the route must be public. The following example shows the recommended Middleware configuration for webhook routes. From b0306cef673d80824f5069128b8aa9af195bba89 Mon Sep 17 00:00:00 2001 From: victoria Date: Fri, 1 Nov 2024 19:42:46 +0100 Subject: [PATCH 36/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index aefea09592..9155c519a4 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -118,7 +118,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec Set up a Route Handler that uses `svix` to verify the webhook and process the payload. - For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.created` event, you might perform a database `update` or `upsert` to update the user's details. + For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.created` event, you might perform a database `create` or `upsert` to add the user's details to the user's table. The webhook must return either an [error code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses) such as `405` or `403` or a [success code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses), such as `200` or `201`. An error code will appear in the Clerk Dashboard log and trigger a [retry](/docs/integrations/webhooks/overview#retry). A success code will stop further retries and show a success status in the Clerk Dashboard log. From 2a00852e248db7b3d40c08a108f07102aad19652 Mon Sep 17 00:00:00 2001 From: vi Date: Tue, 5 Nov 2024 10:52:29 +0100 Subject: [PATCH 37/44] update --- docs/integrations/webhooks/sync-data.mdx | 28 ++++++------------------ 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 9155c519a4..6ce864b8fa 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -53,8 +53,6 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Set up a webhook endpoint - To set up a webhook endpoint, you must provide the **Endpoint URL** and choose the events you want to listen to. For this guide, select the `user.created` event. - 1. In the Clerk Dashboard, navigate to the [**Webhooks**](https://dashboard.clerk.com/last-active?path=webhooks) page. 1. Select **Add Endpoint**. 1. In the **Endpoint URL** field, paste the ngrok **Forwarding** URL you saved earlier, followed by `/api/webhooks`. This is the endpoint that Svix uses to send the webhook payload. The full URL should resemble `https://fawn-two-nominally.ngrok-free.app/api/webhooks`. @@ -78,27 +76,13 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec Incoming webhook events have no auth information. They come from an external source and will not be signed in or signed out. To allow access, the route must be public. - The following example shows the recommended Middleware configuration for webhook routes. - - ```ts {{ filename: 'middleware.ts' }} - import { clerkMiddleware } from '@clerk/nextjs/server' - - // Make sure that the `/api/webhooks(.*)` route is not protected here - export default clerkMiddleware() + Incoming webhook events contain no authentication information. They come from an external source and won't be signed in or signed out, so the route must be public to allow access. - export const config = { - matcher: [ - // Skip Next.js internals and all static files, unless found in search params - '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', - // Always run for API routes - '/(api|trpc)(.*)', - ], - } - ``` + To configure your Middleware, refer to the [clerkMiddleware() guide](docs/references/nextjs/clerk-middleware). ### Install `svix` - You'll use [`svix`](https://www.npmjs.com/package/svix) to verify the webhook signature. Run the following command in your terminal to install it: + Clerk uses [`svix`](https://www.npmjs.com/package/svix) to deliver webhooks, so you'll need the package to verify the webhook signature. Run the following command in your terminal to install it: ```bash {{ filename: 'terminal' }} @@ -116,11 +100,13 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Create the endpoint - Set up a Route Handler that uses `svix` to verify the webhook and process the payload. + Set up a Route Handler that uses `svix` to verify the incoming Clerk webhook and process the payload. For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.created` event, you might perform a database `create` or `upsert` to add the user's details to the user's table. - The webhook must return either an [error code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses) such as `405` or `403` or a [success code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses), such as `200` or `201`. An error code will appear in the Clerk Dashboard log and trigger a [retry](/docs/integrations/webhooks/overview#retry). A success code will stop further retries and show a success status in the Clerk Dashboard log. + If the route handler returns a [2xx code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses), the event will be marked as successful, and retries will stop. If the route handler returns a [4xx](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses) or [5xx code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses), or no code at all, the webhook event will be [retried](/docs/integrations/webhooks/overview#retry). + + In summary, a 2xx (success) code stops retries, while any other response is considered a failure and will trigger retries. > [!NOTE] > The following Route Handler can be used for any webhook event you choose to listen to, not just `user.created`. From 23cff81523e300cb8b961a818c1df7df8a002c89 Mon Sep 17 00:00:00 2001 From: victoria Date: Fri, 8 Nov 2024 01:10:33 +0100 Subject: [PATCH 38/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 6ce864b8fa..8ac6ca13ef 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -84,7 +84,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec Clerk uses [`svix`](https://www.npmjs.com/package/svix) to deliver webhooks, so you'll need the package to verify the webhook signature. Run the following command in your terminal to install it: - + ```bash {{ filename: 'terminal' }} npm install svix ``` From 362ff068b3b61b4afcd571dfbf2bc84227cc7bfc Mon Sep 17 00:00:00 2001 From: victoria Date: Fri, 8 Nov 2024 01:10:43 +0100 Subject: [PATCH 39/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 8ac6ca13ef..dfb0881ec9 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -82,7 +82,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Install `svix` - Clerk uses [`svix`](https://www.npmjs.com/package/svix) to deliver webhooks, so you'll need the package to verify the webhook signature. Run the following command in your terminal to install it: + Clerk uses [`svix`](https://www.npmjs.com/package/svix) to deliver webhooks, so you'll use it to verify the webhook signature. Run the following command in your terminal to install the package: ```bash {{ filename: 'terminal' }} From 628e0ac7fcb2c9294dc75780e22694a0f73bba67 Mon Sep 17 00:00:00 2001 From: victoria Date: Fri, 8 Nov 2024 01:11:10 +0100 Subject: [PATCH 40/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- docs/integrations/webhooks/sync-data.mdx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index dfb0881ec9..5058c42325 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -104,9 +104,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec For this guide, the payload will be logged to the console. In a real app, you'd use the payload to trigger an action. For example, if listening for the `user.created` event, you might perform a database `create` or `upsert` to add the user's details to the user's table. - If the route handler returns a [2xx code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses), the event will be marked as successful, and retries will stop. If the route handler returns a [4xx](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses) or [5xx code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses), or no code at all, the webhook event will be [retried](/docs/integrations/webhooks/overview#retry). - - In summary, a 2xx (success) code stops retries, while any other response is considered a failure and will trigger retries. + If the route handler returns a [4xx](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses) or [5xx code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses), or no code at all, the webhook event will be [retried](/docs/integrations/webhooks/overview#retry). If the route handler returns a [2xx code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses), the event will be marked as successful, and retries will stop. > [!NOTE] > The following Route Handler can be used for any webhook event you choose to listen to, not just `user.created`. From e0653fd3d5d3b3283417cb5907cfc6e0799e9471 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 13 Nov 2024 14:58:58 -0500 Subject: [PATCH 41/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 5058c42325..93db7b4f0c 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -301,5 +301,5 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. When you're ready to deploy your app to production, follow [the guide on deploying your Clerk app to production](/docs/deployments/overview). 1. Create your production webhook by following the steps in the previous [Set up a webhook endpoint](#set-up-a-webhook-endpoint) section. In the **Endpoint URL** field, instead of pasting the ngrok URL, paste your production app URL. 1. After you've set up your webhook endpoint, you'll be redirected to your endpoint's settings page. Copy the **Signing Secret**. -1. On your hosting platform, update your environment variables by adding **Signing Secret** with the key of `SIGNING_SECRET`. +1. On your hosting platform, update your environment variables on your hosting platform by adding **Signing Secret** with the key of `SIGNING_SECRET`. 1. Redeploy your app. From 7596e6c2ac941f095e24bbf7be1fd3f20cd796c5 Mon Sep 17 00:00:00 2001 From: victoria Date: Wed, 13 Nov 2024 14:59:04 -0500 Subject: [PATCH 42/44] Update docs/integrations/webhooks/sync-data.mdx Co-authored-by: Roy Anger --- docs/integrations/webhooks/sync-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 93db7b4f0c..273482294d 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -293,7 +293,7 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec 1. Edit your user in the Clerk Dashboard. 1. Select the `` component in your app to edit your profile. - Once you have updated a user, you should be able to see the webhook's payload logged to your terminal. You can also check the Clerk Dashboard to see the webhook attempt, the same way you did when [testing the webhook](#test-the-webhook). + You should be able to see the webhook's payload logged to your terminal. You can also check the Clerk Dashboard to see the webhook attempt, the same way you did when [testing the webhook](#test-the-webhook). ### Configure your production instance From 51d6488ec94d800db12ae0d99aa712fb89547d3e Mon Sep 17 00:00:00 2001 From: vi Date: Wed, 13 Nov 2024 17:48:52 -0500 Subject: [PATCH 43/44] remove extra paragraph and fix wording --- docs/integrations/webhooks/sync-data.mdx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 273482294d..5e5db0fb5c 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -74,11 +74,8 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec ### Set the webhook route as public in your Middleware - Incoming webhook events have no auth information. They come from an external source and will not be signed in or signed out. To allow access, the route must be public. + Incoming webhook events don't contain auth information. They come from an external source and aren't signed in or out, so the route must be public to allow access. If you're using `clerkMiddleware()`, ensure that the `/api/webhooks(.*)` route is set as public. For information on configuring routes, see the [`clerkMiddleware()` guide](docs/references/nextjs/clerk-middleware). - Incoming webhook events contain no authentication information. They come from an external source and won't be signed in or signed out, so the route must be public to allow access. - - To configure your Middleware, refer to the [clerkMiddleware() guide](docs/references/nextjs/clerk-middleware). ### Install `svix` From 37d495446208060436f8586f6b804981a71401fe Mon Sep 17 00:00:00 2001 From: vi Date: Wed, 13 Nov 2024 17:49:59 -0500 Subject: [PATCH 44/44] lint --- docs/integrations/webhooks/sync-data.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/integrations/webhooks/sync-data.mdx b/docs/integrations/webhooks/sync-data.mdx index 5e5db0fb5c..cbcd88eadc 100644 --- a/docs/integrations/webhooks/sync-data.mdx +++ b/docs/integrations/webhooks/sync-data.mdx @@ -76,7 +76,6 @@ These steps apply to any Clerk event. To make the setup process easier, it's rec Incoming webhook events don't contain auth information. They come from an external source and aren't signed in or out, so the route must be public to allow access. If you're using `clerkMiddleware()`, ensure that the `/api/webhooks(.*)` route is set as public. For information on configuring routes, see the [`clerkMiddleware()` guide](docs/references/nextjs/clerk-middleware). - ### Install `svix` Clerk uses [`svix`](https://www.npmjs.com/package/svix) to deliver webhooks, so you'll use it to verify the webhook signature. Run the following command in your terminal to install the package: