Webhooks

Get notified the moment a machine stop is classified, reclassified or unclassified in Pulsar.

Instead of polling the API, you can have Pulsar call your application when something happens. A webhook is an HTTPS endpoint you host. Pulsar sends it a POST request with a JSON body every time an event you subscribed to occurs.

Webhooks currently cover machine stop classifications: Pulsar notifies you when a stop is classified, when a classification changes, and when one is deleted.

Set up a webhook

Build an endpoint

Add a route to your application that accepts a POST with a JSON body and answers with a 2XX status. It has to meet the endpoint requirements below.

Ask Pulsar to register it

Send your Pulsar contact:

  • Name: a label for the endpoint, such as ERP.
  • URL: the full HTTPS URL of your endpoint.
  • Event type: the event it should receive.

Each registration receives one event type. To receive several, register the same URL once per event type, and branch on eventType in your handler.

Store your signing secret

Pulsar gives you a signing secret. Every request Pulsar sends is signed with it, so you can verify it really came from Pulsar. Keep it out of source control, like any other credential. There is one secret per company, shared by all your endpoints.

Send a test ping

Ask Pulsar to ping your endpoint. You'll receive a Ping event, which confirms that your endpoint is reachable and your signature check passes, before real events start arriving.

Endpoint requirements

Pulsar only delivers to endpoints that are:

  • Public HTTPS. The URL must use https://, be at most 255 characters, and contain no credentials (user:pass@) or #fragment. The hostname must resolve to public IP addresses. Private, loopback and link-local addresses are refused.
  • Fast. Each request has a 10-second limit, including DNS lookup and connection setup.
  • Final. Redirects are not followed. A 3XX response counts as a failed delivery, so register the final URL.

The request

Every notification is a POST with a JSON body and these headers:

POST /webhooks/pulsar HTTP/1.1
Host: example.com
Content-Type: application/json
X-Pulsar-Signature: 5c0e2f4a1b9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f
X-Pulsar-Event-Type: MachineStopClassificationCreated
X-Pulsar-Event-Id: 8d2f6c1e-4b7a-4f0e-9a3c-5e1d7b9f2a64
X-Pulsar-Timestamp: 2026-09-25T14:03:12.482Z
X-Pulsar-Request-Id: 3f9b2c7d-1e4a-4c8b-b6d2-9a0e5f7c1b38

{
  "eventId": "8d2f6c1e-4b7a-4f0e-9a3c-5e1d7b9f2a64",
  "eventTimestamp": "2026-09-25T14:03:12.482Z",
  "eventType": "MachineStopClassificationCreated",
  "event": { ... }
}

Headers

HeaderDescription
Content-TypeAlways application/json.
X-Pulsar-SignatureHMAC-SHA256 signature of the raw body. Verify it before trusting the request.
X-Pulsar-Event-TypeThe event type, same as eventType in the body.
X-Pulsar-Event-IdThe event's ID, same as eventId in the body.
X-Pulsar-TimestampSame as eventTimestamp in the body.
X-Pulsar-Request-IdThe ID of this delivery attempt. Include it when you contact Pulsar support about a delivery.

Header names are case-insensitive, so your framework may show them lowercased.

Body

Every notification has the same envelope:

FieldTypeDescription
eventIdstringUnique ID of the event. It stays the same across retries, so use it to detect duplicates.
eventTimestampstringWhen Pulsar queued the event, as an ISO 8601 UTC timestamp. This is not the time the change happened in Pulsar.
eventTypestringThe event type, for example MachineStopClassificationCreated.
eventobjectThe event's data. Its shape depends on eventType; see Events.

Respond with a 2XX, quickly

Return a 2XX status as soon as you've verified the signature. Pulsar reads only the status code and ignores the response body.

  • Return 200 if you've already handled the event.
  • Return 202 if you've queued it for later.

Do anything slow, like calling other systems or heavy database work, in a background job after responding. A response that takes longer than 10 seconds counts as a failure and is retried, even if your code eventually finishes.

Retries

What Pulsar does with a failed delivery depends on why it failed:

Your endpoint...Pulsar...
Returns 2XXMarks the delivery as done.
Times out, can't be reached, or returns 408, 429 or 5XXMakes up to 3 attempts in quick succession, with exponential backoff, honoring a short Retry-After header. If all 3 fail, it tries the delivery again later.
Returns any other 4XX, or a 3XX redirectDoes not retry. The delivery is recorded as failed, and Pulsar can replay it once your endpoint is fixed.

A 4XX response stops retries

Pulsar treats 400, 401, 403, 404 and most other 4XX codes as your endpoint deliberately rejecting the event, so it doesn't retry them. If a bug in your handler returns a 4XX for valid events, those events wait until Pulsar replays them. Use 5XX for temporary problems on your side.

A failing endpoint doesn't hold up deliveries to your other endpoints.

Duplicates and ordering

Delivery is at least once. Occasionally the same event reaches your endpoint more than once, for example when your endpoint processed a request but Pulsar didn't record the response in time. A retried event also arrives later than events that went through on the first try, so order isn't guaranteed.

Make your handler safe to run twice: store each eventId you've processed, and skip one you've already seen. A retry or a replay always carries the original eventId.

Ping events

A ping tests your endpoint without waiting for a real event. It uses the same headers and signature as any other notification, has eventType set to Ping, and its event is always { "text": "ping" }:

{
  "eventId": "0b6f3d2a-9c1e-4a7b-8f5d-2e4c6a8b0d1f",
  "eventTimestamp": "2026-09-25T14:00:00.000Z",
  "eventType": "Ping",
  "event": {
    "text": "ping"
  }
}

A ping can reach an endpoint whatever event type it's registered for, so reply 2XX to Ping rather than rejecting event types you didn't expect.

Next steps

On this page