List job changes

GET
/api/v1/changes

Poll the append-only feed of job change events for incremental sync. Pages forward by a monotonic integer cursor; omit the cursor to replay the full history from the beginning (initial sync). Always pass the returned next_cursor back on the next poll. When has_more is true, keep paging immediately; when false, poll again on your own interval. Set include=job to embed the current job record (descriptions omitted) with each change. Use since (an ISO-8601 timestamp with offset) as a convenience alternative to cursor for starting the feed at a point in time; it is mutually exclusive with a non-zero cursor. Snapshot filters (level, workplace, employment_type, country, company_id, has_salary) use before-OR-after matching: an event is delivered if the job matched the filter before the change or after it — so you also see jobs leaving your scope (e.g. filtering level=senior still delivers the event where a job moves out of the senior level). Different filter dimensions are ANDed together. The changed_fields attribution filter delivers only events that changed at least one of the named content fields; created events carry no field-level attribution and are always delivered.

Authorization

bearerAuth
AuthorizationBearer <token>

Provide your secret API key (prefixed sk_) as a bearer token: Authorization: Bearer sk_....

In: header

Query Parameters

cursor?string

Resume the feed after this change id. Omit to replay the full history from the beginning. Always pass back the next_cursor from the previous response. Mutually exclusive with since (a non-zero cursor alongside since is rejected).

Match^\d+$
Default"0"
types?array<>

Filter to specific change kinds. Repeat the parameter or comma-separate values (e.g. types=created,closed). A change matches if it is any of the given kinds.

Itemsitems <= 4
level?array<>

Filter by seniority level. Repeat the parameter or comma-separate values. Matches before-OR-after: an event is delivered if the job was at any of these levels before the change or is at one after it (jobs leaving your scope are still delivered).

Itemsitems <= 7
workplace?array<>

Filter by workplace arrangement. Repeat the parameter or comma-separate values. Matches before-OR-after: delivered if the job matched any of these before the change or matches one after it.

Itemsitems <= 3
employment_type?array<>

Filter by employment type. Repeat the parameter or comma-separate values. Matches before-OR-after: delivered if the job matched any of these before the change or matches one after it.

Itemsitems <= 5
country?array<>

Filter by ISO 3166-1 alpha-2 country code(s). Repeat the parameter or comma-separate values (e.g. country=us,de). Up to 20 values; case-insensitive. Matches before-OR-after: delivered if the job was tagged with any of these countries before the change or matches its current location.

Itemsitems <= 20
company_id?integer

Filter to changes for jobs belonging to this numeric company id.

has_salary?boolean

When true, deliver events where the job had a salary before the change OR has one after it; when false, the inverse. Matches before-OR-after state.

changed_fields?array<>

Attribution filter: deliver only events that changed at least one of these content fields. Repeat the parameter or comma-separate values (e.g. changed_fields=salary_min,salary_max). created events are always delivered (they have no field-level attribution).

Itemsitems <= 27
since?string

Start the feed at this ISO-8601 timestamp, including a UTC offset (e.g. 2024-01-01T00:00:00+00:00). A convenience alternative to cursor for starting from a point in time; resolved to a cursor server-side. Mutually exclusive with a non-zero cursor.

Formatdate-time
limit?integer

Maximum number of changes to return. Defaults to 100; values above 500 are clamped to 500.

Range0 < value
Default100
include?"job"

When set to job, attach the current job record (descriptions omitted) to each change.

Value in

  • "job"

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/api/v1/changes"
{  "data": [    {      "id": 0,      "job_id": 0,      "change_type": "created",      "changed_at": "string",      "changed_fields": [        "string"      ],      "job": {        "id": 0,        "source_id": 0,        "company_id": 0,        "external_job_id": "string",        "url": "string",        "apply_url": "string",        "title": "string",        "location_raw": "string",        "locations_raw": "string",        "location": "string",        "city": "string",        "region": "string",        "postal_code": "string",        "country_code": "string",        "latitude": 0,        "longitude": 0,        "usa": true,        "country_codes": [          "string"        ],        "admin1_refs": [          "string"        ],        "workplace": "remote",        "employment_type": "full_time",        "level": "intern",        "language": "string",        "salary_raw": "string",        "salary_min": 0,        "salary_max": 0,        "salary_currency": "string",        "salary_period": "year",        "posted_at": "string",        "expires_at": "string",        "content_hash": "string",        "first_seen_at": "string",        "closed_at": "string",        "created_at": "string",        "updated_at": "string",        "description_md": "string",        "description_html": "string",        "company": {          "id": 0,          "name": "string",          "website_url": "string",          "logo_url": "string"        }      }    }  ],  "next_cursor": "string",  "has_more": true,  "limit": 0}
{  "type": "string",  "title": "string",  "status": 0,  "detail": "string",  "errors": [    {      "field": "string",      "message": "string"    }  ]}
{  "type": "string",  "title": "string",  "status": 0,  "detail": "string",  "errors": [    {      "field": "string",      "message": "string"    }  ]}
{  "type": "string",  "title": "string",  "status": 0,  "detail": "string",  "errors": [    {      "field": "string",      "message": "string"    }  ]}