Monitors
Follow specific jobs and get a job.closed webhook when one closes. A monitor lists the jobs, names one of your webhook endpoints, and runs for 1 to 365 days (default 90). Free.
A monitor is a list of records you want to follow, delivered to one of your
webhook endpoints, until it expires. Today a monitor follows jobs
and sends job.closed when one of them closes; other record types and events will be added
under the same API.
Monitors are available on paid plans and cost no credits: creating one, adding records, and every event it sends. Instead of re-fetching the jobs you hold to find out which have closed, you are told.
| Limit | Builder, Growth | Scale, Business |
|---|---|---|
| Records monitored, all monitors | 100,000 | 1,000,000 |
| Records in one monitor | 100,000 | 100,000 |
| Ids per request | 1,000 | 1,000 |
| Lifetime | 1 to 365 days, default 90, renewable | same |
All endpoints accept an API key (Authorization: Bearer jp_live_... or x-api-key) or an OAuth
access token.
Create a monitor
POST https://api.jobspipe.dev/v1/monitorscurl https://api.jobspipe.dev/v1/monitors \
-H "Authorization: Bearer $JOBSPIPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "job",
"ids": ["4464825573", "8739185002", "no-such-job"],
"webhook_id": "0f8b6c1e-3a52-4d7e-9c41-2b8f7a6d5e30",
"expires_in_days": 30
}'| Field | Required | Description |
|---|---|---|
type | yes | What the ids are. job today. |
ids | yes | 1 to 1,000 ids, as search returned them. |
webhook_id | yes | One of your webhook endpoints (GET /api/webhooks). |
events | no | Events to send. Default: every event of the type, which for jobs is job.closed. |
expires_in_days | no | How long the monitor runs, a whole number from 1 to 365. Default 90. |
Every id is looked up, so the response also tells you, for free, which jobs are already closed and which ids match nothing. Neither is added: only open jobs are monitored.
{
"id": "7f3c1a52-8a3e-4c1e-9f0a-2d6b4e1c9a77",
"type": "job",
"events": ["job.closed"],
"webhook_id": "0f8b6c1e-3a52-4d7e-9c41-2b8f7a6d5e30",
"status": "active",
"expires_at": "2026-10-24T10:00:00.000Z",
"created_at": "2026-09-24T10:00:00.000Z",
"target_count": 1,
"open_target_count": 1,
"already_closed": [
{ "id": "8739185002", "closed_at": "2026-09-20T00:00:00Z", "closed_reason": "gone" }
],
"not_found": ["no-such-job"]
}| Field | Description |
|---|---|
status | active until expires_at, then expired. An expired monitor sends nothing until renewed. |
target_count | Records in the monitor. |
open_target_count | Records whose close has not been sent yet. |
Add and remove records
POST https://api.jobspipe.dev/v1/monitors/{id}/ids {"ids": [...]}
DELETE https://api.jobspipe.dev/v1/monitors/{id}/ids {"ids": [...]}
GET https://api.jobspipe.dev/v1/monitors/{id}/ids?limit=100&cursor=...Adding answers {"added", "target_count", "already_closed", "not_found"}; ids already in the
monitor are ignored. Removing answers {"removed"}. The list shows each record with status
open or closed: a record whose job.closed was sent stays listed as closed and sends nothing
more.
Renew, list, get and delete
POST https://api.jobspipe.dev/v1/monitors/{id}/renew {"expires_in_days": 90}
GET https://api.jobspipe.dev/v1/monitors?limit=100&cursor=...
GET https://api.jobspipe.dev/v1/monitors/{id}
DELETE https://api.jobspipe.dev/v1/monitors/{id}Renewing sets expires_at to expires_in_days (default 90) from now, and works on an expired
monitor too. The list is newest first; pass next_cursor back as cursor until it is null.
Deleting a webhook endpoint deletes the monitors that deliver to it.
What you receive
When a record in an active monitor closes, the monitor's endpoint receives a signed
job.closed event whose monitor_ids names the monitors
that include the job. An endpoint that reaches the same job through two monitors receives it once.
Only verified closes are sent (gone, closed), and the endpoint must list job.closed in its
enabledEvents.
Errors
| Status | When |
|---|---|
400 | Unknown type or event, ids empty or over 1,000, expires_in_days not a whole number from 1 to 365, or a monitor would pass 100,000 records. |
401 | No valid credential. |
402 | Free plan, or the request would pass the plan's monitored-records limit. |
404 | The monitor or webhook does not exist on your account. |