Skip to content

Webhooks — events & delivery

Webhooks are the recommended way to keep your system in sync with Atlast. Instead of polling, Atlast pushes a small notification to your server the moment a job changes, and you re-fetch that job from the API for its full detail. You configure one webhook endpoint per organisation in the Atlast Portal (Settings → Integrations → Webhook).

EventFires when…
job.publishedA job becomes publicly visible.
job.updatedA published job’s content changes.
job.unpublishedA published job is taken down (but not deleted).
job.deletedA job is permanently removed.

Webhook payloads carry identifiers, not full job content. They tell you what changed and where to fetch the current state — they are not a snapshot of the job:

{
"id": "evt_9f8e7d6c5b4a3210",
"event": "job.updated",
"occurredAt": "2026-06-09T12:34:56.000Z",
"data": {
"jobId": "job-550e8400-e29b-41d4-a716-446655440000",
"publicId": "abc123def456",
"jobUrl": "https://acme.careers.atlasthq.com/jobs/abc123def456",
"applyUrl": "https://acme.careers.atlasthq.com/jobs/abc123def456/apply",
"apiUrl": "https://api.atlasthq.com/api/public/v1/jobs/abc123def456"
}
}
FieldDescription
idUnique event ID. Use this to de-duplicate (see below).
eventOne of the four event types above.
occurredAtISO-8601 timestamp of when the change happened.
data.jobIdInternal job ID.
data.publicIdPublic identifier — use it with the Jobs API.
data.jobUrl / data.applyUrlPublic careers URLs (may be null).
data.apiUrlThe exact Jobs API URL to fetch this job’s full detail.

Because the payload is thin, the correct way to handle most events is:

  1. Receive the webhook and verify its signature.
  2. GET the data.apiUrl (or …/jobs/{publicId}) to load the full, current job detail.
  3. Upsert that into your system.
The webhook and re-fetch loop Atlast sends a thin webhook when a job changes. Your integration verifies it, then calls GET /jobs/{publicId} on the Atlast Jobs API to load the full, current job, and upserts it into your data store. Atlast events + Jobs API Your integration verify · enqueue Your data store Webhook — job changed (thin payload) GET /jobs/{publicId} Full, current job JSON Upsert

This keeps your data correct even if events arrive out of order or are redelivered — you always reconcile against the live API, which is the source of truth.

For job.deleted and job.unpublished, you don’t need to re-fetch — the job is gone or no longer public (GET …/jobs/{publicId} returns 404). Remove or hide it on your side.

Every delivery includes these headers:

HeaderPurpose
X-Atlast-SignatureHMAC-SHA256 of the raw body — verify this.
X-Atlast-TimestampISO-8601 time the event occurred.
X-Atlast-EventThe event type (e.g. job.updated).
X-Atlast-Delivery-IdEquals the payload id — the de-duplication key.
  • At-least-once. A delivery may arrive more than once. De-duplicate on the event id (X-Atlast-Delivery-Id): record IDs you’ve processed and skip repeats.
  • Retries. If your endpoint doesn’t return a 2xx, Atlast retries with backoff. Return 2xx only after you’ve safely accepted the event (queued or stored it).
  • Ordering is not guaranteed. Events can arrive out of order. The re-fetch pattern makes this a non-issue — reconcile against the live API rather than trusting event order.
  • HTTPS only. Webhook endpoints must be public HTTPS URLs.
HTTP/1.1 200 OK

Respond 2xx quickly (within a few seconds). Do slow work (re-fetching, database writes) asynchronously — accept the event, enqueue it, return 200, then process. A slow handler looks like a failure and triggers retries.