Okta Webhook: Example Payload, Headers and Signature

An Okta event hook delivers System Log events to your endpoint, authenticated by a header and secret you choose rather than by a signature. Here is a user-created event, the one-time verification request, and what Okta does when your endpoint is slow.

No webhook URL yet. Creating one needs no account.

Request details
Requests sent to your webhook URL appear here: method, headers and the body exactly as it arrived.

The button posts the example below to your webhook URL from your browser. It is not sent by Okta, it carries your browser's User-Agent, and its signature is a placeholder that will not verify. To see a real delivery, follow the steps further down.

Last updated . How this page is checked.

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

HeaderExampleWhat it is
Authorizationa-secret-you-chose-1234The authentication header and secret configured on the hook. The header name is your choice; this is the usual one.
Content-Typeapplication/jsonThe body is JSON.
X-Okta-Verification-ChallengeAhs8Jw0gEXAMPLE7hV3dQSent 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

  1. Press Create webhook URL at the top of this page and copy the address.
  2. In the Admin Console of a developer or preview org, open Workflow → Event Hooks and create an event hook.
  3. Paste the address as the URL, set the authentication field to Authorization with a throwaway secret, and subscribe to an event such as User created.
  4. Save and press Verify. The verification GET appears in the inbox above and the hook becomes active.
  5. 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.events can hold several entries; loop over it.
  • The verification is a GET, deliveries are POST. 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

Other webhooks that send a plain secret token

References

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.