code. Branch on the code, not the HTTP status and not the
message — the status is shared across unrelated failures and the message is prose we may
reword. Where a finite set of legal values exists, the body carries it in
details.accepted_values, so a 400 is usually enough to fix the call without reading anything.
Authentication
The request never reached a handler. Check the key, not the query.| Code | HTTP | What happened | What to do |
|---|---|---|---|
MISSING_API_KEY | 401 | No Authorization header was sent. | Send Authorization: Bearer gdelt_sk_…. |
INVALID_API_KEY | 401 | The key is not recognised. | Check for a truncated paste; create a new key if unsure. |
INVALID_TOKEN | 401 | The bearer token is malformed or expired. | Re-issue the token. |
API_KEY_DISABLED | 403 | The key was disabled — usually by the automated abuse sweep. | Check the owner mailbox for the notice, then create a replacement key. |
ADMIN_REQUIRED | 403 | An admin-only preview surface. | Not available on customer keys. |
Entitlement
The endpoint exists and your key is valid, but this workspace does not carry the flag it needs. Always an explicit error — never an empty result, which would be indistinguishable from “we have no data for you”.| Code | HTTP | What happened | What to do |
|---|---|---|---|
SUBSCRIPTION_REQUIRED | 403 | This action requires a paid subscription or an active trial. Signed-in browsing remains available with QU. | Start or renew a subscription; saved keys and Monitor configurations are retained. |
PLAN_REQUIRED | 403 | The endpoint is behind a plan capability this workspace does not carry. details.required_capability is the plan flag (for example can_use_filings), details.capability its human label, and details.current_plan the plan the key resolved to. | Choose a plan that carries details.required_capability at details.pricing_url (details.eligible_plans names them when the catalogue is attached), or call one of details.alternatives — endpoints the current plan can already answer. details.retryable is false: the same request will not succeed until the plan changes. |
PROGRAMMATIC_ACCESS_DENIED | 403 | The plan does not include programmatic access — API keys and the MCP server — outside an active evaluation. The web app and the API Arena keep working on it; details.surface says whether the refused call came through a key or MCP. | Choose a paid plan at details.pricing_url to keep API keys and the MCP connection working, or use the web app and the API Arena at details.arena_url. |
BRIEF_ACCESS_DENIED | 403 | Briefs are not enabled for this workspace when the hosted feature is available. | Requires can_use_briefs after the feature is restored. |
DETAILED_BRIEF_NOT_AVAILABLE | 403 | The requested brief depth is not enabled. | Request a shallower depth, or enable can_use_detailed_briefs. |
PAYMENT_OVERDUE | 402 | The workspace is past due and reads are paused. | Settle the balance; access resumes without a new key. |
MONITOR_ACCESS_DENIED | 403 | Monitors are not active on this plan. | details.plan names the current plan. Upgrade, or start an evaluation. |
MONITOR_FREQUENCY_NOT_ALLOWED | 403 | This plan supports daily Monitors only. | Use cadence: daily, or upgrade for hourly checks. |
MONITOR_WEBHOOK_NOT_ALLOWED | 403 | Signed webhook delivery is not available on this plan. | Use email delivery, or upgrade to Watch or higher. |
MONITOR_PUBLIC_DISABLED | 403 | Monitors are disabled on this deployment. | The emergency deployment kill switch is active; existing scheduled Monitors are unaffected. |
MONITOR_MANAGER_REQUIRED | 403 | Only organization owners and admins can manage Monitors. | Ask an organization admin, or view Monitors read-only. |
MONITOR_QUERY_ACCESS_DENIED | 403 | The current workspace does not have every source capability required by the query. Saved specifications never grant entitlements. | Choose sources included in the current plan or change the plan through the normal billing flow; do not reinterpret unavailable data as zero. |
Validation
A parameter was rejected rather than silently ignored. A filter that looks accepted and does nothing produces a confident, wrong answer, so the API fails loudly instead. The body carriesdetails.accepted_values wherever a finite set exists.
| Code | HTTP | What happened | What to do |
|---|---|---|---|
CONFLICTING_COUNTRY_FILTERS | 400 | Resource statistics received both country and its country_iso3 alias. | Send country or country_iso3, not both. Each accepts country names, ISO codes and comma-separated countries. |
INVALID_EDITION_REQUEST | 400 | A Situation edition selector, level or historical filter is invalid or conflicts with another parameter. | Use one edition_id or UTC as_of selector and the parameters documented for the requested endpoint. |
INVALID_RECORDED_INTERVAL | 400 | Recorded-time bounds or the continuation cursor are invalid or conflict with reporting dates. | Send paired recorded_start and recorded_end UTC timestamps and reuse unchanged filters with next_cursor. |
INVALID_BODY | 400 | The request body is not a valid JSON object. | Send a JSON object with Content-Type: application/json. |
UNKNOWN_FIELD | 400 | The request body contains a field the endpoint does not accept. | Use only fields documented for this endpoint and method. |
IDEMPOTENCY_CONFLICT | 409 | The Idempotency-Key was already used for a different Situation creation body. | Use the original body to recover that request, or a new key for a different request. |
IDEMPOTENCY_KEY_REQUIRED | 400 | Admitted Situation work requires an Idempotency-Key of 8–128 letters, numbers or ._:- characters. | Generate a key once and retain it across retries of the same request. |
INVALID_SEED | 400 | A Situation seed or target identifier is empty, contains whitespace/control characters, or exceeds 256 characters. | Use an identifier returned by the Story, Event or Situation API. |
SEED_REQUIRED | 400 | Neither a Story nor an Event seed was supplied for Situation creation. | Supply story_id or event_uid. |
INVALID_DIRECTION | 400 | The Situation expansion direction is not back or forward. | Use back or forward, or omit direction for forward expansion. |
SEED_MISMATCH | 409 | The selected Story does not support the supplied Event seed. | Select a Story returned by the Event’s serving links. |
AMBIGUOUS_EVENT_SEED | 409 | The Event has multiple supporting Stories, so the service cannot choose a Situation seed. | Choose one of details.stories and resend with its story_id and the Event ID. |
STORY_NOT_IN_SITUATION | 409 | The seed is not a member of the requested Situation, or the target cannot be resolved. | Use a member Story of the target Situation or omit situation_uid to discover/create the seed’s Situation. |
UNKNOWN_PARAM | 400 | A strict descriptor-backed endpoint received a query parameter it does not declare. On /events, /stories and their summaries, a spelling that can only mean one declared parameter is served as that parameter instead and listed in applied_filters.normalized; this code remains for anything ambiguous. | Read details.param, details.did_you_mean and details.accepted_params; correct or remove the parameter. |
MISSING_PARAM | 400 | A parameter required by the selected operation or parameter combination was omitted. | Read the error message for the required name. Atlas GPR requires geo when level is country, region, or continent; omit it only for level=world. |
UNSUPPORTED_FILTER | 400 | A parameter this endpoint deliberately does not support. Rejected rather than ignored. | Read details.alternatives — the reference lists a replacement for every rejected parameter. |
UNSUPPORTED_ENTITY_MATCH | 400 | An explicit entity-match policy is not implemented. On /events, /stories and their summaries the request is served with entity_match=coverage instead, flagged applied_filters.coverage_fallback_applied: true and listed in applied_filters.normalized; elsewhere it is refused without substituting broader results. | Use entity_match=coverage or omit it to retrieve Stories mentioning or linking the entity and the Events those Stories carry. Coverage does not establish actor participation or material involvement. This refusal is not retryable. |
INVALID_CURSOR | 400 | The pagination cursor could not be read. Cursors are opaque — construct them only by copying pagination.next_cursor. | Restart the walk from the first page and follow pagination.next_cursor. |
CURSOR_STALE | 400 | The cursor is valid but no longer describes this result set. Legacy snapshot cursors become stale when their source or snapshot changes; retained Event and Story walks also become stale after their fixed 24-hour lifetime or when their retained data is unavailable. Continuing would repeat or skip rows, so the request is refused rather than answered plausibly. details.reason identifies the cause when available. | Restart the walk from the first page. Keep filters fixed and finish Event or Story pagination within 24 hours; never force a warehouse route to bypass snapshot consistency. |
UNSUPPORTED_PARAM | 400 | A parameter that is not part of this endpoint at all. | Check the parameter reference for the endpoint you are calling. |
INVALID_MONITOR_PAYLOAD | 400 | The Monitor body failed the public Monitor schema. | details.path names the failing field. The body is strict — an unrecognised key is refused rather than ignored. |
INVALID_MONITOR_UPDATE | 400 | A Monitor PATCH was empty or named a field the update contract does not accept. | Send at least one of name, description, subject, criteria, trigger, schedule, delivery, rotate_webhook_secret, enabled. |
INVALID_MONITOR_BATCH | 400 | A batch request named no Monitors, more than 100, or an unknown action. | Send 1-100 ids and one of enable, disable, delete. |
INVALID_MONITOR_CONFIGURATION | 400 | The Monitor is syntactically valid but cannot be executed as configured. | details names the unsupported combination. |
INVALID_MONITOR_RUN_PAGINATION | 400 | limit or offset on Monitor runs was out of range or repeated. | limit 1-100, offset 0-100000, each at most once. |
INVALID_MONITOR_MATCHES_PAGINATION | 400 | limit or cursor on a Monitor run’s matched items was out of range, repeated, or not a cursor this endpoint issued. | limit 1-100, each parameter at most once. cursor is opaque and is NOT an offset — copy next_cursor from the previous page verbatim, and omit it for the first page. |
INVALID_WEBHOOK_URL | 400 | The webhook destination is not a public HTTPS URL. | Production destinations must be public HTTPS. localhost is permitted only behind the local development flag. |
INVALID_FACILITY_ID | 400 | A facility handle is not a canonical f_/s_ id. | Resolve the facility first with GET /api/v2/facilities. |
INVALID_COUNTRY | 400 | A country value is not a recognised ISO-3 code, ISO-2 code or country name. | Use ISO-3, e.g. USA. |
INVALID_ADMIN1 | 400 | An admin1 value is malformed, or was sent without exactly one country. | admin1 requires exactly one country. |
ACTOR_MATCH_NOT_SUPPORTED | 400 | subject.match = actor is not offered by Monitor v1. | Use coverage, then confirm actor involvement with the Events API after a match. |
MATERIAL_MATCH_NOT_SUPPORTED | 400 | subject.match = material is not offered by Monitor v1. | Use coverage and investigate matches with the API. |
VOLUME_SPIKE_NOT_SUPPORTED | 400 | trigger.type = volume_spike is not offered by Monitor v1. | Use new_matches. |
MONITOR_ORG_REQUIRED | 400 | Monitors are organization-scoped and the request resolved no organization. | Select an active organization. |
INVALID_TARGET_SCOPE | 400 | The requested typed target scope is invalid or cannot be resolved as supplied. | Check the target type and IDs, then use canonical IDs returned by the corresponding search or detail endpoint. details provides field-specific guidance. |
PREVIEW_WEBHOOK_URL_NOT_PERSISTABLE | 400 | A two-minute first-party Preview receiver URL was submitted as a saved Monitor destination. | Supply a webhook endpoint you operate. Preview receiver capabilities are temporary and cannot be persisted. |
MULTIPLE_ENTITY_HANDLES | 400 | More entity handles were sent than the parameter accepts. entity on /api/v2/events and /api/v2/stories unions a comma list up to the published cap; co_occurring_with on /api/v2/entities takes exactly one subject. | Read details.accepted_count for the ceiling and split the list across requests, merging the results. The extra handles are never silently dropped — before this code existed they were, at HTTP 200, echoed back as applied. |
OFFICE_SCOPE_TOO_LARGE | 400 | The political office sent as office= had more office-holders inside the window than one request may scope over (details.accepted_count, currently 1,000 — every national legislature we hold fits). The roster is never truncated to the first N. | Narrow the valid-time roster: send office_as_of=YYYY-MM-DD to scope to the holders on ONE date, or a shorter date_start/date_end window. details.holders is the count that was refused. |
INVALID_DATE | 400 | A date is not YYYY-MM-DD. | Use ISO dates. date_start / date_end take a calendar date only; observed_start / observed_end additionally accept a full instant such as 2026-08-01T04:04:30Z. |
INVALID_DATE_RANGE | 400 | date_start is after date_end. | Swap them. |
DATE_WINDOW_TOO_LARGE | 400 | The window exceeds this endpoint’s maximum span. On /events, /stories and their summaries a window of up to a year is served as its most recent permitted days instead, reported in meta.window_adjustment (reason window_exceeds_maximum) and applied_filters.normalized; longer windows still receive this code. | Read details.coverage and suggested_window. Use consecutive chunks of at most max_days inclusive days, not calendar months. Keep filters fixed and exhaust pagination.next_cursor in each chunk; restart without a cursor for the next chunk. |
DATE_RANGE_REQUIRED | 400 | This endpoint will not run unbounded. | Pass days or an explicit date_start/date_end. |
INVALID_LIMIT | 400 | limit is outside the accepted range. On /events, /stories and their summaries a limit above the maximum is served at the maximum instead and listed in applied_filters.normalized; a non-numeric or below-minimum value still receives this code. | Use the documented maximum and paginate with cursor. |
INVALID_BBOX | 400 | A bounding box is malformed or inverted. | The axis order differs by family, and a swapped box usually returns an empty or wrong 200 rather than this error. Events, stories, facilities and energy take latitude first — lat_min,lon_min,lat_max,lon_max. Maritime takes longitude first — min_lon,min_lat,max_lon,max_lat. The per-parameter description in the spec is authoritative for the path you are calling. |
INVALID_NEAR | 400 | The near grammar does not match this endpoint’s. | Events and stories take lat,lon with a separate radius_km; facilities and energy take a single lat,lon,radius_km triple. The spec carries the right example per path. |
INVALID_ENTITY_ID | 400 | A bare name was sent where a resolved id is required. | Resolve it first with GET /api/v2/search, then pass the e_… id. |
AMBIGUOUS_LEGACY_ID | 409 | A legacy facility-unit id maps to more than one canonical physical site. | Use a canonical s_… site id returned by GET /api/v2/facilities; candidate ids are in details.canonical_site_ids. |
ENTITY_REQUIRED | 400 | This endpoint is per-entity and no entity was named. | Pass entity. |
FILTER_REQUIRED | 400 | This endpoint needs at least one narrowing filter. | Add a geography, taxonomy or entity filter. |
INVALID_LIST_SOURCE | 400 | An unknown screening list, or one we declare but do not yet carry. | Branch on details.reason: unknown_source_key vs declared_but_not_ingested. Never an empty success — on a sanctions surface that would read as a clean result. |
EVENT_FAMILY_CATEGORY_CONFLICT | 400 | A deprecated event_family contradicts the category sent with it. | Drop event_family; category implies the family. |
INCOMPATIBLE_PARAMETERS | 400 | Individually valid parameters describe a combination this endpoint cannot answer honestly. | Read details.required and remove or replace the conflicting values. |
SUBCATEGORY_REQUIRES_CATEGORY | 400 | subcategory was sent with no category. Sub-event types are scoped by category and several labels are ambiguous without one. | Send category too. details.accepted_categories lists the categories that have subcategories. |
INVALID_SUBCATEGORY_FOR_CATEGORY | 400 | The subcategory is a real taxonomy code but not one that belongs to the category sent with it. | Read details.accepted_values — it is the subcategory list for the category you actually asked for. |
STORY_CATEGORY_CONFLICT | 400 | story_category and the deprecated category spelling of it were both sent, naming different values. | Send one. story_category is the current spelling. |
INVALID_NUMBER_RANGE | 400 | A metric _min is greater than its _max, so the range is empty. Refused rather than served as a (correct but useless) empty result. | Read details.min_value / details.max_value and swap them. |
EVENT_FAMILY_METRIC_CONFLICT | 400 | A metric only one event family publishes (magnitude, systemic_importance, propagation_potential, market_sensitivity — all CAMEO+) was combined with a taxonomy filter that commits the request to the other family. Unsatisfiable by construction: the conflict detail table has no such column. | Read details.metric_family and details.implied_family — they disagree. Drop the metric filter, move the taxonomy filter into details.metric_family, or use a metric both families publish (details.accepted_metrics_for_family). |
INVALID_NUMBER | 400 | A numeric parameter is not a number, or is outside the range this endpoint publishes for it. Also raised for days / window when the relative span is not a whole number of days inside the endpoint’s cap. | The message names the bound that was broken, and it is the same bound the OpenAPI schema publishes for that parameter (minimum / maximum). Where the registry validates the parameter the body carries details.param, details.invalid_value and those bounds; the days / window form carries details.max_days. |
INVALID_BOOLEAN | 400 | A boolean parameter was sent something that is not a boolean literal. Refused rather than read as false, because a filter silently dropped to its negative case answers a different question at HTTP 200. | Send true or false; case is not significant, so TRUE is accepted. 1 / 0 and yes / no are not — the vocabulary is exactly the two words. |
CONFLICTING_TIME_WINDOW | 400 | An explicit window (date_start / date_end) and a relative one (days or window) were both sent. Only one can apply, and silently choosing either would return rows outside the range you asked for. | Send one of them; details.params lists what arrived. date + days is deliberately still allowed — that composes into a relative span ending on a fixed date rather than contradicting it. |
INVALID_SITUATION_ID | 400 | The Situation address is not a valid Story ID or Situation UID. | Copy an ID from the Stories or Situations endpoint; do not pass a title or URL as the path ID. |
INVALID_PARAM | 400 | A candidate-search parameter has an invalid value or is incompatible with the selected source universe or entity type. | Use the accepted values in details when present. Politicians require people with office evidence; facility candidates use all or reference sources. |
INVALID_SCOPE_VERSION | 400 | A Situation page continuation supplied a malformed scope fingerprint. | Use the scope_version returned by the preceding page, or restart at the first page without a fingerprint. |
INVALID_WINDOW | 400 | The date_start / date_end span on a Situation is inverted, longer than this endpoint will walk, or — on /api/v2/situations — a country, category or entity facet was sent without BOTH reporting bounds. The dates that are present are well-formed; the WINDOW is what is refused. | Order the dates and keep the span within details.max_days (30). With a country, category or entity facet, always send both bounds. On the detail route, sending neither is usually right: the window defaults to the anchor Story’s own date rather than to today. |
INVALID_SEARCH | 400 | The free-text search term was refused before any query ran: it is too short to narrow anything (/api/v2/stories requires two characters), or it names more terms than the endpoint will conjoin (/api/v2/situations matches at most details.max_terms, since every term must appear in the stored title or a member Story headline). | Read details — it names the parameter and, where a count applies, term_count against max_terms. Shorten the phrase rather than expecting the extra terms to be dropped; nothing is truncated silently. To search what a Situation is ABOUT rather than what its headline says, use GET /api/v2/stories?search= and take a returned Story id to /api/v2/situations/{story_id}. |
INVALID_SUBCATEGORY | 400 | A subcategory value is not a sub-event type this API carries at all. Distinct from INVALID_SUBCATEGORY_FOR_CATEGORY, where the code is real and simply belongs to a different category. | Read details.accepted_values — it is already scoped to the categories you sent — and details.nearest_values for the closest spellings to what you wrote. |
MULTIPLE_STORY_CATEGORIES | 400 | More than one Story-cluster category arrived through the deprecated category spelling. A Story carries exactly one. | Send a single story_category, and keep category for the linked Event categories. details.accepted_values lists the Story vocabulary. |
CONFLICTING_FAMILY_FILTER | 400 | domain=CONFLICT names the conflict family — it is the value an event card prints in its domain field — and an event_family naming a different family was sent alongside it. Both cannot apply. | Send event_family=conflict on its own, or a CAMEO+ domain together with event_family=cameoplus. Sent alone, domain=CONFLICT is translated to the family filter that means it. |
INVALID_MONITOR_QUERY | 400 | A query Monitor contains unsupported or competing parameters, an unresolved identity, or fixed dates/pagination in its standing parameters. | Use an allowlisted endpoint and its documented parameters, resolve selected IDs with /api/v2/search, and keep discovery dates in source_request. Scheduled matching uses committed records since the previous successful checkpoint. |
DATE_OUT_OF_COVERAGE | 400 | The requested window lies entirely before the dataset’s coverage begins (published on every successful response as meta.coverage.start). No snapshot exists for those dates and none will be built, so this is not retryable. details includes http_status, target, date, coverage_start and retryable: false. | Request a window on or after details.coverage_start. A window that begins before coverage but ends inside it is served from the first covered day, with the omitted dates disclosed in meta.window_adjustment (reason requested_dates_precede_coverage). Do not retry the original request. |
MONITOR_QUERY_RETRIEVAL_BOUNDED | 422 | Semantic relevance retrieval is a bounded candidate pool and cannot establish exhaustive scheduled query matching. | Explicitly choose search_mode=lexical for literal phrase matching over served text, or remove the text query and use supported structured filters. This changes matching meaning and is never automatic. |
Data availability
The request is valid, but the evidence required to answer it under the requested semantics is not available. Never interpret this as an empty result or as evidence that nothing happened.| Code | HTTP | What happened | What to do |
|---|---|---|---|
SOURCE_UNAVAILABLE | 503 | The selected registry release or requested collection lacks positive publication evidence. | Retry after source publication completes. Empty data is not evidence of absence. |
ACCESS_UNAVAILABLE | 503 | Current workspace or trial access could not be established. No access was granted by assumption. | Retry with backoff; the response includes Retry-After. |
CREATION_UNAVAILABLE | 503 | Situation creation admission, its durable receipt, or completion recovery is temporarily unavailable. | Retry the same request with the same Idempotency-Key. Do not start a second charged request to work around an uncertain response. |
FEATURE_DISABLED | 503 | This optional product surface is disabled across all plans, including a hosted agent, Monitoring Briefs, or retained Situation editions. | Use the available REST API, MCP data tools, or Monitors; retry the disabled surface after it is enabled. |
CREATION_IN_PROGRESS | 409 | A Situation creation request with this key is running or being recovered. | Wait, then retry with the same Idempotency-Key and unchanged body. |
ADJUDICATOR_UNAVAILABLE | 503 | Situation adjudication is disabled or its service is unavailable; no creation charge was admitted. | Retry later with the same request key. |
EVENT_UNAVAILABLE | 503 | The Event’s canonical serving identity could not be established. | Retry after serving identity reconciliation; do not substitute an unverified Event date or ID. |
MONITOR_WAREHOUSE_UNAVAILABLE | 503 | The analytical warehouse did not answer this Monitor query. | Retry with backoff. details names which read failed. |
MONITOR_WEBHOOK_UNAVAILABLE | 503 | Signed webhook delivery is not configured on this deployment. | Contact support; the signing secret is a server-side configuration. |
FACILITY_ACTIVITY_SCOPE_UNAVAILABLE | 503 | Facility-scoped Activity is unavailable until facility identities are present in both publication journal projections. | Retry after the facility publication schema is upgraded. Do not remove the facility scope or treat the response as an empty result. |
SCOPE_CURSOR_UNAVAILABLE | 503 | Scoped Activity pagination is unavailable because the durable cursor secret is not configured. | Retry after the service operator configures the cursor secret. Do not restart pagination with an offset. |
ENTITY_TONE_UNAVAILABLE | 503 | Entity tone cannot safely reconcile a known identity conflict for the requested window because the live cluster-level source is unavailable. | Retry with backoff. The API refuses to substitute the affected daily aggregate because it contains misattributed evidence. |
SITUATION_SCOPE_CHANGED | 409 | Situation membership changed between pages, so this continuation would mix snapshots. | Restart at the first page and use its new scope_version for subsequent pages. |
ENTITY_ATTRIBUTION_UNAVAILABLE | 503 | A legacy Monitor requested an attribution capability that cannot be executed. | Update the Monitor subject to match: coverage. The public Events and Stories APIs support coverage matching only. |
WAREHOUSE_BUSY | 503 | The data service temporarily reached its memory or concurrency capacity. | Honor Retry-After and retry with backoff; details.retryable is true. |
PUBLICATION_SNAPSHOT_UNAVAILABLE | 503 | The committed publication snapshot is unavailable or its serving commit metadata has not finished mirroring. A failed read cannot establish an empty page or complete a Monitor checkpoint. | Retry with backoff. Operators should reconcile publication commit metadata under the source writer lease; do not route around the committed projection. |
SERVING_SNAPSHOT_UNAVAILABLE | 503 | The safely published Event or Story snapshot cannot yet answer the requested date or stable id. The required partition may still be publishing, or a known row may not yet be present in that published snapshot. details includes http_status, target, date and retryable. | Honor Retry-After and retry the same request. For a date-range query, you may instead choose a range containing an already published date; a partly available valid range returns HTTP 200 with exact coverage. Do not switch to an ingest/warehouse read. |
MONITOR_QUERY_INCOMPLETE | 503 | The query could not establish complete coverage because publication history, paging, or a bounded Preview was incomplete. No completed Monitor checkpoint was advanced. | Follow the error explanation. Retry source availability failures or narrow the scope for a bounded Preview. Scheduled successful pages remain staged for continuation. |
SERVING_WINDOW_INCOMPLETE | 503 | The requested Monitor interval does not have complete serving coverage. No completed quiet interval is inferred. | Honor Retry-After and retry after the missing serving dates are repaired. Preview may disclose partial coverage. |
QUERY_DEADLINE_EXCEEDED | 503 | A shared data read exceeded its deadline. | Retry with backoff or narrow the requested window and filters. |
TIMEOUT | 503 | An upstream shared data read timed out. | Retry with backoff. An unavailable response does not establish zero matches. |
MONITOR_QUERY_TIMEOUT | 503 | The Monitor query exceeded its 45-second execution budget and was cancelled. | Retry with a narrower window or more specific supported filters. Missing historical examples do not mean there are no matches. |
QUERY_TIMEOUT | 503 | The query exceeded its execution budget. The server does not repeat a deterministic timeout within the same request. | Honor Retry-After and retry with backoff. Reduce the date window or add supported structured filters; details.retryable is true. |
ENTITY_SEARCH_UNAVAILABLE | 503 | A candidate source or required identity-evidence lookup failed. The request establishes neither a complete candidate list nor the absence of a match. | Retry with backoff using the same candidate query. Do not bind another identity or infer zero coverage from this failure. |
Not found and withdrawn
The id is well-formed but resolves to nothing, or to something that has since been superseded. A withdrawn or merged record returns a pointer to its replacement rather than a bare 404.| Code | HTTP | What happened | What to do |
|---|---|---|---|
SITUATION_EDITION_NOT_FOUND | 404 | No retained edition matches this historical Situation identity and selector. | List the Situation editions. Complete retention starts at rollout; earlier knowledge is not reconstructed. |
MONITOR_NOT_FOUND | 404 | No Monitor with that id is visible to the active organization. | Check the id and the active organization. A malformed id also answers 404 rather than 500. |
MONITOR_RUN_NOT_FOUND | 404 | No run with that id belongs to this Monitor and this organization. Runs are retained for seven days, so an id from an older notification is expected to answer this. | List the retained runs with GET /api/v2/monitors/{id}/runs. A run that has aged out is gone; nothing re-creates it. |
NOT_FOUND | 404 | No record with that id. | Ids are opaque — do not construct them. Re-fetch from a list endpoint. |
NOT_FOUND_IN_WINDOW | 404 | The id resolves to nothing INSIDE the date window the request asked for. It may exist outside it. | Drop start_date/end_date — a by-id read defaults to the record’s own date — or widen the window. |
ENDPOINT_REMOVED | 410 | A retired endpoint. It existed, it is intentionally gone, and it will not return. | Read details.replacement — it names the /api/v2 path that answers the same question. The Link: rel="successor-version" header carries it too. |
ENTITY_NOT_FOUND | 404 | The entity id does not resolve. | It may have merged; re-resolve the name through GET /api/v2/search. |
OFFICE_NOT_FOUND | 404 | No political office carries that id. An office id is the office’s Wikidata QID (Q…) or the deterministic p_ + 16-hex id /api/v2/offices serves; a name or any other form is not looked up and answers this too, so the code is also what a malformed id returns. | Resolve the office first with GET /api/v2/offices?q=<name> (optionally country=) and use the office_id it returns. Ids are stable across re-projection, so one that stopped resolving was never minted rather than retired. |
SITUATION_NOT_FOUND | 404 | A sit_… id that was never minted. Note that this is NOT what a superseded Situation answers — a Situation that merges into another resolves FORWARD to its survivor and returns it. | Check the id. Any member Story id also addresses this endpoint and resolves to its primary Situation, so a Story id from GET /api/v2/stories is the way in when you do not have a sit_…. |
STORY_NOT_FOUND | 404 | The path named a Story with no settled row on any date, so there is no situation to assemble around it. Different from a Story that simply has no neighbours — that is an empty situation at HTTP 200. | Confirm the id against GET /api/v2/stories, which serves from the same settled tables. A situation is assembled from those tables only, so an id they do not carry has nothing to walk from. |
UNKNOWN_ENDPOINT | 404 | No operation is served at that path under /api/v2. Also returned when an invented subpath such as /events/count would otherwise be mistaken for an Event id. | Read details.did_you_mean, which ranks by shared path segments rather than raw edit distance. GET /api/v2/meta/endpoints lists every operation this API serves. |
STORY_MERGED | 404 | The story was adjudicated a duplicate and folded into another. | Follow the replacement id in the body. This is not an error to retry. |
EVENT_WITHDRAWN | 404 | The event stopped resolving and no single replacement could be determined — it was suppressed in review, or merged in a way that names no one live successor. | Read the reason in the body; do not treat the prior record as still true. Re-query GET /api/v2/events for the current event covering this incident. |
EVENT_MERGED | 404 | The event was adjudicated a duplicate and folded into another event, which is live. | Follow successor_event_id in the body. This is not an error to retry. |
Limits
The request was well-formed and refused on volume or account state.| Code | HTTP | What happened | What to do |
|---|---|---|---|
MONITOR_LIMIT_REACHED | 403 | The organization is using every enabled Monitor slot. | Pause or delete a Monitor, or upgrade. details.max_monitors carries the cap. |
MONITOR_WATCHED_ITEM_LIMIT_REACHED | 403 | This Monitor exceeds the number of explicitly selected targets allowed on the current plan. | Remove selected targets or upgrade. Automatically connected updates do not count toward the selected-target limit. |
MONITOR_PREVIEW_RATE_LIMITED | 429 | The free first-party webhook demonstration has reached its organization-scoped hourly limit. The real Preview query already completed. | Wait for the Retry-After interval, then retry Preview. This limiter does not consume Query Units. |
RATE_LIMITED | 429 | Too many requests per minute. | Back off and retry. Concurrency, not volume, is usually the cause. |
QUOTA_EXCEEDED | 429 | The Query Unit allowance for the period is spent. | Wait for the period to roll over, or raise the allowance for this workspace. |
Server
Our fault. Safe to retry with backoff.| Code | HTTP | What happened | What to do |
|---|---|---|---|
CREATION_FAILED | 503 | Situation creation or expansion did not complete; its reservation was cancelled and this receipt charged zero QU. | Inspect the error and retry later. Reusing the same Idempotency-Key returns the saved outcome; a new attempt needs a new key. |
CREATION_INTERRUPTED | 503 | An interrupted Situation request was recovered before a Situation was saved; no QU were charged. | Start a new request with a new Idempotency-Key to try creation again. |
MONITOR_OPERATION_FAILED | 500 | A Monitor write did not complete. | Retry. Nothing was partially applied. |
INTERNAL_ERROR | 500 | An unhandled failure. | Retry with backoff. If it persists, send us the request id from the response. |
PLAN_FEATURES_ERROR | 500 | Entitlements could not be resolved for this workspace. | Transient — retry. Not a statement about what your workspace carries. |
ORG_RESOLUTION_ERROR | 500 | The workspace behind the key could not be resolved. | Transient — retry. |
SEMANTIC_SEARCH_UNAVAILABLE | 503 | The embedding call behind search= failed or timed out, so the query could not be embedded. Nothing is served in its place — a lexical fallback would silently answer a different question. | Retry shortly. To proceed without it, drop search and narrow with category, country or entity instead. |
Rejected values, by vocabulary
A closed vocabulary rejects anything outside its list. Most returnINVALID_ENUM; a few carry
their own code so a caller can branch without inspecting details. Derived from the same
vocabulary registry the server validates against.
| Code | Vocabularies |
|---|---|
INVALID_CATEGORY | event_category |
INVALID_CONTINENT | continent |
INVALID_ENUM | activity-change, activity-kind, activity-time-basis, actor_role, actor_type, atlas_coverage_tier, atlas_gpr_component, atlas_gpr_construction, atlas_gpr_metric, atlas_gpr_variant, atlas_level, atlas_posture_scope and 73 more |
INVALID_LIST_SOURCE | exposure_list, list_source_key |
INVALID_REGION | region |
INVALID_TRACKER | gem_tracker |
UNSUPPORTED_FILTER | gem_heavy_industry_tracker |
An observed vocabulary never rejects on membership — it is a dated measurement, not an
allowlist, and the API accepts values outside it. Only closed vocabularies appear above.

