Job Change Data API: Query vs Webhook
By Kooperativa Engineering
A job change data API answers one question, has this person's employer or title changed, but there are two structurally different ways to get that answer, and picking the wrong one is the most common integration mistake in this category. One is a query you run against a time window. The other is a subscription that pushes a notification the moment the underlying record changes. They solve different problems and neither one is a drop-in replacement for the other.
The query model: recent movers in a window
The query form answers "who changed jobs in the last N days," either globally or filtered to people who previously worked at a specific company. This is the shape for a batch job: run it weekly, get back everyone who moved since the last run, feed the list into a CRM sync or a sales queue.
curl "https://kooperativa.io/api/v1/person/job-changes?days=30&company_id=1035" \
-H "Authorization: Bearer ik_live_..."`days` sets the look-back window, up to 365, and `company_id` is optional: omit it for every recent mover globally, include it to find people who specifically left one company, the shape you want for a competitor-alumni play. The response is paginated and returns a lightweight profile per result, not a full enrichment, so scanning a large window stays cheap.
The problem the query model cannot solve
A window query has an unavoidable blind spot: it tells you about everyone who moved, but only for the population that shows up in that specific query. If you care about forty named accounts and want to know within minutes of any one of them changing roles, running a global query on a schedule means polling forty needles in a haystack that gets rebuilt from scratch every time, and the interval between polls is exactly how stale your "immediate" alert actually is.
That is a subscription problem, not a query problem, and the fix is a mechanism that watches specific records rather than re-scanning everything.
The webhook model: watching specific people
A monitor subscribes to one person (or company) and delivers a signed webhook the moment a tracked field changes, rather than requiring anyone to poll for it. Setting one up is a single POST naming what to watch:
{
"type": "person",
"target_id": "f9413465-c1b9-4129-ab9f-2234caf971b1",
"events": ["person.job_changed"],
"webhook_url": "https://yourapp.com/webhooks/kooperativa"
}The delivered payload carries both the old and new value in a `diff`, which is what lets a receiving system decide relevance without a second lookup: a lateral move inside the same company is a different signal than a departure, and the diff is what makes that distinction available immediately rather than after a follow-up enrich call.
Picking between them
The deciding factor is not budget, it is the shape of the population you are watching.
- A short, named list, target accounts, a competitor's leadership team, a handful of past prospects: monitors. The cost of a webhook per person is trivial at that scale, and the latency advantage is the entire point.
- A broad population you refresh in bulk, an entire CRM's worth of contacts, a whole industry segment: the windowed query, run on a schedule. Setting up a monitor per contact at that scale is mostly overhead for signal you would also catch, slightly later, on the next scheduled query anyway.
- Both at once is common and not a contradiction: monitors on the accounts that justify same-day outreach, a weekly windowed query as the backstop that catches everyone else.
Get started
Try Kooperativa
One API key. Person and company enrichment, structured search, and monitors under one flat license.
