Added — bulk downloads. Every coded event we serve is now also a file: one per calendar month plus a rolling full-history cut, in Parquet and gzipped CSV, at /downloads or through /api/v2/bulk/files. 172,213 events across 171 settled days, March 2026 to now. It is the same table /api/v2/events reads, so a row in a file and the same row from the API agree field for field — we check that on six dates spanning the range before publishing, comparing the exported projection against the live serve path row by row. Included on Intelligence, Enterprise and the new Academic plan.
Added — an Academic & Research plan. Free, verified access for individual researchers and journalists: every data surface at 5,000 query units a month, five daily Monitors, API, MCP, Monitor webhooks and bulk downloads, with no Briefs. It is invite-only rather than purchasable — request it from your subscription page and a person reads every one. Previously this was a card on the pricing page whose only mechanism was an email address.
Changed — the bulk files publish their own coverage rather than implying it. Each one reports settled days against calendar days, so an in-progress month reads 18/31 instead of looking complete, and a sha256 you can verify before loading. A month is only whole when those two numbers agree.
Note for anyone loading the files — a null metric is not a zero. The conflict family carries no magnitude, systemic-importance, propagation or market scores, and the CAMEO+ family carries no fatalities, because those questions were never asked of those events. Coalescing them to 0 on import invents measurements that were never taken. civilian_targeting is three-valued for the same reason: true, false, and null where no coder evaluated it.
Changed — /api/v2/stories/summary is now a Story summary. The 43 linked-event metric rollups (avg/min/max of goldstein scale and severity, magnitude, systemic importance, propagation potential, market sensitivity, confidence, and avg_recency_score) have been removed. A Story has no metrics of its own; those belong to its linked Events, and /api/v2/events/summary is where they live — it supports every group_by this endpoint does, plus two more, and accepts the same entity scope. Every response now carries a notice field naming it.
Fixed — and this is why they were removed rather than moved. Those averages were wrong. A story with no linked events contributed a literal 0 rather than a null, so the not-null guard never fired and each average was spread over every story in the bucket instead of only the stories that had events. Measured over 2026-08-14..16, avg_linked_event_magnitude read 0.4693 where the event-level figure was 2.9316 — understated by 84% — on the default, most-common call. If you were reading those fields, the numbers you had were not the numbers you wanted, and the events endpoint computes them per event, so they will not match what this endpoint used to return.
Kept — everything that is genuinely a property of a Story: story and article counts and their distributions, significance (an article-volume measure, not an event rollup), counts of linked events, stories with events, fatalities, and country/region counts. No request that worked before returns an error now; the response is narrower, not stricter.
Changed — ?country= on Stories now finds Stories with no coded Event. A Story has no coordinates of its own, so the filter was answered entirely through its linked Events, which meant ?country= silently also meant has_events=true and roughly four in five Stories were unreachable by any country filter, in any spelling. Stories now also match on their own attributed country. Over 2026-08-14..16 that took the reachable set from 5,386 to 24,207 of 25,463 Stories — about 4.5x. Nothing that matched before stops matching; this only adds.
Scope — combining country with an Event-scoped filter (event_category, subcategory, admin1, bbox, domain, civilian_targeting) keeps the Event-only definition, because those ask a question about the Story's Events and a Story with none cannot answer it. Attribution begins 2026-07; query a window before that and the filter behaves exactly as it did.
Changed — group_by on /api/v2/stories/summary now buckets Stories by the same country the filter matches on. Previously the filter and the grouping disagreed: you could filter to a country, group by country, and not find it, for exactly the Stories with no coded Event. Two numbers move as a result. On a date bucket, country_count and region_count rise (167 to 193 countries on 2026-08-14) because those Stories now have a country at all. Inside a country bucket, region_count falls sharply — United States read 10, now reads 1 — and that is the correction: a United States bucket holds US Stories, which are in one region; the old number counted the regions of their Events, which can be anywhere.
Faster — date, country, region and continent summaries now read the pre-settled snapshot. Same numbers to within 0.1 to 0.3 percent, and the category and subcategory dimensions are unchanged because those group by linked-Event taxonomy.
Fixed — the docs said /api/v1/* was still supported. It is not, and has not been since 2026-08-12: every v1 path returns 410 Gone naming its v2 replacement in the message, in details.replacement, and in an RFC 8594 Link header. Three pages carried the old claim. /api/v2/events?family=conflict and ?family=cameoplus are strict supersets of the two v1 event routes.
Fixed — the docs said metric_version was stored but not returned by the API. It is returned on the event card whenever it is set, so it is the direct way to tell a v2-scored event from an older one.
Changed — the event metric reference is now one page per metric. /reference/metrics keeps the design rule, significance in full and a summary of each of the four scored metrics; magnitude, systemic importance, propagation potential and market sensitivity each have their own page with the sub-factors, the anchors, the NULL rule and what that metric does not claim. Existing #anchor links still resolve. The cross-cutting caveats that were repeated on every metric — the frameworks we adapt, how thin the registry coverage is, and the run-to-run noise floor — now live once, on /metrics/limits.
Corrected — the coding-latency explanation. It said a Story had to accrete corroboration before it could be coded, and named that as the main reason events are coded after the day they happened. That is not how the pipeline works: single-article clusters are a first-class coding path and are most of what we code. Measuring latency from the earliest contributing article instead of the one the coder read moves the median by 32 seconds. The real causes are the hourly ingest cycle, publication lag in the sources, and the fact that event_date is a date rather than a timestamp. The page now also names observed_start / observed_end, which is the point-in-time filter on the API.