Stories, Events and Situations
Situation membership is adjudicated automatically from evidence. Curated means a stored,
adjudicated collection; it does not mean a human reviewed every member. Membership can be
incomplete or mistaken. A Story can belong to more than one Situation when it contributes to
more than one developing thread.
Find a maintained Situation
Use your existing API key:situation_uid, title, span, origin and peak pointers, and full serving
totals. Take a returned situation_uid to the detail endpoint. The UID is the identity;
the title and representative Stories can change as the collection develops. A merged
Situation’s old identifier resolves forward to its survivor.
List dates select Situations whose current serving span overlaps the requested window.
totals and scope describe the whole Situation; selected_scope describes member reporting
in your requested dates. Selection, ordering and counts use the same current serving membership.
counts_updated_at is serving freshness, while scope.version identifies the measured content.
Article totals sum member Story counts; they do not assert globally unique article URLs.
The list’s search matches words in the stored title. It does not search every member or
article, and it is not semantic search. For broader discovery, search
/api/v2/stories and pass a returned Story ID to the Situation detail endpoint.
That route may return an exploratory result, as explained below. Consult the
parameter reference for supported filters rather than assuming every
Event or Story filter also applies to Situations.
Inspect the collection and its evidence
ReplaceSITUATION_ID with a UID returned by the list:
stories, coded incidents, an entity cast, daily
rollups, composition and totals. Follow each member’s story_id to
/api/v2/stories/{story_id} and /api/v2/stories/{story_id}/articles to inspect its evidence.
Use the returned Event identifiers for the fuller Event records, including date and casualty
evidence where available.
origin points to the earliest member with material coverage, and peak to the largest
member by article coverage. Neither is a claim about the exact beginning of the real-world
occurrence, and the peak is not necessarily its most severe moment. Read the coded Events
for occurrence dates; Story dates describe the coverage being assembled.
Page Stories, Events and Entities independently
Use/api/v2/situations/{story_id}/stories, /events, and /entities for complete
membership discovery. The published path token is story_id on every Situation route; the member
lists accept only a stored sit_… UID. Each defaults to 25 records; its own pagination.total and has_more
are independent of graph limits. Send the same reporting dates on every page. Keep the first
response’s scope.version and send it as scope_version with later offsets. If the evidence
changes, HTTP 409 asks you to restart instead of silently combining different editions.
Entity versions also reflect canonical identity resolution and linked coverage. The workspace keeps each evidence page and its version when you change tabs or reopen its link; an explicit restart begins with the current membership.
scopes.whole and scopes.selected make whole-Situation versus window totals explicit.
The graph, its cast and incident arrays remain bounded; caps says what was returned. The
adjudication split describes the returned incident rows. Membership route counts are not an
independently confirmed count of real-world incidents.
Dated background and changes
When available,narrative contains a short background and changes in reporting, each with
supporting Story IDs. method=extractive labels attributed verbatim headline excerpts used when a synthesis cannot be supported. A separate adversarial check must approve the claims against served
reporting before publication. The response names its evidence sample size, full member count,
publication date and content version. These summaries are reporting summaries, not independent
verification that every reported claim is true.
Failed regeneration retains the previous dated summary. narrative.current=false means newer
served evidence exists; narrative=null means no verified summary is currently available.
A snapshot preserves its full member manifest and measured scope. The summary covers the whole
Situation even when the evidence tabs use narrower dates.
Maintained Situations advance and discover qualifying threads hourly. Reconciliation and merging
run overnight, preserving the existing daily creation budget. The two-day Story-link candidate
window limits link discovery, not how long a Situation can continue. Published freshness and
partial/error maintenance runs remain distinct from a guarantee of exhaustive coverage.
Stored membership and exploratory results
The public discovery page initially shows Situations with at least 2 member Stories and 2 coded Events across their whole current servable membership. These are combined requirements; narrowing the reporting dates does not reapply them to just that slice. Include emerging Situations lowers the request tomin_stories=1&min_events=0. The REST API applies these floors
only when supplied: existing calls that omit them still discover all nonempty, unmerged Situations.
The page’s default request is GET /api/v2/situations?min_stories=2&min_events=2.
These filters determine what discovery promotes; they do not delete seeds or prevent direct access
and growth. Automatic creation examines the reporting day’s top 400 Stories by their own article
count, requires a cross-day precursor or continuation link, then ranks candidates by the seed’s
article count plus its linked neighbors’ article counts. That combined coverage must reach 250
articles; at most 50 automatic Situations can be created per UTC day. There is no coded-Event
minimum at creation. The initial membership contains only the seed Story. A separate membership
judge decides which other Stories belong, so a large candidate thread can still produce a small
maintained collection if its proposed members are rejected. User-requested creation starts from
a served Story or a supporting Story for an Event and does not use the automatic coverage floor.
The scheduled workflow advances and seeds at minute 20 each hour. At 05:20 UTC it also reconciles
the history and nearby dates, then considers merges. A newly created seed may therefore remain
small while it awaits expansion; no growth is guaranteed.
Always read meta.situation_source:
A Story ID resolves to its primary stored Situation where one exists. Otherwise the detail
API can walk related Stories. At greater
depth, a member may be reached through another
Story without having been compared directly with the anchor. Inspect hop, via_story_id
and the optional edges; reachability is a weaker claim than Situation membership. On a
stored Situation, depth is inapplicable and is reported under applied_filters.ignored.
The maintained workspace focuses on stored Situations. Browsing or exporting an exploratory
API response does not create a stored Situation. Building or expanding one is separate from
the read API described here.
What a relationship means
Two different fields answer two different questions:stories[].routelabels the member’s place in the thread: coverage of the occurrence, an antecedent, a consequence, or another telling of the same incident. An expansion can assign antecedent or consequence from the Story’s date relative to the collection’s bounds. The label alone does not mean a judge established a causal relationship.stories[].relationandedges[].relationdescribe chronology or duplicate identity. A precursor occurs earlier; a continuation occurs later. Chronological order alone does not show that one development caused the other.
edge_source describes how a candidate pair was proposed. Shared entities or
embedding similarity can help find candidates; neither establishes membership on its own.
Confidence describes the adjudicator’s judgment, not a calibrated probability of causation.
Read each Story’s membership alongside the label. Its basis distinguishes a seed,
stored membership and a pairwise path; route_basis explains how the route was assigned.
reason carries a recorded membership explanation when available. evidence_status tells
you whether that decision is available, was not recorded, was not loaded, or whether only
pairwise evidence exists. A null reason is not a positive finding or a synthesized explanation.
Where present, decision identifies the verdict, policy version and decision time, and via
identifies the Story or Situation through which the membership was reached.
Same-incident Stories are represented differently on the two read paths. Stored Situations
retain them as members with route same_incident; exploratory results fold duplicates out
and report them under duplicates. Use the returned distinct counts and adjudication split
rather than treating every Story or Event row as a different real-world incident.
Follow connected entities and offices
The entity cast identifies entities linked to member Stories. Itsstory_ids let you trace
the connection back to those Stories. Appearance in the cast is not a claim that the entity
acted in, caused, or was affected by every Event. Use Event actor roles and source evidence
to establish those stronger relationships.
Reuse the returned entity ID for its profile and available source sections. A person’s
political offices provide dated actor context. Office-held facts,
public-list entries, ownership relationships and news co-occurrence answer different
questions; preserve their source and relationship meaning when combining them.
Source sections follow their existing entitlements. An unavailable or withheld section is
not evidence that the entity has no such records. In particular, offices use published
holding dates for valid-time as_of; that is different from a knowledge-time snapshot of
what the service knew then.
Limits, uncertainty and export
limit and offset page the member Stories. Incidents, the entity cast, daily rollups and
totals describe the admitted collection, so they can refer to Story IDs outside the current
page. For a stored Situation, max_nodes limits the graph sample and never changes full-scope totals.
For an exploratory walked result it bounds the discovered neighbourhood. Inspect
caps.members, caps.incidents, caps.entities and truncated before treating an array as
complete. A missing optional edges block means it was not requested, not that no links exist.
A member’s facts_status distinguishes available Story facts from an unavailable hydration.
An unknown linked_event_count is null; it is not a measured zero Events.
Fatality fields are reported figures: neither the maximum nor the raw sum is a verified death
toll for the entire Situation. Events may overlap or have unadjudicated identities. Unknown
values remain null; do not turn them into zero or sum overlapping reports into a new fact.
Save the complete API response, including metadata, filters, caps and timestamps:
Access
Situations reads use existing API authentication and Query Unit allowances. There is no separate Situations subscription or premium feature flag. Explore evaluation, the 50 QU/month web allowance after an evaluation ends — API reads need an active evaluation or a paid plan (403 PROGRAMMATIC_ACCESS_DENIED otherwise, see errors) — paid plans and
legacy overrides follow the same access rules as other API reads. Consult your account’s current
allowance and the pricing page for limits; individual connected
data sources retain their own access rules.
Browse all linked entities
GET /api/v2/situations/{story_id}/entities accepts a stored sit_… UID and pages
canonical entities across its full current servable membership. This is independent
of the detail response’s bounded member view and top entity cast.
summary.entity_count for the distinct canonical count and summary.by_type for
available type filters. entity_type=person filters before pagination. pagination.total
counts the type-filtered set; the summary always describes the whole requested scope.
Optional date_start and date_end scope membership by reporting date. Omit both to
inspect the full membership. An empty measured set returns zero; a failed or over-budget
measurement returns an error, never a partial exact total.
Each row includes canonical entity_id, name, type, distinct story_count, coverage counts,
first/last reporting dates, source entity IDs and identity basis. Story breadth is deduplicated
after identity folding. Article and mention counts sum resolved-link coverage and can overlap
across aliases. Linked coverage does not establish an actor role, ownership or exposure.
Filter discovery by linked Event evidence
country means coded Event location, using ISO-3 codes; actor nationality is not used.
category uses the Event taxonomy, not Story category. A Situation qualifies when any
member-linked Event matches both filters. Neither field claims a primary Situation country
or category. Both reporting date bounds are required when using either filter, with a maximum
of 30 inclusive days. Filtering happens before pagination and its exact match total.
Directory totals.entity_count is separately measured over each returned Situation’s full
current servable membership. entity_count_status=unavailable and a null count mean that
measurement failed. Existing Story/article/Event totals retain their stored-span scope and
counts_updated_at; they are not recomputed to the discovery filter window.
Refine discovery and inspect connections
Useentity, story_id or event_uid to find maintained memberships. Entity, country and category
filters require a reporting range of at most 30 days. The default sort=recent uses reporting dates
and genuine first-observed evidence; maintenance and settle refreshes do not promote a Situation.
category_summaries and selected_scope describe the selected reporting window, while totals
retains whole membership. Sharing a country, role or name does not establish membership.
GET /api/v2/situations/{story_id}/connections pages the complete membership list with relationship,
reporting date, first-observed timestamp and available adjudication provenance. Stories, Events,
Entities and Connections have independent limits, offsets and scope_version witnesses. Keep each
witness and the same dates while paging; restart that list from offset zero after a scope-change
409. Graph samples never limit list totals. Entity roles require explicit Event actor bindings;
reporting mentions alone do not establish participation.
Create a shared Situation
Paid subscribers and active trials can callPOST /api/v2/situations with story_id or event_uid.
An Event with several supporting Stories returns 409 AMBIGUOUS_EVENT_SEED and candidate Stories;
choose one explicitly. Reuse an existing canonical Situation for 0 QU. Admitted creation or
expansion costs 5 QU, with a quota reservation and refund on failed work.
Send a stable Idempotency-Key header of 8–128 letters, digits or ._:- characters. Store that key
before sending and reuse the same key and JSON body after a timeout. A repeated completed request
returns its original receipt without another charge. A running request returns a retryable
in-progress response; changing the request under the same key is refused. Optional situation_uid
selects a Situation to expand, and its seed Story must already belong to that Situation.
The MCP create_situation tool runs through gdelt_cloud_tool_write; its API reservation owns
billing, so the MCP wrapper does not add another 1 QU. Show the 5 QU price before creating.
A complete request, with the two rules that keep a retry from double-charging: the same body
after a timeout reuses the SAME key; a different body needs a NEW key. The Story id below is the
one the quickstart response returned; any served Story id works.
details.stories lists up to 100
candidate Stories with their reporting dates, and details.truncated says whether more exist.
A 409 IDEMPOTENCY_CONFLICT means the key was already used for a different body; a 409
CREATION_IN_PROGRESS means the same request is still running — retry it with the same key.
Every 503 on this route releases the quota reservation and names its retry in error.
Coverage, measured
A read-onlyGET /api/v2/situations?limit=1 against the production serving tables on
2026-09-07 (23:55 UTC) reported pagination.total of 18 maintained Situations, and
16 of them with at least one coded Event (min_events=1). That is the whole stored
collection at that moment — a small, deliberately bounded set, not a sample of a larger one.
Read the number with its counterexamples:
- Membership is adjudicated automatically and can be incomplete or mistaken;
curatedmeans a stored, adjudicated collection, not a human-reviewed one. - The automatic seed cap is 50 new Situations per UTC day, so a day with more qualifying threads than that leaves some unopened until the next day.
- Seven days without a qualifying development makes a Situation inactive; the total counts what is maintained, not everything that ever opened.
- A Story can belong to more than one Situation, so member totals across Situations overlap and do not sum to a count of distinct Stories.
- Exploratory
walkedresults returned for a Story with no stored Situation are not in this total at all.
Public daily editions and maintenance
Public/situations/{uid} pages display an immutable edition published through the last completed
UTC day. Cutoff and publication time are shown together. Evidence, counts, narrative and all
paginated lists are frozen together; a failed or incomplete publication retains the previous
edition. Signed-in /view/situations/{uid} pages use live serving data. Public page filter variants
are not indexed, and merged IDs redirect to their canonical identity.
Active Situations advance hourly at minute 20; reconciliation and merging run at 05:20 UTC.
Seven days without a qualifying development makes a Situation inactive. Routine refreshes do not
reset that clock. Bounded archived retrieval can propose new evidence, but independent membership
adjudication is required to reactivate the same UID. The automatic seed cap remains 50 per UTC day;
paid creation is accounted separately. Maintenance records model/service tier, duration, attempts,
tokens and estimated cost using versioned rates; unrecorded historical usage stays unavailable.
