From 8304482e186ee25d4b9b1cb1ca969f88dc83724d Mon Sep 17 00:00:00 2001 From: Tamal Anwar Chowdhury Date: Wed, 4 Feb 2026 23:58:28 +0600 Subject: [PATCH 1/9] add the initial setup guides --- .../third-party-tools/kinde-loops.mdx | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 src/content/docs/integrate/third-party-tools/kinde-loops.mdx diff --git a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx new file mode 100644 index 000000000..64ef73986 --- /dev/null +++ b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx @@ -0,0 +1,241 @@ +--- +page_id: 5e97601f-3b77-4034-ae12-31737020b254 +title: Connect Loops to Kinde (via Zapier) +description: Step-by-step guide to connecting Kinde webhooks with Loops via Zapier for email automation and marketing campaigns using webhooks and event hooks +sidebar: + order: 14 +relatedArticles: + - 7fe91aba-930c-4a63-8996-85af6bb605a7 + - 95bf5e04-3415-4dc8-9ff6-953171df3b8b + - 84581694-59d6-4a02-ab8b-c7a2889713d5 + - c9e65865-caac-45ed-a71c-2a5dd2ecd4d8 +topics: + - integrate + - third-party-tools +sdk: [] +languages: [] +audience: + - developers + - business owners +complexity: beginner +keywords: + - loops + - email marketing + - automation + - integration + - webhooks + - zapier + - email campaigns +updated: 2026-02-04 +featured: false +deprecated: false +ai_summary: Step-by-step guide to connecting Kinde webhooks with Loops via Zapier for email automation and marketing campaigns using webhooks and event hooks. +--- + +This guide will walk you through connecting Kinde webhooks to Loops via Zapier, allowing you to automatically sync your Kinde users to Loops for email marketing and automation. When events like user creation or authentication happen in Kinde, they can trigger automated actions to add or update contacts in Loops. + +### What you need + +- A [Kinde](https://www.kinde.com/register) account with an available webhook slot (Sign up for free) +- A [Loops](https://loops.so/) account (Sign up for free) +- A [Zapier](https://zapier.com/) account (Professional plan or higher required for webhook triggers) + +## Step 1: Create a Zap in Zapier + +1. Log in to your Zapier account and select **Create** > **Zaps** +2. In the **Trigger** step, search for **Webhooks** and select it. +3. In the **Event** dropdown, select **Catch Raw Hook**, then select **Continue** + + + +4. In the **Test** tab, Zapier will generate a unique webhook URL for your Zap. The URL will look like: `https://hooks.zapier.com/hooks/catch/1234567/abcdefg/` + + Copy this URL - you'll need it in the next step. + + Keep this Zap open - you'll return to it after configuring the webhook in Kinde. + +## Step 2: Create a webhook in Kinde + +1. In your Kinde dashboard, go to **Settings > Webhooks** +2. Select **Add webhook** +3. Give your webhook a descriptive name (e.g., "Kinde Zapier Loops") +4. Enter a description explaining what this webhook is for (e.g., "Sync users to Loops when created") +5. In the **Endpoint URL** field, paste the Zapier webhook URL you copied in Step 1 +6. Select **Add event** to select which events you want to trigger this webhook + + For this example, select `user.created` to trigger the webhook when a new user is created + + Common events you might want to monitor: + - `user.created` - When a new user signs up + - `user.updated` - When user information is updated + - `user.authenticated` - When a user logs in + - `organization.created` - When a new organization is created + + For a complete list of available events, see [Add and manage webhooks](/integrate/webhooks/add-manage-webhooks#webhook-triggers) + +7. Select **Save** to create the webhook + +## Step 3: Test the webhook trigger + +1. In your Kinde dashboard, create a test user to trigger the webhook: + - Go to **Users** and select **Add user** + - Enter test user details (e.g., name: "Test User", email: "test@example.com") + - Select **Save** +2. Return to Zapier and select **Test trigger** in the trigger step +3. You should see the webhook data appear (request A). The data will be a raw JWT token string in the body +4. Select **Continue with selected record** to proceed to the next step +5. Zapier will open a new popup. Search for **Code** and select it + +## Step 4: Decode the JWT using Zapier Code action + +Since Kinde sends webhook data as a JWT token, you'll need to decode it to access the user information. Zapier's Code action allows you to run JavaScript to decode the JWT. + +1. Select **Code by Zapier** and from the Action event dropdown, select **Run JavaScript** as the action. Select **Continue** +2. In the **Input Data** field, add a field called `jwt` and map it to the **Raw Body** from the webhook trigger +3. In the **Code** field, paste the following JavaScript to decode the JWT, replacing the existing code: + + ```javascript + // Function to decode a JWT token + function decodeJWT(token) { + const parts = token.split('.'); + if (parts.length !== 3) { + throw new Error('Invalid JWT token'); + } + + const payload = parts[1]; + const decoded = JSON.parse(Buffer.from(payload, 'base64').toString('utf-8')); + return decoded; + } + + // Get the JWT from input data + const jwt = inputData.jwt; + + // Decode the JWT + const decoded = decodeJWT(jwt); + + // Extract user data from the decoded payload + const userData = decoded.data.user || {}; + + // Return the decoded data + return { + firstName: userData.first_name || '', + lastName: userData.last_name || '', + email: userData.email || '', + fullName: `${userData.first_name || ''} ${userData.last_name || ''}`.trim(), + userId: userData.id || '', + rawData: decoded + }; + ``` + +4. Select **Continue**, then **Test step** to verify the JWT is decoded correctly. +5. You should see the decoded user data including first name, last name, and email +6. Select **Continue** + + + +## Step 5: Add Loops action + +Now that you have decoded the JWT, you can use the extracted data to add contacts to Loops. This will sync your Kinde users to Loops for email marketing and automation. + +1. In Zapier, edit your Zap and select the plus icon **+** to add another step after the Code action +2. Search for **Loops** and select it +3. From the Action event dropdown, select **Add Contact** as the action +4. Connect your Loops account: + - Click **Sign in to Loops** + - Enter your Loops API key (you can find this in your Loops dashboard under **Settings > API Keys**) + - Select **Continue** +5. Map the fields from your decoded JWT to Loops: + - **Email**: Map to the `Email` field from the Code step output (required) + - **First Name**: Map to the `First Name` field from the Code step output + - **Last Name**: Map to the `Last Name` field from the Code step output + - **User ID**: Map to the `User ID` field from the Code step output (useful for syncing with Kinde) + - **Source**: Set to `kinde` or `zapier` (optional) + - **Subscribed**: Set to `true` (default) to ensure users receive emails + +6. Select **Continue** +7. Select **Test step** to verify the contact is created in Loops +8. Check your Loops dashboard to confirm the contact was added with the correct information +9. Select **Publish** to activate your Zap + + + +## Step 6: Test the complete integration + +1. In your Kinde dashboard, go to **Users** and select **Add user** +2. Create a new user with a name and email address +3. Select **Save** to create the user +4. The webhook will automatically trigger, sending the user data to Zapier +5. Zapier will decode the JWT, extract the user information, and add the contact to Loops +6. Check your Loops dashboard to verify the contact was added with the correct name and email +7. You can also check Zapier's **Task History** to see if your Zap ran successfully + +## What you can do with Loops + +Once your Kinde users are synced to Loops, you can: + +### Automated email workflows + +- **Welcome emails**: Automatically send welcome emails to new users when they sign up +- **Onboarding sequences**: Create multi-step email sequences to guide users through your product +- **Re-engagement campaigns**: Automatically email users who haven't logged in recently +- **Product updates**: Send targeted announcements based on user properties + +### Email segmentation + +- **Segment by organization**: Use Loops segments to group users by their Kinde organization +- **Dynamic segments**: Create segments that automatically update based on user properties +- **Targeted campaigns**: Send personalized emails based on user roles, permissions, or other Kinde attributes + +### Personalization + +- **User data**: Use Kinde user data (name, email, organization) to personalize your emails +- **Dynamic content**: Show different content based on user properties from Kinde +- **Event-based triggers**: Trigger emails based on user authentication or other Kinde events + +### Analytics and engagement + +- Track email opens, clicks, and engagement rates +- Monitor email performance and optimize your campaigns +- Identify high-engagement users and create segments for them + +## Advanced workflows + +You can extend this integration to create more sophisticated workflows: + +### Update contacts on user changes + +Create a separate Zap for the `user.updated` event to keep Loops contacts in sync when user information changes in Kinde. + +### Segment users by organization + +Use Zapier's filtering or branching features to add users to different Loops mailing lists based on their organization or other properties from Kinde. + +### Multi-step automation + +Create complex workflows that: +1. Add contact to Loops +2. Add to specific mailing lists based on user properties +3. Trigger immediate emails or add to automated sequences + +### Conclusion + +Now that you've successfully connected Kinde webhooks to Loops via Zapier, you can automate your email marketing and keep your user base synchronized. This integration enables you to: + +- Automatically sync new users to Loops for email marketing +- Create personalized email campaigns based on Kinde user data +- Build automated email workflows triggered by Kinde events +- Segment your audience using data from Kinde + +For more information about Loops features and capabilities, visit the [Loops documentation](https://loops.so/docs). From 50aa74ffdf7377b5dbfd75d0dc2d4df8b81dacb6 Mon Sep 17 00:00:00 2001 From: Tamal Anwar Chowdhury Date: Fri, 6 Feb 2026 20:58:12 +0600 Subject: [PATCH 2/9] create the loops contact import section and general integration --- .../third-party-tools/kinde-loops.mdx | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx index 64ef73986..aea25e09b 100644 --- a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx +++ b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx @@ -40,7 +40,13 @@ This guide will walk you through connecting Kinde webhooks to Loops via Zapier, - A [Loops](https://loops.so/) account (Sign up for free) - A [Zapier](https://zapier.com/) account (Professional plan or higher required for webhook triggers) -## Step 1: Create a Zap in Zapier +## Step 1: Generate a Loops API key + +1. Sign in to your Loops account and go to [**Settings > API**](https://app.loops.so/settings?page=api) +2. Select **Generate key** +3. Select the newly generated key to copy it. You will need this in the next step. + +## Step 2: Create a Zap in Zapier 1. Log in to your Zapier account and select **Create** > **Zaps** 2. In the **Trigger** step, search for **Webhooks** and select it. @@ -58,13 +64,13 @@ This guide will walk you through connecting Kinde webhooks to Loops via Zapier, Keep this Zap open - you'll return to it after configuring the webhook in Kinde. -## Step 2: Create a webhook in Kinde +## Step 3: Create a webhook in Kinde 1. In your Kinde dashboard, go to **Settings > Webhooks** 2. Select **Add webhook** 3. Give your webhook a descriptive name (e.g., "Kinde Zapier Loops") 4. Enter a description explaining what this webhook is for (e.g., "Sync users to Loops when created") -5. In the **Endpoint URL** field, paste the Zapier webhook URL you copied in Step 1 +5. In the **Endpoint URL** field, paste the Zapier webhook URL you copied in Step 2 6. Select **Add event** to select which events you want to trigger this webhook For this example, select `user.created` to trigger the webhook when a new user is created @@ -79,7 +85,7 @@ This guide will walk you through connecting Kinde webhooks to Loops via Zapier, 7. Select **Save** to create the webhook -## Step 3: Test the webhook trigger +## Step 4: Test the webhook trigger 1. In your Kinde dashboard, create a test user to trigger the webhook: - Go to **Users** and select **Add user** @@ -90,7 +96,7 @@ This guide will walk you through connecting Kinde webhooks to Loops via Zapier, 4. Select **Continue with selected record** to proceed to the next step 5. Zapier will open a new popup. Search for **Code** and select it -## Step 4: Decode the JWT using Zapier Code action +## Step 5: Decode the JWT using Zapier Code action Since Kinde sends webhook data as a JWT token, you'll need to decode it to access the user information. Zapier's Code action allows you to run JavaScript to decode the JWT. @@ -106,8 +112,9 @@ Since Kinde sends webhook data as a JWT token, you'll need to decode it to acces throw new Error('Invalid JWT token'); } - const payload = parts[1]; - const decoded = JSON.parse(Buffer.from(payload, 'base64').toString('utf-8')); + const payload = parts[1].replace(/-/g, '+').replace(/_/g, '/'); + const padded = payload + '='.repeat((4 - (payload.length % 4)) % 4); + const decoded = JSON.parse(Buffer.from(padded, 'base64').toString('utf-8')); return decoded; } @@ -127,6 +134,7 @@ Since Kinde sends webhook data as a JWT token, you'll need to decode it to acces email: userData.email || '', fullName: `${userData.first_name || ''} ${userData.last_name || ''}`.trim(), userId: userData.id || '', + orgCode: userData.organizations[0].code || '', rawData: decoded }; ``` @@ -141,7 +149,7 @@ Since Kinde sends webhook data as a JWT token, you'll need to decode it to acces -## Step 5: Add Loops action +## Step 6: Add Loops action Now that you have decoded the JWT, you can use the extracted data to add contacts to Loops. This will sync your Kinde users to Loops for email marketing and automation. @@ -150,13 +158,14 @@ Now that you have decoded the JWT, you can use the extracted data to add contact 3. From the Action event dropdown, select **Add Contact** as the action 4. Connect your Loops account: - Click **Sign in to Loops** - - Enter your Loops API key (you can find this in your Loops dashboard under **Settings > API Keys**) + - Enter your Loops API key you copied from Step 1 - Select **Continue** 5. Map the fields from your decoded JWT to Loops: - **Email**: Map to the `Email` field from the Code step output (required) - **First Name**: Map to the `First Name` field from the Code step output - **Last Name**: Map to the `Last Name` field from the Code step output - **User ID**: Map to the `User ID` field from the Code step output (useful for syncing with Kinde) + - **User Group**: Map to the `Org Code` field from the Code step output (useful for segmentation by user or audience groups) - **Source**: Set to `kinde` or `zapier` (optional) - **Subscribed**: Set to `true` (default) to ensure users receive emails @@ -181,6 +190,23 @@ Now that you have decoded the JWT, you can use the extracted data to add contact 6. Check your Loops dashboard to verify the contact was added with the correct name and email 7. You can also check Zapier's **Task History** to see if your Zap ran successfully +## Import Kinde users to Loops + +You can import all your Kinde users to Loops using the Kinde's export user feature. Follow the steps: + +1. In your Kinde dashboard, go to **Settings > Business > Details** +2. Scroll down to the **Export data** section and select **Export** +3. In the pop-up window, select **All data (except passwords)**, then select **Next** +4. Enter the one-time verification code sent to your email and select **Next** +5. You will be able to download the `kinde_export.zip` file +6. Unzip the file and you will see the `users.ndjson` file with all your Kinde users data +7. Create a new `.csv` file with the following columns: `First Name`, `Last Name`, `Email`, `User Group`. Copy the Kinde contacts to this `.csv` file +8. Go to Loops > **Audience**, and select **Import**, a pop-up opens +9. Select **CSV** and select **Upload CSV** +10. On the new screen, upload your `.csv` file you created earlier and select **Next** +11. Map the CSV columns and select **Import contacts** +12. You will see the imported users in Loops **Audience** page + ## What you can do with Loops Once your Kinde users are synced to Loops, you can: From e9a8a204ebdb6f7c34513042ba77fb2aa7cd4e3a Mon Sep 17 00:00:00 2001 From: Tamal Anwar Chowdhury Date: Fri, 6 Feb 2026 22:15:40 +0600 Subject: [PATCH 3/9] update the loops documentation --- .../third-party-tools/kinde-loops.mdx | 76 ++++--------------- 1 file changed, 15 insertions(+), 61 deletions(-) diff --git a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx index aea25e09b..77a4f4ea8 100644 --- a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx +++ b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx @@ -42,9 +42,11 @@ This guide will walk you through connecting Kinde webhooks to Loops via Zapier, ## Step 1: Generate a Loops API key -1. Sign in to your Loops account and go to [**Settings > API**](https://app.loops.so/settings?page=api) +1. Sign in to your Loops account and go to **Settings > API** 2. Select **Generate key** 3. Select the newly generated key to copy it. You will need this in the next step. +4. If you want to add the contacts to specific mailing lists in Loops, go to **Settings > Lists > Mailing lists** and select **Create a list** +5. Enter a name and description for the list, and copy the list ID. You will need this when creating the Zap in Zapier ## Step 2: Create a Zap in Zapier @@ -75,11 +77,10 @@ This guide will walk you through connecting Kinde webhooks to Loops via Zapier, For this example, select `user.created` to trigger the webhook when a new user is created - Common events you might want to monitor: - - `user.created` - When a new user signs up + Common events you might use: + - `user.created` - When a new user signs up for the first time - `user.updated` - When user information is updated - - `user.authenticated` - When a user logs in - - `organization.created` - When a new organization is created + - `user.authenticated` - When a new or existing user logs in For a complete list of available events, see [Add and manage webhooks](/integrate/webhooks/add-manage-webhooks#webhook-triggers) @@ -92,7 +93,7 @@ This guide will walk you through connecting Kinde webhooks to Loops via Zapier, - Enter test user details (e.g., name: "Test User", email: "test@example.com") - Select **Save** 2. Return to Zapier and select **Test trigger** in the trigger step -3. You should see the webhook data appear (request A). The data will be a raw JWT token string in the body +3. You should see the webhook data appear. The data will be a raw JWT token string in the body 4. Select **Continue with selected record** to proceed to the next step 5. Zapier will open a new popup. Search for **Code** and select it @@ -134,7 +135,7 @@ Since Kinde sends webhook data as a JWT token, you'll need to decode it to acces email: userData.email || '', fullName: `${userData.first_name || ''} ${userData.last_name || ''}`.trim(), userId: userData.id || '', - orgCode: userData.organizations[0].code || '', + orgCode: (userData.organizations && userData.organizations[0] && userData.organizations[0].code) || '', rawData: decoded }; ``` @@ -164,10 +165,11 @@ Now that you have decoded the JWT, you can use the extracted data to add contact - **Email**: Map to the `Email` field from the Code step output (required) - **First Name**: Map to the `First Name` field from the Code step output - **Last Name**: Map to the `Last Name` field from the Code step output - - **User ID**: Map to the `User ID` field from the Code step output (useful for syncing with Kinde) - - **User Group**: Map to the `Org Code` field from the Code step output (useful for segmentation by user or audience groups) - **Source**: Set to `kinde` or `zapier` (optional) - **Subscribed**: Set to `true` (default) to ensure users receive emails + - **User Group**: Map to the `Org Code` field from the Code step output (useful for segmentation by user or audience groups) + - **User ID**: Map to the `User ID` field from the Code step output (useful for syncing with Kinde) + - **Mailing list**: Add the user to a mailing list in Loops. Enter the list ID you copied from Step 1 and set the value to `true` 6. Select **Continue** 7. Select **Test step** to verify the contact is created in Loops @@ -180,7 +182,7 @@ Now that you have decoded the JWT, you can use the extracted data to add contact -## Step 6: Test the complete integration +## Step 7: Test the complete integration 1. In your Kinde dashboard, go to **Users** and select **Add user** 2. Create a new user with a name and email address @@ -192,7 +194,7 @@ Now that you have decoded the JWT, you can use the extracted data to add contact ## Import Kinde users to Loops -You can import all your Kinde users to Loops using the Kinde's export user feature. Follow the steps: +You can import all your Kinde users to Loops using Kinde's export user feature. Follow these steps: 1. In your Kinde dashboard, go to **Settings > Business > Details** 2. Scroll down to the **Export data** section and select **Export** @@ -200,61 +202,13 @@ You can import all your Kinde users to Loops using the Kinde's export user featu 4. Enter the one-time verification code sent to your email and select **Next** 5. You will be able to download the `kinde_export.zip` file 6. Unzip the file and you will see the `users.ndjson` file with all your Kinde users data -7. Create a new `.csv` file with the following columns: `First Name`, `Last Name`, `Email`, `User Group`. Copy the Kinde contacts to this `.csv` file -8. Go to Loops > **Audience**, and select **Import**, a pop-up opens +7. Create a new `.csv` file with the following columns: `First Name`, `Last Name`, `Email`, `User Group`. Copy the user data from the `users.ndjson` file to this `.csv` file +8. Go to Loops > **Audience**, and select **Import**. A pop-up opens 9. Select **CSV** and select **Upload CSV** 10. On the new screen, upload your `.csv` file you created earlier and select **Next** 11. Map the CSV columns and select **Import contacts** 12. You will see the imported users in Loops **Audience** page -## What you can do with Loops - -Once your Kinde users are synced to Loops, you can: - -### Automated email workflows - -- **Welcome emails**: Automatically send welcome emails to new users when they sign up -- **Onboarding sequences**: Create multi-step email sequences to guide users through your product -- **Re-engagement campaigns**: Automatically email users who haven't logged in recently -- **Product updates**: Send targeted announcements based on user properties - -### Email segmentation - -- **Segment by organization**: Use Loops segments to group users by their Kinde organization -- **Dynamic segments**: Create segments that automatically update based on user properties -- **Targeted campaigns**: Send personalized emails based on user roles, permissions, or other Kinde attributes - -### Personalization - -- **User data**: Use Kinde user data (name, email, organization) to personalize your emails -- **Dynamic content**: Show different content based on user properties from Kinde -- **Event-based triggers**: Trigger emails based on user authentication or other Kinde events - -### Analytics and engagement - -- Track email opens, clicks, and engagement rates -- Monitor email performance and optimize your campaigns -- Identify high-engagement users and create segments for them - -## Advanced workflows - -You can extend this integration to create more sophisticated workflows: - -### Update contacts on user changes - -Create a separate Zap for the `user.updated` event to keep Loops contacts in sync when user information changes in Kinde. - -### Segment users by organization - -Use Zapier's filtering or branching features to add users to different Loops mailing lists based on their organization or other properties from Kinde. - -### Multi-step automation - -Create complex workflows that: -1. Add contact to Loops -2. Add to specific mailing lists based on user properties -3. Trigger immediate emails or add to automated sequences - ### Conclusion Now that you've successfully connected Kinde webhooks to Loops via Zapier, you can automate your email marketing and keep your user base synchronized. This integration enables you to: From 2921529a01dafd714a49f5c90b8aa8b3280d663e Mon Sep 17 00:00:00 2001 From: Tamal Anwar Chowdhury Date: Fri, 6 Feb 2026 22:20:24 +0600 Subject: [PATCH 4/9] update related articles --- .../docs/integrate/third-party-tools/kinde-loops.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx index 77a4f4ea8..057adee3c 100644 --- a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx +++ b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx @@ -5,10 +5,10 @@ description: Step-by-step guide to connecting Kinde webhooks with Loops via Zapi sidebar: order: 14 relatedArticles: - - 7fe91aba-930c-4a63-8996-85af6bb605a7 - - 95bf5e04-3415-4dc8-9ff6-953171df3b8b + - 55350C9F-88FA-4996-B648-A4B5C11C8FFF + - 5d958ce9-27ee-420a-9e20-09a2ed7fb179 - 84581694-59d6-4a02-ab8b-c7a2889713d5 - - c9e65865-caac-45ed-a71c-2a5dd2ecd4d8 +next: false topics: - integrate - third-party-tools From fc98dfca82605207ffb8c669763d9d23add64943 Mon Sep 17 00:00:00 2001 From: Tamal Anwar Chowdhury Date: Fri, 6 Feb 2026 23:38:26 +0600 Subject: [PATCH 5/9] update broken link --- src/content/docs/integrate/third-party-tools/kinde-loops.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx index 057adee3c..f907fb58d 100644 --- a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx +++ b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx @@ -146,7 +146,7 @@ Since Kinde sends webhook data as a JWT token, you'll need to decode it to acces From a0ac49e491939a9bdeb2312ee8392c28057b2e77 Mon Sep 17 00:00:00 2001 From: Tamal Anwar Chowdhury Date: Sat, 7 Feb 2026 18:31:52 +0600 Subject: [PATCH 6/9] added a python script to guide users to convert ndjson to csv file --- .../third-party-tools/kinde-loops.mdx | 83 ++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx index f907fb58d..a7bf289e1 100644 --- a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx +++ b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx @@ -202,7 +202,88 @@ You can import all your Kinde users to Loops using Kinde's export user feature. 4. Enter the one-time verification code sent to your email and select **Next** 5. You will be able to download the `kinde_export.zip` file 6. Unzip the file and you will see the `users.ndjson` file with all your Kinde users data -7. Create a new `.csv` file with the following columns: `First Name`, `Last Name`, `Email`, `User Group`. Copy the user data from the `users.ndjson` file to this `.csv` file +7. Create a new `.csv` file with the following columns: `First Name`, `Last Name`, `Email`, `User Group`. + + Copy the user data from the `users.ndjson` file to this `.csv` file + + You can use the following Python script to convert `users.ndjson` to `.csv` file: + + ```python + #!/usr/bin/env python3 + # convert_users_to_csv.py + """ + Convert users.ndjson to CSV with columns: + First Name, Last Name, Email, User Group + """ + + import json + import csv + import os + + def extract_user_groups(user_data): + """Extract user groups from organizations field.""" + if 'organizations' in user_data and user_data['organizations']: + # Extract organization codes and join them with comma + org_codes = [org.get('code', '') for org in user_data['organizations'] if isinstance(org, dict)] + return ', '.join(org_codes) + return '' + + def convert_ndjson_to_csv(input_file, output_file): + """Convert NDJSON file to CSV.""" + rows = [] + + # Read and parse NDJSON file + with open(input_file, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if not line: + continue + + try: + user_data = json.loads(line) + + # Extract fields with fallback to empty string + first_name = user_data.get('first_name', '') + last_name = user_data.get('last_name', '') + email = user_data.get('email', '') + user_group = extract_user_groups(user_data) + + rows.append({ + 'First Name': first_name, + 'Last Name': last_name, + 'Email': email, + 'User Group': user_group + }) + except json.JSONDecodeError as e: + print(f"Warning: Skipping invalid JSON line: {e}") + continue + + # Write to CSV + if rows: + fieldnames = ['First Name', 'Last Name', 'Email', 'User Group'] + with open(output_file, 'w', newline='', encoding='utf-8') as f: + writer = csv.DictWriter(f, fieldnames=fieldnames) + writer.writeheader() + writer.writerows(rows) + + print(f"Successfully converted {len(rows)} users to {output_file}") + else: + print("No data found to convert") + + if __name__ == '__main__': + # Get the directory of this script + script_dir = os.path.dirname(os.path.abspath(__file__)) + input_file = os.path.join(script_dir, 'users.ndjson') + output_file = os.path.join(script_dir, 'users_output.csv') + + convert_ndjson_to_csv(input_file, output_file) + ``` + Run the script using the following command (You will need Python 3.x installed): + + ```bash + python3 python convert_users_to_csv.py + ``` + 8. Go to Loops > **Audience**, and select **Import**. A pop-up opens 9. Select **CSV** and select **Upload CSV** 10. On the new screen, upload your `.csv` file you created earlier and select **Next** From 69ca3df6047bc13482165a6538e793df98305473 Mon Sep 17 00:00:00 2001 From: Tamal Anwar Chowdhury Date: Sat, 7 Feb 2026 18:36:52 +0600 Subject: [PATCH 7/9] fix coderabbit issue --- src/content/docs/integrate/third-party-tools/kinde-loops.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx index a7bf289e1..f0fde34a9 100644 --- a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx +++ b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx @@ -281,7 +281,7 @@ You can import all your Kinde users to Loops using Kinde's export user feature. Run the script using the following command (You will need Python 3.x installed): ```bash - python3 python convert_users_to_csv.py + python3 convert_users_to_csv.py ``` 8. Go to Loops > **Audience**, and select **Import**. A pop-up opens From 7a4a5889b743f3ed1c69518471ade1b772ee59d0 Mon Sep 17 00:00:00 2001 From: Tamal Anwar Chowdhury Date: Mon, 9 Feb 2026 14:49:25 +0600 Subject: [PATCH 8/9] update the webhook payload example for consistency and jwt debugger --- .../third-party-tools/kinde-loops.mdx | 23 ++++++++++++++----- .../kinde-mailgun-email-delivery.mdx | 4 ++-- .../add-and-edit/send-invitations-webhook.mdx | 13 +++++++---- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx index f0fde34a9..9a635c4c7 100644 --- a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx +++ b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx @@ -108,6 +108,10 @@ Since Kinde sends webhook data as a JWT token, you'll need to decode it to acces ```javascript // Function to decode a JWT token function decodeJWT(token) { + if (!token) { + throw new Error('JWT token is missing'); + } + const parts = token.split('.'); if (parts.length !== 3) { throw new Error('Invalid JWT token'); @@ -120,13 +124,20 @@ Since Kinde sends webhook data as a JWT token, you'll need to decode it to acces } // Get the JWT from input data - const jwt = inputData.jwt; - - // Decode the JWT - const decoded = decodeJWT(jwt); + const jwt = inputData?.jwt; + + // Decode the JWT with error handling + let decoded = null; + try { + decoded = decodeJWT(jwt); + } catch (error) { + return { + error: error.message || 'Failed to decode JWT' + }; + } // Extract user data from the decoded payload - const userData = decoded.data.user || {}; + const userData = decoded?.data?.user || {}; // Return the decoded data return { @@ -135,7 +146,7 @@ Since Kinde sends webhook data as a JWT token, you'll need to decode it to acces email: userData.email || '', fullName: `${userData.first_name || ''} ${userData.last_name || ''}`.trim(), userId: userData.id || '', - orgCode: (userData.organizations && userData.organizations[0] && userData.organizations[0].code) || '', + orgCode: userData?.organizations?.[0]?.code || '', rawData: decoded }; ``` diff --git a/src/content/docs/integrate/third-party-tools/kinde-mailgun-email-delivery.mdx b/src/content/docs/integrate/third-party-tools/kinde-mailgun-email-delivery.mdx index 227395678..bd517c621 100644 --- a/src/content/docs/integrate/third-party-tools/kinde-mailgun-email-delivery.mdx +++ b/src/content/docs/integrate/third-party-tools/kinde-mailgun-email-delivery.mdx @@ -120,9 +120,9 @@ When a user is created, Kinde sends a webhook payload (as a JWT token) that cont "data": { "user": { "email": "new.user@example.com", - "user_id": "usr_abc", "first_name": "John", - "last_name": "Doe" + "last_name": "Doe", + "id": "kp_1234567890" } }, "source": "admin" diff --git a/src/content/docs/manage-users/add-and-edit/send-invitations-webhook.mdx b/src/content/docs/manage-users/add-and-edit/send-invitations-webhook.mdx index 8d9fd8c65..cd1da166b 100644 --- a/src/content/docs/manage-users/add-and-edit/send-invitations-webhook.mdx +++ b/src/content/docs/manage-users/add-and-edit/send-invitations-webhook.mdx @@ -46,12 +46,15 @@ Payload example: ```json { "type": "user.created", - "id": "evt_123", "data": { - "user_id": "usr_abc", - "email": "new.user@example.com", - "source": "admin" - } + "user": { + "email": "new.user@example.com", + "first_name": "John", + "last_name": "Doe", + "id": "kp_1234567890" + } + }, + "source": "admin" } ``` From 6273ea8fced37767ddc237f756419997d20c71af Mon Sep 17 00:00:00 2001 From: Tamal Anwar Chowdhury Date: Mon, 9 Feb 2026 14:59:35 +0600 Subject: [PATCH 9/9] update marketing consent --- .../integrate/third-party-tools/kinde-loops.mdx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx index 9a635c4c7..f70338cd1 100644 --- a/src/content/docs/integrate/third-party-tools/kinde-loops.mdx +++ b/src/content/docs/integrate/third-party-tools/kinde-loops.mdx @@ -178,9 +178,17 @@ Now that you have decoded the JWT, you can use the extracted data to add contact - **Last Name**: Map to the `Last Name` field from the Code step output - **Source**: Set to `kinde` or `zapier` (optional) - **Subscribed**: Set to `true` (default) to ensure users receive emails - - **User Group**: Map to the `Org Code` field from the Code step output (useful for segmentation by user or audience groups) - - **User ID**: Map to the `User ID` field from the Code step output (useful for syncing with Kinde) - - **Mailing list**: Add the user to a mailing list in Loops. Enter the list ID you copied from Step 1 and set the value to `true` + + 6. Select **Continue** 7. Select **Test step** to verify the contact is created in Loops