Skip to main content

GET /v1/events

Returns events, together with any retractions in the same window.

curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.docsignal.app/v1/events?domains=linear.app,vercel.com&observed_since=2026-07-01"

Parameters​

ParameterTypeMeaning
domainscomma-separatedCompanies to include, by domain. Defaults to every company your token allows.
observed_sinceYYYY-MM-DDOnly events detected on or after this date.
observed_untilYYYY-MM-DDOnly events detected on or before this date.
shipped_sinceYYYY-MM-DDOnly events the vendor shipped on or after this date.
shipped_untilYYYY-MM-DDOnly events the vendor shipped on or before this date.
originobserved, backfilled, allWhether to include history reconstructed from archives. Defaults to all.
limit1–1000Page size. Defaults to 100.
offsetintegerRows to skip. Defaults to 0.

If you supply no date window at all, observed_since defaults to 30 days ago. Supplying any ship-date filter disables that default.

Response​

{
"events": [ "..." ],
"retractions": [ "..." ],
"has_more": true,
"query": {
"domains": ["linear.app"],
"observed_since": "2026-07-01",
"observed_until": null,
"shipped_since": null,
"shipped_until": null,
"origin": "all",
"limit": 100,
"offset": 0
}
}

The query block echoes the filter that was actually applied, including any defaults filled in for you.

Paging​

Page with limit and offset. Ordering is stable across requests and across rebuilds, so an offset means the same thing tomorrow. Continue while has_more is true.

The event shape​

Each event names one change and carries the evidence it was derived from.

{
"id": "evt_01KY4ESMC6P3X336MRW17MMTBR",
"domain": "vercel.com",
"organization_id": "ogn_01ARZ3NDEKTSV4RRFFQ69G5FAV",
"unit_id": null,
"product": "vercel",
"product_id": "ogn_01ARZ3NDEKTSV4RRFFQ69G5FAZ",
"scope_id": "ogn_01ARZ3NDEKTSV4RRFFQ69G5FAZ",
"type": "capability_expanded",
"area": "developer-experience",
"title": "Python function bundles now include precompiled bytecode",
"summary": "Vercel now precompiles Python function bundles to bytecode as part of the build, reducing per-invocation compilation overhead and cold-start latency for Python runtime functions. Corroborated by the @vercel/python@6.51.1 package release published the following day.",
"shipped_at": "2026-07-21",
"observed_at": "2026-07-22T08:19:31Z",
"origin": "observed",
"confidence": "high",
"evidence": {
"source_kind": "changelog",
"excerpt": "## Python function bundles now include precompiled bytecode"
},
"payload": {
"capability_slug": "function-runtimes",
"change": "Python function bundles now ship with precompiled bytecode, reducing cold-start compilation time."
}
}
FieldMeaning
idStable and unique. Safe to use for deduplication on your side.
domainThe company, matching what you passed in domains.
organization_idStable organization-graph ID. Additive; the domain remains present.
unit_idNearest business-unit ancestor for the event scope, or null.
productWhich of the company's products shipped it. See below — null is meaningful.
product_idStable product graph ID, or null when product is null. Additive; the product slug remains present.
scope_idExact graph node the event belongs to; may be an organization, business unit, brand, family or product.
typeWhat kind of change it is.
areaA functional area shared across companies, so the same concept is comparable between vendors.
titleOne line naming the change.
summaryWhat changed, and how we corroborated it.
originobserved for changes we detected live, backfilled for history reconstructed from archives.
confidencehigh, medium or low.
evidenceThe source kind and the excerpt the event came from, so a claim can be checked rather than trusted.
payloadFields specific to the event type.

What product means, and when it is null​

A company that ships one product stamps it on every event, so grouping by product never loses rows for those companies.

Where a company ships several, product names the one that shipped the change, and null means the change could not be attributed to a single product — either because it genuinely spans every or most of the products the company ships, or because the source never says which one it belongs to. Both are the same fact from a consumer's side: the vendor shipped something, and the product is not determinable. 1.5% of events carry it.

Treat null as its own bucket rather than as a row to drop — filtering it out discards real ships, and for a company shipping many products over shared infrastructure it discards a lot of them.

The graph IDs are stable across renames and reparenting. They are resolved from the one effective-dated organization graph as of the ship date where available, otherwise the observation date. scope_id is the most precise join; organization_id, unit_id and product_id are convenient projections of its ancestor path. Existing domain and product values retain their legacy behavior.

A capability that a vendor documents inside several products is recorded under each of them, not collapsed into one company-level row. That is deliberate: a change shipping for one product and not the others is a real event, and a collapsed row has nowhere to put it.

Event types​

The types currently in the store, most common first:

capability_expanded, feature_added, capability_added, other, new_integration, model_release, feature_removed, endpoint_added, limit_change, price_change, endpoint_deprecated, plan_added, capability_removed, new_product, feature_tier_change, integration_removed, plan_removed.

other is a real ship that fits no more specific type — a third-party model becoming available, a dated deprecation notice, an existing surface redesigned. It is one of the larger types, so a filter that omits it drops real changes.

Treat the set as open. Filter on the types you care about rather than assuming this list is exhaustive.

Payloads carry the change structurally​

A tier change records the movement, which makes questions like "what did competitors just un-gate" answerable directly:

{
"feature": "Devin Outposts",
"from_tiers": ["dedicated-tenant"],
"to_tiers": ["pro", "max", "teams", "dedicated-tenant"],
"direction": "opened_down"
}

A limit change records both sides, including a limit that was withdrawn rather than altered:

{
"limit": "copilot_5hr_tokens",
"old": "launch:50000, scale:2000000, max:4000000, enterprise:25000000",
"new": null,
"unit": "tokens/5h"
}

Ship date and observed date​

Every event carries both dates, and they answer different questions.

  • observed_at is when we detected the change. This is the filter for staying current.
  • shipped_at is when the vendor shipped it, where the source states a date. This is the filter for analysing a period.

The two diverge, sometimes by weeks. OpenAI's Codex Security plugin shipped on 4 June 2026 and appeared in the documentation on 28 July 2026. Combining the filters queries that gap directly:

curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.docsignal.app/v1/events?observed_since=2026-07-01&shipped_until=2026-06-30"

Not every event reports a ship date. We always know when we saw a change; the source does not always say when it shipped. Ship-date filters can only see the events that carry one, and /v1/companies reports dated_events per company so you can size that before relying on it.