Outbound webhooks are a Pro feature. They send one signed POST request for each newly matched job.
Use webhooks when you want matched jobs to flow into tools like Slack, Notion, Airtable, Zapier, Make, or your own workflow.
Email notification settings do not control webhook delivery. Use the webhook Active switch to pause or resume webhooks.
What triggers a webhook
JobBeacon sends a job.matched webhook when all of these are true:
- You are on Pro.
- You have saved an active webhook endpoint.
- JobBeacon finds a new job after the company’s first scan.
- The job matches that company’s keyword and location filters.
The first scan seeds existing jobs. Seed jobs do not send webhook delivery.
If a job does not match your filters when JobBeacon first sees it, changing filters later does not send a backfill webhook for that old job.
Set up a webhook
Open Settings
Click your avatar, then click Settings.
Find Outbound Webhook
In Outbound Webhook, enter your Endpoint URL.
Choose the payload version
Keep the current Payload version unless an existing integration needs an older payload shape.
Add authentication if needed
If your endpoint requires API key authentication, enter a Provider auth header name such as x-jobbeacon-apikey.
Save the endpoint
Click Save. The endpoint must use HTTPS.
Copy the signing secret
Copy the Signing secret when it appears. JobBeacon only shows the full secret once.
Send a test
Click Send test to queue a webhook.test delivery.
Your account can have one webhook endpoint.
Endpoint requirements
Your endpoint must:
- Use
https://
- Be reachable from the public internet
- Return a
2xx response when delivery succeeds
- Not use credentials in the URL
JobBeacon blocks localhost, private network addresses, and test-only hostnames.
Use the Provider auth header field if your endpoint requires an API key in a custom header.
Each delivery includes these headers:
| Header | Value |
|---|
Content-Type | application/json |
User-Agent | JobBeacon-Webhooks/1.0 |
JobBeacon-Event-Id | The event ID, such as evt_... |
JobBeacon-Timestamp | Unix timestamp in seconds |
JobBeacon-Signature | HMAC signature, such as v1=... |
JobBeacon-Webhook-Version | The selected payload version, such as 2026-06-15 |
Idempotency-Key | Stable dedupe key for the event |
Use JobBeacon-Event-Id or Idempotency-Key to ignore duplicate deliveries.
If you set a Provider auth header, JobBeacon sends the signing secret as the value of that header.
For example, a provider auth header named x-jobbeacon-apikey sends:
x-jobbeacon-apikey: whsec_...
JobBeacon only sends the provider auth header to the original endpoint origin. If your endpoint redirects to a different origin, the redirected request does not include that header.
Verify the signature
JobBeacon signs the raw JSON body with your signing secret.
The signed input is:
The signature is an HMAC SHA-256 hex digest with a v1= prefix.
Example in Node.js:
import crypto from "node:crypto";
export function verifyJobBeaconWebhook({
rawBody,
timestamp,
signature,
secret,
}) {
const expected =
"v1=" +
crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const signatureBuffer = Buffer.from(signature);
const expectedBuffer = Buffer.from(expected);
return (
signatureBuffer.length === expectedBuffer.length &&
crypto.timingSafeEqual(signatureBuffer, expectedBuffer)
);
}
Reject requests with an old JobBeacon-Timestamp. A 5-minute window is a common choice.
Payload versions
Your webhook endpoint is pinned to one payload version. New deliveries and test deliveries use that version until you change Payload version in Settings.
| Version | Status | Notes |
|---|
2026-06-15 | Current | Default for new webhook endpoints. |
2026-06-12 | Legacy | Available for existing integrations that already use this version. |
Both supported versions currently use the same fields. The selected version appears in the api_version payload field and the JobBeacon-Webhook-Version request header.
job.matched payload
{
"event": "job.matched",
"event_id": "evt_abc123",
"api_version": "2026-06-15",
"created_at": "2026-06-13T09:15:00.000Z",
"dedupe_key": "job.matched:user_123:job_123",
"job": {
"id": "job_123",
"external_id": "456789",
"title": "Senior Backend Engineer",
"location": "Remote",
"url": "https://company.example/careers/job/456789",
"first_seen_at": "2026-06-13T09:14:30.000Z",
"last_seen_at": "2026-06-13T09:14:30.000Z",
"is_active": true
},
"company": {
"id": "company_123",
"name": "Acme",
"slug": "acme"
},
"share": {
"token": "share_token",
"url": "https://jobbeacon.app/share/share_token",
"image_url": "https://jobbeacon.app/share/share_token/opengraph-image",
"twitter_image_url": "https://jobbeacon.app/share/share_token/twitter-image",
"sharer_name": "alex"
}
}
job.matched fields
| Field | Type | Description |
|---|
event | string | Always job.matched. |
event_id | string | Unique ID for this webhook delivery. It also appears in the JobBeacon-Event-Id header. |
api_version | string | The selected payload version. It matches the JobBeacon-Webhook-Version header. |
created_at | string | Time JobBeacon created the payload, in ISO 8601 format. |
dedupe_key | string | Stable key for this matched job event. It also appears in the Idempotency-Key header. |
job | object | The matched job. |
company | object | The company that posted the job. |
share | object | Public JobBeacon share links and images for the job. |
job object
| Field | Type | Description |
|---|
id | string | JobBeacon’s ID for the job. |
external_id | string | The job ID from the company’s careers system. |
title | string | Job title. |
location | string or null | Job location, if JobBeacon received one. |
url | string | Public URL for the job posting. |
first_seen_at | string or null | Time JobBeacon first saw the job, in ISO 8601 format. |
last_seen_at | string or null | Time JobBeacon last saw the job active, in ISO 8601 format. |
is_active | boolean | Whether JobBeacon currently sees the job as active. |
company object
| Field | Type | Description |
|---|
id | string | JobBeacon’s ID for the company on your watchlist. |
name | string | Company name. |
slug | string | JobBeacon’s company slug. |
share object
| Field | Type | Description |
|---|
token | string | Token for the public JobBeacon share page. |
url | string | Public JobBeacon preview page for the job. |
image_url | string | Stable Open Graph image URL for the share page. |
twitter_image_url | string | Stable Twitter image URL for the share page. |
sharer_name | string | Display name shown on the share page. |
The image URLs are useful for tools that let you attach or preview images.
Test payload
Click Send test to queue a webhook.test event.
The test payload uses the same selected payload version as matched job deliveries.
{
"event": "webhook.test",
"event_id": "evt_abc123",
"api_version": "2026-06-15",
"created_at": "2026-06-13T09:15:00.000Z",
"dedupe_key": "webhook.test:user_123:delivery_123",
"test": true,
"job": {
"id": "job_test",
"external_id": "jobbeacon-test",
"title": "JobBeacon is hiring a Product Engineer",
"location": "Remote",
"url": "https://jobbeacon.app/careers/jobbeacon-test",
"first_seen_at": "2026-06-13T09:15:00.000Z",
"last_seen_at": "2026-06-13T09:15:00.000Z",
"is_active": true
},
"company": {
"id": "company_test",
"name": "JobBeacon",
"slug": "jobbeacon"
},
"share": {
"token": "jobbeacon-test",
"url": "https://jobbeacon.app/share/jobbeacon-test",
"image_url": "https://jobbeacon.app/share/jobbeacon-test/opengraph-image",
"twitter_image_url": "https://jobbeacon.app/share/jobbeacon-test/twitter-image",
"sharer_name": "JobBeacon"
}
}
webhook.test fields
The webhook.test payload includes the same fields as job.matched, plus:
| Field | Type | Description |
|---|
event | string | Always webhook.test. |
test | boolean | Always true for test deliveries. |
The job, company, and share objects contain test data. Use them to verify your endpoint, signature check, and field mapping before relying on live matched job deliveries.
You can send one test per minute, up to 25 tests in 24 hours.
Delivery behavior
JobBeacon waits up to 10 seconds for your endpoint.
A delivery is marked delivered when your endpoint returns any 2xx status.
JobBeacon retries temporary failures, including network errors, 408, 409, 425, 429, and 5xx responses.
Retries use backoff and stop after 5 attempts. Other failures are marked failed.
JobBeacon follows up to 3 redirects, as long as the final URL still passes endpoint validation.
Delivery history
The Recent deliveries table in Settings shows the latest webhook deliveries.
Delivery history is kept for 30 days.
Common statuses:
| Status | Meaning |
|---|
queued | Waiting to be sent |
sending | Delivery is in progress |
delivered | Your endpoint returned 2xx |
failed | Delivery will not be retried |
skipped | Delivery was skipped, usually because Pro or the webhook was disabled |
Rotate or pause webhooks
Click Rotate secret if your signing secret may have been exposed.
After rotating, update your endpoint to use the new secret.
Use the Active switch to pause delivery without deleting your endpoint.
If your account moves from Pro to Free, webhook delivery pauses. Your endpoint and signing secret stay saved in case you reactivate Pro later.
Troubleshooting
If a webhook does not arrive:
- Check that your account is on Pro.
- Check that the webhook is Active.
- Check that the endpoint uses HTTPS and is publicly reachable.
- Click Send test.
- Review Recent deliveries for response status and error details.
- Confirm the job was new and matched your filters when JobBeacon first saw it.