Webhooks: Stream Jobven Jobs Into Your Stack
If you're a Jobven customer today, you're probably running a cron that hits GET /v1/public/jobs?postedAfter={lastSync} every few minutes. It works, and for batch refresh it's fine, but it has two failure modes you keep paying for:
- Latency-vs-load tradeoff. Poll every minute, you waste budget. Poll every hour, you miss a third of the day's listings.
- Empty-poll tax. Most of those requests come back unchanged. You're paying quota for "no, still nothing new since 14:32."
Webhooks are now live. Subscribe to job.created, job.updated, job.closed, and job.deleted, and we POST the event to your HTTPS endpoint when it happens. No more empty polls, no more "did we miss any during the maintenance window?" anxiety.
Available on Starter, Growth, Professional, and Custom plans. The full reference is at Webhooks documentation. This post covers the why and the watch-outs.
How it works in 60 seconds
You create a subscription in the dashboard with a URL, a list of event types, and an optional filter (any subset of the Pull API filter shape: country, employment type, salary range, and so on). We hand you a signing secret exactly once. When a matching event fires, we POST a JSON envelope to your endpoint with Jobven-Signature and Jobven-Event-Id headers.
{
"id": "8e3f5c44-1cd1-4a40-bb4f-9d4f95c54c1d",
"type": "job.created",
"createdAt": 1715520000,
"subscriptionId": "7c2f8f7a-d8ab-4d4a-9a09-71b4e6dffb8a",
"deliveryAttempt": 1,
"data": {
"job": { "id": "...", "title": "Senior Backend Engineer", "company": { "...": "..." } }
}
}
Verify the signature with the secret, dedupe on Jobven-Event-Id, and you're done. Here's the TypeScript verifier (the docs carry Python and Go too):
import crypto from 'node:crypto'
export function verifyJobvenWebhook(rawBody: string, header: string, secret: string) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
const t = Number(parts.t)
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false
const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex')
const a = Buffer.from(expected, 'hex')
const b = Buffer.from(parts.v1, 'hex')
return a.length === b.length && crypto.timingSafeEqual(a, b)
}
Replay window is 5 minutes (t drift over 300s rejects). Always HMAC the raw bytes. JSON re-serialization changes whitespace and breaks the comparison.
What you can build
Webhooks are the bridge between Jobven's job data and your specific workflow. A few shapes we've seen in beta:
- Job alerts in Slack or email.
job.createdfires the alert, your filter narrows to the roles your users care about. No polling, no missed mornings. - Inventory sync for job boards.
job.createdinserts,job.updatedpatches,job.closedflips the listing inactive,job.deletedremoves it. Your store stays accurate to the minute without you owning the scraping. - ATS or recruiter CRM ingest. Match incoming roles against your client briefs in real time. Score and route before the listing has been live for an hour.
- Search index warming.
job.createdwrites to your ES/Typesense index immediately so the role is findable before the next batch refresh. - LLM enrichment pipelines.
job.updatedevents make it cheap to keep embeddings, summaries, or labels current as descriptions change.
The shared property is react vs poll. If your product cares about being fresh (alerts, marketplaces, agent inboxes), webhooks save you both latency and quota.
The verification gate
This is the part worth highlighting because it's deliberately non-standard.
When you create a subscription, it lands in a status called pending_verification. It is not in the dispatch pool. No events flow to your endpoint until you hit Send test from the dashboard and your endpoint returns a 2xx response. Then, and only then, the subscription flips to active and starts receiving real events.
We took this stance on purpose. Common webhook implementations all default new subscriptions to active immediately. That works for low-rate event sources. Jobven isn't one. A broad filter against our crawler can blast hundreds of job.created events through your endpoint within a minute of save. If you saved the subscription before deploying the handler, that's a flood at an endpoint returning 502s and burning quota on retries.
The gate applies on every reactivation. If you pause and re-enable a subscription, it returns to pending_verification first. If we auto-disable it after a sustained failure streak and you hit Re-enable, same thing, plus we hand you a Pull-API backfill curl scoped to the disable window. You can backfill the gap and resume live delivery from a verified, healthy endpoint.
The cost is one extra click. The benefit is that "I shipped the dashboard config before the endpoint was ready" never breaks anything.
At-least-once, with backoff
Webhook delivery is at-least-once. Persist Jobven-Event-Id for each event you've processed and skip duplicates. The header stays the same UUID across retries of the same event.
Failed deliveries (non-2xx, network timeout, or 429) retry on this schedule:
- Attempt 2 at 30 seconds
- Attempt 3 at 2 minutes
- Attempt 4 at 10 minutes
- Attempt 5 at 30 minutes
After the fifth failure we stop trying for that specific event. 4xx responses other than 429 (think 400, 404, 410, 422) are treated as permanent. Fix your endpoint, don't ignore them.
Past a sustained failure pattern (50 consecutive failures or 24 hours with no successful delivery), Jobven auto-disables the subscription. The dashboard surfaces a banner, you fix the endpoint, hit Re-enable, send a test, and you're back in business with a backfill recipe for the gap.
Quota and pricing
job.created or job.updated delivery counts one job; job.closed and job.deleted are free and keep flowing even when you are over your limit. The paragraphs below describe the original launch rule and are kept as written. See the changelog and Webhooks documentation for the current rule.Successful webhook deliveries count toward your plan's monthly API call allowance, same as a Pull API request. Test events do not count. Failed deliveries do not count. You're only billed for value delivered.
There's no per-subscription rental fee. You pay for events you actually received successfully, on the same per-call quota that backs the rest of the API.
What's next
Open the dashboard, create a subscription, send a test, and stop polling. The Webhooks reference has the full lifecycle table, verifier recipes in three languages, the event payload schemas, and the filter semantics.
If you have a use case we haven't covered above, or if you want a Zapier / n8n / Make.com bridge before we ship one, tell me. I'm the one who reads the inbox.
How to Build Automated Job Alerts with n8n - Jobven API Tutorial
Learn how to build an automated job alert system using n8n workflow automation and a job API. Get email notifications when new jobs match your criteria.
Why Job Descriptions Now Come as Plain Text and Markdown
Request job descriptions as plain text, markdown or HTML with one query parameter. Precomputed at ingest, so email, search and AI pipelines get what they need.