How the webhook URL works. It is a public address that records whatever is sent to it and
answers 200. An inbox keeps the 50 most recent requests, accepts bodies up to 256 KB, and is
deleted 24 hours after it was created — or sooner if you press Delete URL or our server
restarts, because requests are held in memory and never written to disk.
Anyone who has the URL can read what it received. Use sandbox and test-mode accounts, do not route production traffic or customer data through it, and delete it when you are done. Privacy details.
What is a Okta webhook?
An Okta event hook is an HTTP POST that Okta sends to an external service when chosen events occur in an org: a user is created, activated or deactivated, added to a group, assigned an application, signs in. They are the same events that appear in the System Log, delivered as they happen. An event hook is one-way and asynchronous; Okta does not wait for your answer to decide anything, which is what separates it from an inline hook, where your response changes the outcome of a sign-in or registration.
The body is an envelope whose data.events array holds one or more System Log events. Each event has an eventType such as user.lifecycle.create, an actor who caused it, a list of target objects it was done to, and an outcome. An admin sets the hook up in the Admin Console or through the API, choosing the URL, the events, and an authentication header.
What a Okta webhook request looks like
The request line and headers as they reach your server, followed by the body. Ids, tokens and the signature are placeholders.
POST /your/webhook/path HTTP/1.1
Host: your-server.example
Authorization: a-secret-you-chose-1234
Content-Type: application/json
X-Okta-Verification-Challenge: Ahs8Jw0gEXAMPLE7hV3dQ
{
"eventType": "com.okta.event_hook",
"eventTypeVersion": "1.0",
"cloudEventsVersion": "0.1",
"source": "https://your-org.okta.com/api/v1/eventHooks/who8vt36kWpkM3d8O0g7",
"eventId": "b5a188b9-5ece-4636-b041-482ffda96311",
"eventTime": "2026-01-01T12:00:02.000Z",
"contentType": "application/json",
"data": {
"events": [
{
"uuid": "febc1e2c-1a2b-11ec-9621-0242ac130002",
"published": "2026-01-01T12:00:00.000Z",
"eventType": "user.lifecycle.create",
"version": "0",
"displayMessage": "Create okta user",
"severity": "INFO",
"actor": {
"id": "00u1EXAMPLEadmin0h7",
"type": "User",
"alternateId": "admin@example.com",
"displayName": "Grace Hopper"
},
"outcome": {
"result": "SUCCESS"
},
"target": [
{
"id": "00u2EXAMPLEuser00h7",
"type": "User",
"alternateId": "ada@example.com",
"displayName": "Ada Lovelace"
}
],
"client": {
"userAgent": {
"browser": "CHROME",
"os": "Mac OS X"
},
"ipAddress": "203.0.113.10"
},
"legacyEventType": "core.user.config.user_creation.success"
}
]
}
}
Two ids matter. The envelope's eventId identifies this delivery, and each event's uuid identifies the System Log entry, which is the one to de-duplicate on. actor is who performed the action and target is what it was performed on; for a user created by an admin they are different people, and a handler that reads the actor's email creates the wrong account. alternateId is normally the login.
Headers Okta sends
| Header | Example | What it is |
|---|---|---|
Authorization | a-secret-you-chose-1234 | The authentication header and secret configured on the hook. The header name is your choice; this is the usual one. |
Content-Type | application/json | The body is JSON. |
X-Okta-Verification-Challenge | Ahs8Jw0gEXAMPLE7hV3dQ | Sent only on the one-time verification GET, not on event deliveries. |
Header names are case-insensitive. Your framework may show them lower-cased, and HTTP/2 always does.
How an Okta event hook is authenticated
Okta does not sign event hook requests. When creating the hook you choose an authentication field, which is the name of a request header, and an authentication secret, which is its value. Okta sends that header on every delivery, and your endpoint compares it with what it expects. Most people name the header Authorization; the value is sent exactly as typed, with no Bearer prefix unless you put one there.
A shared secret in a header proves only that the caller knows the secret, and says nothing about whether the body was altered, so HTTPS is doing real work here and Okta requires it. Additional custom headers can be configured if a gateway in front of your service wants its own key.
const crypto = require('crypto');
// req.headers: lower-cased request headers
// expected: the authentication secret configured on the event hook
function fromOkta(req, expected) {
const got = Buffer.from(String(req.headers['authorization'] || ''));
const want = Buffer.from(expected);
return got.length === want.length && crypto.timingSafeEqual(got, want);
}
One-time verification, timeouts and retries
Before a new hook becomes active it must be verified. Okta sends a single GET request to the URL with an X-Okta-Verification-Challenge header, and the endpoint has to answer with a JSON body of the form {"verification":"<the header value>"}. The webhook URLs created on this site do that automatically, so the hook can be verified in the Admin Console and real events inspected.
Event deliveries are different: Okta ignores the response body and only needs a 200 or 204. According to Okta's documentation at the time of writing, a delivery times out after three seconds and is retried at most once, and a 4xx is not retried at all. That is a much thinner safety net than payment providers offer, so anything that must not be missed should be reconciled against the System Log API. Deliveries are at least once and are not guaranteed to be in order.
Catch a real Okta event hook
- Press Create webhook URL at the top of this page and copy the address.
- In the Admin Console of a developer or preview org, open Workflow → Event Hooks and create an event hook.
- Paste the address as the URL, set the authentication field to
Authorizationwith a throwaway secret, and subscribe to an event such as User created. - Save and press Verify. The verification
GETappears in the inbox above and the hook becomes active. - Use the hook's preview to deliver a sample, or create a test user, and read the event in the inbox.
Event payloads contain logins, names and IP addresses. Point a hook at a public inbox only from an org that holds test identities, and deactivate the hook afterwards.
To run a caught request against your own code, select it and press Open in API Tester: the method, headers and body are loaded into the request console, where you enter your server's public URL and send it. A body you edit will no longer match its signature — that is the signature doing its job.
Things that catch people out
- An event hook cannot block anything. If you need to stop or modify a registration or sign-in, that is an inline hook, with a different payload and a response Okta reads.
- Events are batched.
data.eventscan hold several entries; loop over it. - The verification is a
GET, deliveries arePOST. A route that only accepts one of the two fails either at setup or afterwards.
api-tester.com is independent and is not affiliated with Okta. Providers change header names, limits and retry schedules; treat the official Okta documentation as the source of truth.
Related examples and tools
Stripe Webhook Example
What Stripe actually sends to your endpoint — the event envelope, the Stripe-Signature header and the retry behaviour — with a webhook URL you can create here to catch a real one.
GitHub Webhook Example
The headers and JSON GitHub posts when a repository event fires, how X-Hub-Signature-256 is computed, and what happens when your endpoint is down.
PayPal Webhook Example
The notification PayPal posts when a payment event happens — its envelope, the five PAYPAL- headers, and the certificate-based signature that works differently from everyone else's HMAC.
Shopify Webhook Example
What Shopify posts when a store event fires — the topic and shop headers, the resource JSON, and a base64 HMAC that trips up people expecting hex.
Zapier Webhook Example
Zapier works in both directions.
API Authentication
Shared secrets, signatures and tokens compared, and what each one actually proves.
Curl POST JSON
Send a JSON body like this one from a terminal.
Webhook Tester
The inbox on its own page, plus a guide to signatures, retries and idempotent handlers.
All Webhook Examples
30 providers side by side: content type, signature scheme and retry behaviour.
Other webhooks that send a plain secret token
References
- Official Okta documentation — The provider's own guide to the requests described on this page.
- Okta Developer: event hook implementation — A worked example service, including the one-time verification.
- Okta Developer: event types — The catalogue of events a hook can subscribe to.
- Node.js: crypto.timingSafeEqual() — The constant-time comparison used in the code on this page.
These links leave api-tester.com, which is independent of the companies and projects they point to.
Okta webhook FAQ
What does an Okta event hook payload look like?
A JSON envelope with eventType set to com.okta.event_hook, an eventId, eventTime, source and a data object. data.events is an array of System Log events, each with eventType, actor, target, outcome, published and a uuid.
How do I verify an Okta event hook endpoint?
Okta sends one GET request with an X-Okta-Verification-Challenge header. Respond with a JSON body containing a verification property set to the value of that header.
Are Okta event hooks signed?
No. Okta sends an authentication header whose name and secret value you configure on the hook, typically Authorization. Your endpoint compares that header with the expected secret over HTTPS.
Does Okta retry failed event hook deliveries?
Only minimally. According to Okta's documentation at the time of writing, a delivery times out after three seconds and is retried at most once, and 4xx responses are not retried.
What is the difference between an Okta event hook and an inline hook?
An event hook notifies your service after something has happened and ignores the response. An inline hook calls your service during a process such as registration or sign-in and uses your response to change the outcome.