More Jobs on Every Plan, and Closures Are Free
More Jobs on Every Plan, and Closures Are Free
Every Jobven plan is now a number of jobs a month, and every tier holds as many jobs as before or more at the same price. Your allowance is spent only on job records that actually reach you: an empty check for new listings, a company lookup, a failed request, and every closure or removal cost nothing.
What counts as a job
Every job in a search response counts one. A single job lookup counts one. A new or updated job delivered to a webhook endpoint counts one.
Everything else is free: a search that returns nothing, a company lookup, a request that fails, a test event, and every job.closed and job.deleted delivery. Page size no longer changes what you pay, so ask for the largest page your plan allows and make fewer requests.
The authentication page has the per-plan table.
Push and pull cost the same
A job counts once however it reaches you. Fetch a page of 100 and it counts 100; have those same 100 pushed to you as they are posted and it counts 100. So the choice between polling and webhooks is about latency and how much code you want to run, and no longer about what you pay.
What webhooks add on top, which roles closed and which were removed, is the free part. That is the information that keeps a job board honest, and it costs nothing to receive.
What happens at your limit
API requests return 429 until your period resets, as before. Webhooks change: new and updated jobs are dropped, but closures and deletions keep arriving, so the jobs you already hold do not go stale while you are over. Dropped events are not re-sent, and the rate limits guide explains how to read the headers so you see it coming. X-RateLimit-Remaining is in jobs and already accounts for the response it arrives with.
Plan volumes
Starter stays at 10,000 jobs a month and Free at 300. Growth is now 50,000, Professional 150,000, and Custom starts at 1,000,000. No price changed. The 7-day trial is 2,500 jobs.
The usage shown on your billing page carried over as jobs.
One payload changed
job.closed now carries only what you need to act on it:
{
"type": "job.closed",
"data": {
"job": {
"id": "01HZX7K4VWJ8MMGS31F7DCYJ8Z",
"applyUrl": "https://example.com/jobs/123",
"closedAt": 1758448800
}
}
}
That is the same shape as job.deleted, and it is what makes closures free to deliver. You already hold the record, so a closure only has to tell you which one. If your handler read other fields off a closure, key on the id and fetch the job when you need the rest:
if (event === 'job.closed') {
await db.jobs.update({ where: { id: data.job.id }, data: { status: 'closed' } })
}
A closure for a job you do not have can be ignored. The event reference has every field.
Where to start
If you poll, nothing changes except that a page costs what it contains, so use postedAfter freely: an empty poll is free. If you receive webhooks, check your job.closed handler against the new shape and add job.updated to your subscription if you want refreshed records pushed rather than re-fetched. The changelog entry lists the exact renames.
Jobs are what you came for, and they are now the only thing you pay for.