Add and manage webhooks
Integrations
If you are experiencing issues with webhooks, it could be because the webhook request content-type header has changed from application/json to application/jwt. Read the full details here. We apologize for any inconvenience.
Webhooks are a way of monitoring events in Kinde, so that you can be notified and take action when something you’re monitoring happens.
Depending on which Kinde plan you’re on, the number of webhooks you can create might be limited. View plans.
When you create a webhook, you register your own URL endpoints in Kinde and associate them with a Kinde event (e.g. when a user is created). When an endpoint is triggered, Kinde sends data about the event, so that you can initiate an action in your application or store the data.
A simple example would be setting up a webhook for when a new user is created in Kinde. This event can be set up to trigger an update to your database, enabling your system to automatically send a welcome email.
You’ll come across these terms when you start using webhooks.
Endpoint - the URL called when an event occurs.
Event type - something that happens in Kinde, e.g. a user is created.
Event - an instance of an event type that happens in Kinde, e.g. Jane Doe just signed up.
Request - the request object sent to your endpoint that contains a JSON Web Token (JWT) with the event data and details about the event.
Attempt - an instance of an HTTP request attempt. Multiple request attempts may be made if Kinde does not receive a 200 response.
user.created.200 response is received, the workflow is complete.Kinde uses the application/jwt content-type for webhook requests.
The body of the request is a JWT token that is signed by Kinde.
eyJhbGciOiJSUzI1NiIsImtpZCI6IjJhOmUwOjRmO...Here is an example decoded payload.
You can use the Kinde webhook package to decode and verify the JWT. You can also use the Kinde Online JWT decoder to view it online.
{ "data": { "user": { "email": "user@example.com", "first_name": "Test", "id": "kp_1234567890", "is_password_reset_requested": false, "is_suspended": false, "last_name": "", "organizations": [ { "code": "org_1234567890", "permissions": null, "roles": null } ], "phone": null, "username": null } }, "event_id": "event_1234567890", "event_timestamp": "2026-02-03T12:00:00.000Z", "source": "admin", "timestamp": "2026-02-03T12:00:00.000Z", "type": "user.created"}There are a number of unique IDs you will come across with webhooks.
webhook_, this refers to a webhook that you create in Kinde. Webhook IDs are exposed via the Kinde Management API webhook endpoints. You can get a list of webhooks via the endpoint GET /api/v1/webhooksevent_, this is the ID of an event that has occurred in your account, and is included as event_id in webhook request payloads. You can use this ID to retrieve an event from Kinde’s API using GET /api/v1/events/{event_id}webhook-id, this is unique to a webhook and event, and will not change between attempts. You can use this as the idempotency key (see Webhooks security below).Kinde provides a webhooks decoder to help you decode and validate webhook tokens for easier implementation.
Here’s how to use it in a JavaScript application:
import { decodeWebhook } from "@kinde/webhooks";
const decodedToken = await decodeWebhook( "eyJhbGciOiJSUzI1NiIsImtpZCI6IjJhOmUwOjRmO...", "https://your-kinde-subdomain.kinde.com"); // KINDE_ISSUER_URL
if(!decodedToken) { // return early if the webhook is not valid // send a 400 response to Kinde return; }
if(decodedToken.type === "user.created") { // send a 200 response to Kinde // handle user created event}If you are using a different programming language, you will need the JWKS URL to verify the JWT. You can find the JWKS URL athttps://<your_subdomain>.kinde.com/.well-known/jwks.
Each webhook request has a webhook-id header that can be used to avoid reprocessing the same webhook request. This is referred to as the idempotency key, meaning that multiple requests will result in the same outcome.
A replay attack occurs when a payload is intercepted, potentially modified, and re-transmitted. Kinde webhooks contain a timestamp attribute in the payload, and the payload is a signed JSON Web Token (JWT). This allows you to verify that the request came from Kinde, and check the timestamp to prevent replay attacks.
You can request events by their event_id using the Kinde Management API via /api/v1/events/{event_id}. The event_id is provided in all webhook requests.
Ensure webhooks are secure and optimized.
If Kinde fails to receive a 200 response from your endpoint, Kinde operates a back-off retry policy, which roughly equates to the following attempts:
Webhooks that fail consistently for 72 hours are automatically disabled, and you’ll receive an email notification when this happens. This prevents runaway failures from impacting your system and keeps you informed so you can investigate and re-enable when ready.
Now that you know about webhooks, your next steps are to: