---
title: "The change feed since your cursor"
method: GET
path: "/v1/events"
---

# The change feed since your cursor

`GET /v1/events`

## Request

- Base URL: `https://api.reqbeat.com`
- URL: `https://api.reqbeat.com/v1/events`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

The `since=cursor` diff feed -- ledger events with `event_seq > since`,
ordered ascending, plus a `next_cursor` an agent replays instead of
polling or re-scraping. Meters one `change` unit per event RETURNED,
independent of poll count: an empty page costs nothing. A free-tier
caller is change-feed-gated to the same freshness floor every other
free atom uses. `limit` is bounded: an oversized page is rejected with
422 rather than truncated -- replay with `next_cursor` instead of
raising `limit`.

Requires the `read` scope.

## Query parameters

- `since` integer, required: Cursor: return only events with `event_seq` greater than this. Start at 0, then replay the previous response's `next_cursor` instead of re-polling from the beginning.
- `company_id` integer, nullable: Return only events for this company id.
- `event_type` string, nullable: Return only events of this type, e.g. 'opened' or 'closed'.
- `limit` integer: Maximum events per page. An oversized value is rejected with 422 rather than truncated — replay with `next_cursor` instead.

## Headers

- `Idempotency-Key` string, nullable

## Response `200`

Successful Response

- ChangeFeedResponse
  - `events` ChangeEventOut[], required
    - `event_seq` integer, required
    - `company_id` integer, required
    - `req_key` string, required
    - `board` string, required
    - `event_type` string, required
    - `observed_at` string, date-time, required
    - `function` string, nullable, required
    - `country` string, nullable, required
    - `title` string, nullable, required
    - `source_board` string, nullable, required: The board whose posting this event was read off -- normally the same value as `board`. Null when the event carries no per-posting board label; `board` is always set.
    - `country_code` string, nullable, required: The posting country's ISO-3166-1 alpha-2 code, uppercase (`DE`, `US`), derived from `country` and never stored. `null` when `country` is absent or is not a country this corpus names — never a guess. Note this is an output only: the `geo`/`country` filter still takes the name, because a bare two-letter code is ambiguous on input (`CA` is Canada to ISO and California to this column).
    - `function_name` string, nullable, required: The job function's human-readable name (`Software & IT`, `Healthcare`), derived from `function` and never stored. The `?function=` filter accepts this name as well as the opaque taxonomy id in `function`. `null` when the req carries no function attribution (`unspecified`, 10.2% of served reqs), or when it was classified from its skills alone, so its id is outside the named title-family vocabulary (16.7%) — never a guess and never the raw id. Named on 73.1% of served reqs (309,251 of 422,826, measured 2026-10-07).
  - `next_cursor` integer, required

## Other responses

- `401`: No API key was sent.
- `402`: The key is over its plan's rolling call quota, or the account is past its spend cap. `upgrade_url` and `purchase_url` are the ways out.
- `403`: The presented key is invalid or revoked, or (see `x-required-scope` on this operation) it does not carry the scope this operation requires.
- `422`: Validation Error
- `429`: Too many calls in the current 60-second window. The limit is per API key, set by the key's plan, and shared by every metered REST route and MCP tool; the shared demo key is limited per IP address instead. Wait `Retry-After` seconds and retry. The `RateLimit-*` headers are absent when `reason` is `key_throttled`.

---

[API](https://skmtc.dev/reqbeat/apis/reqbeat-api.md) · [All operations](https://skmtc.dev/reqbeat/apis/reqbeat-api/llms.txt) · [OpenAPI document](https://skmtc.dev/reqbeat/apis/reqbeat-api/revisions/4758e5957e8c?raw)
