From zero knowledge to live humanitarian data in about ten minutes — the mental model, your first authenticated request, and two real queries.
This is the front door. If you’ve never touched the CLEAR API before, read this page top to bottom. By the end you’ll understand how the data is shaped and you’ll have pulled real records with your own API key. Everything else in these docs — the Queries, Mutations, and Types reference — is there to look things up after you understand the shape of the system.
1. The mental model
CLEAR is a five-tier graph. Raw observations flow in at the bottom and are progressively grouped, classified, and escalated into human-readable advisories. Almost every query you write touches one of these five tiers:
A user-curated aggregation of related events, enriched by an LLM with a summary, forward scenarios, and a needs analysis.
Two things to internalise. First, the tiers build upward: a Signal links to the Event it belongs to, which links to any Alert raised from it. Second, everything is geolocated — signals, events, and alerts all reference the Location hierarchy. That’s why the “by location” queries are the most powerful way to slice the data.
New to GraphQL? You send one POST request to /graphql with a query naming exactly the fields you want, and you get back exactly those fields — no over-fetching, no guessing at response shapes. The GraphQL Sandbox autocompletes every field as you type, which is the fastest way to explore.
2. Get set up
You need an account and an API key. Both live in the Developer Portal.
In the portal, open API Keys and create one. Copy it immediately — the full key is shown only once.
Treat your key like a password. Keep it in an environment variable or secrets manager — never in client-side code or version control.
3. Your first request
The me query is the simplest authenticated call: it returns the account your key belongs to. Run it first to confirm your key works before you touch real data. Replace YOUR_API_KEY with the key you just generated:
curl -X POST https://api.clearinitiative.io/graphql \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"{ me { id email role } }"}'
If me comes back null, your key isn’t being read — double-check the Authorization header and that the key hasn’t been revoked in the portal.
4. Pull real data
Now something useful. Locations are the backbone of the graph, so start there: this lists every country CLEAR tracks (hierarchy level 0), with each one’s id, name, and resident population.
curl -X POST https://api.clearinitiative.io/graphql \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"{ locations(level: 0) { id name population } }"}'
You’ll get back an array of Location objects. Grab the id of a country that interests you — you’ll feed it into the next query.
level walks the hierarchy: 0 = country, 1 = state/province, 2 = city, and so on. Pass a country’s id to location(id: …) and request children to drill down a level at a time.
5. Slice by location
This is where it gets powerful. eventsByLocation returns every event whose origin, destination, or general location falls within a location and all of its descendants — so one country id gives you everything happening anywhere inside that country. Drop in the id from the previous step:
curl -X POST https://api.clearinitiative.io/graphql \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"query($loc: String!) { eventsByLocation(locationId: $loc) { id title severity types generalLocation { name level } } }","variables":{"loc":"YOUR_LOCATION_ID"}}'
Each Event comes back with a severity from 1 (low) to 5 (severe), its disaster-type types tags, and the place it’s bound to. From any event you can follow the graph further — ask for its signals to see the raw observations underneath, or its alerts to see what was escalated from it.
The plain events, signals, and alerts lists are scoped to a team. If you’re not an admin, pass a teamId for a team you belong to (find yours via the myTeams query). The …ByLocation queries shown here have no such requirement, which is why they’re the easiest place to start.
Where to go next
You now know the shape of the graph and how to authenticate, query, and slice by location. From here:
Browse the full Queries and Types reference below — it’s auto-generated from the live schema, so it’s always current.
Open the GraphQL Sandbox to build queries interactively with field autocomplete.
Read the Authentication section for the browser/cookie flow if you’re building a web app rather than a server integration.
Welcome to the CLEAR API - your gateway to humanitarian intelligence.
The CLEAR API gives you programmatic access to signals, events, alerts, data sources, and geographic location data through a single GraphQL endpoint. Whether you’re building a monitoring dashboard, integrating alerts into your workflow, or analysing humanitarian patterns, this API has you covered.
Everything here is accessible via GraphQL at /graphql. You send a query describing exactly the data you want, and you get back precisely that — nothing more, nothing less.
Look up an alert by ID. Requires authentication. Non-admins can only access alerts within their team scope.
id: String!
signals
[Signal!]!
List signals. Requires authentication. includeDummy defaults to false.
teamId: StringincludeDummy: Boolean
signal
Signal
Look up a signal by ID. Requires authentication. Non-admins can only access signals within their team scope.
id: String!
signalsByLocation
[Signal!]!
List signals by location. Returns all signals whose origin, destination, or general location is within the given location (including descendants).
locationId: String!
events
[Event!]!
List events. Requires authentication. includeDummy defaults to false.
teamId: StringincludeDummy: Boolean
event
Event
Look up an event by ID. Requires authentication. Non-admins can only access events within their team scope.
id: String!
publicEvent
PublicEvent
Resolve a public share-link to its cached event snapshot. No auth —
the (eventId, token) pair from the URL is the gate, and the snapshot
only contains the safe fields enumerated on `PublicEvent`. Returns
null when the Redis cache has no entry for that pair (link expired,
revoked, or evicted under memory pressure — caller treats all three
the same).
eventId: String!token: String!
existingPublicEventLink
CreatePublicEventLinkResult
Look up the most recently-minted public share link for an event,
if one still exists in the cache. The Share modal calls this on
open so it can reuse an existing link rather than minting a fresh
token every time. Returns null when no live link exists — the
caller then mints one via `createPublicEventLink`. Requires
`requireContentReader` (admin / analyst / viewer); pending users
are blocked.
eventId: String!
eventsByLocation
[Event!]!
List events by location. Returns all events whose origin, destination, or general location is within the given location (including descendants).
locationId: String!
alertsByLocation
[Alert!]!
List alerts by location. Returns all alerts whose event's location is within the given location (including descendants).
locationId: String!status: AlertStatus
dataSources
[DataSource!]!
List all data sources.
dataSource
DataSource
Look up a data source by ID.
id: String!
locations
[Location!]!
List locations, optionally filtered by hierarchy level (0 = country, 1 = state, etc.).
level: Int
location
Location
Look up a location by ID.
id: String!
notifications
[Notification!]!
List notifications, optionally filtered by status.
status: NotificationStatus
notification
Notification
Look up a notification by ID.
id: String!
featureFlags
[FeatureFlag!]!
List all feature flags.
featureFlag
FeatureFlag
Look up a feature flag by its unique key.
key: String!
disasterTypes
[DisasterType!]!
List all disaster type classifications (flat list of level-3 rows).
disasterType
DisasterType
Look up a disaster type by ID.
id: String!
disasterTypeHierarchy
[DisasterLevel1!]!
List disaster types grouped into the 3-level hierarchy (level1 > level2 > level3).
locationMetadata
[LocationMetadata!]!
List metadata entries for a location, optionally filtered by type.
By default only the CURRENT value is returned (validTo is null). Pass
current: false to include the full history.
locationId: String!type: Stringcurrent: Boolean
allLocationMetadata
[LocationMetadata!]!
List every locationMetadata entry of a given type across all locations.
By default only current values. Pass current: false for the full history.
type: String!current: Boolean
locationMetadataHistory
[LocationMetadata!]!
History of a (location, type) pair — newest first. Includes the current
row plus every superseded one.
locationId: String!type: String!
myApiKeys
[ApiKey!]!
List all API keys belonging to the authenticated user. Requires authentication.
myOrganisations
[Organisation!]!
List organisations the authenticated user belongs to.
organisation
Organisation
Look up an organisation by ID. Requires membership or global admin.
id: String!
myTeams
[Team!]!
List teams the authenticated user belongs to.
team
Team
Look up a team by ID. Requires membership or global admin.
id: String!
pendingInvites
[Invitation!]!
List pending invitations for an organisation. Requires org admin.
organisationId: String!
invitationByToken
InvitationInfo
Look up an invitation by token (public — used on accept-invite page).
token: String!
myAlertSubscriptions
[AlertSubscription!]!
List the authenticated user's alert subscriptions.
alertSubscriptionsByLocation
[AlertSubscription!]!
List all alert subscriptions for a location (admin only).
locationId: String!
crises
[Crisis!]!
List all crises.
crisis
Crisis
Look up a crisis by ID.
id: String!
alertsPage
AlertsPage!
Paginated alerts feed with severity / location / type / date filters and
explicit ordering. Use this instead of `alerts(...)` when the UI needs
pages or a totalCount.
input: AlertsPageInput
eventsPage
EventsPage!
Paginated events feed (same filter shape as alertsPage, plus event-only
options). Honours teamId as a location-scope filter.
input: EventsPageInput
signalsPage
SignalsPage!
Paginated signals feed with source-based filtering.
input: SignalsPageInput
entityStats
EntityStats!
Cross-entity stats query — returns a total plus optional buckets grouped
by type / severity / day / week / month. Filter shape mirrors the page
queries so a "current view" can compute its own counts.
input: EntityStatsInput!
nominatimCacheEntry
NominatimCacheEntry
Look up a cached Nominatim geocoder response by query hash. Returns
null when the entry is missing or expired (admin/pipeline only).
queryHash: String!
activityLogs
[ActivityLog!]!
Paginated activity log. Admin only. Newest first.
filter: ActivityLogFilterInputlimit: Intoffset: Int
activityStats
ActivityStats!
Aggregated activity counts + per-user + per-day breakdown for the
admin dashboard. Admin only. Default window: last 30 days.
from: DateTimeto: DateTime
userEngagement
UserEngagementMetrics!
Point-in-time user-engagement summary: DAU, WAU, MAU, and the
DAU/MAU stickiness ratio. Derived from auth.login activity. Admin
only. `asOf` defaults to NOW(); pass a historical timestamp to
compute as-of that date.
asOf: DateTime
dauSeries
[DauPoint!]!
Daily Active Users time series — one point per UTC date in the
window. Admin only. Days with zero logins are omitted; the dashboard
can backfill them client-side when plotting.
from: DateTime!to: DateTime!
mauSeries
[MauPoint!]!
Monthly Active Users time series — one point per UTC calendar
month in the window. Admin only.
from: DateTime!to: DateTime!
pipelineCountries
[PipelineCountry!]!
The countries the CLEAR pipeline publishes a Situation Analysis for, with
each Country's bounding box. The scheduled publisher reads this to know which
countries to run. Requires authentication.
translations
[TranslationRow!]!
Translation rows currently stored for an entity, one per locale.
Admin/pipeline only. Used by clear-pipeline to compare stored source
hashes against the canonical row and decide which fields to re-translate.
entityType: String!entityId: String!
translationCoverage
[TranslationCoverage!]!
Per-(entityType, locale) translation coverage snapshot for the
admin dashboard. Admin only. Each row reports canonicalCount (how
many entities of that type exist) and translatedCount (how many
have a translation row for that locale). Coverage = translated /
canonical.
entitiesMissingTranslation
[ID!]!
IDs of entities of the given type that have NO translation row
for the given locale. Admin/pipeline only. Lets the backfill
driver enqueue only entities the worker would actually translate,
instead of relying on per-task staleness diffs to no-op thousands
of already-current rounds. Stale rows (row exists but hashes are
out of date) are NOT returned here — they're rare and handled by
the per-entity enrichment hooks.
entityType: String!locale: String!
Mutations
Name
Returns
Description
createApiKey
CreateApiKeyPayload!
Create a new API key for the authenticated user.
input: CreateApiKeyInput!
revokeApiKey
ApiKey!
Revoke an API key by ID. Only the key owner or an admin can revoke.
id: String!
createPublicEventLink
CreatePublicEventLinkResult!
Mint a Redis-backed share token for an event. The snapshot of the
event's safe-to-share fields is stored under a key derived from
the eventId + token and lives for `ttlDays` days (default 30, max
90). Anyone who has the resulting URL can read the snapshot via
the `publicEvent(eventId, token)` query. Caller must be able to
read the event normally (admin / analyst / viewer); pending users
are blocked.
input: CreatePublicEventLinkInput!
revokePublicEventLink
Boolean!
Invalidate a public share token by deleting the cached snapshot.
Idempotent — revoking a missing key returns true. Caller must be
an approved user; ownership of the original link is not checked
because the link is by definition unauthenticated and the only
state to delete is the cache entry itself.
eventId: String!token: String!
createDevUser
CreateDevUserResult!
Provision a developer account from an approved waitlist application.
Creates the user, mints an initial API key (no expiry), issues a
long-lived set-password verification token, and sends the welcome
email. Requires global `admin`. The CRM write-back is the caller's
responsibility.
input: CreateDevUserInput!
rotateDevUserApiKey
RotateDevUserApiKeyResult!
Revoke every active API key for a dev user and issue a fresh one.
Notifies the user by email. Requires global `admin`.
userId: String!
approveUser
ApproveUserResult!
Approve a self-signed-up user. Flips their role from `pending`
to `viewer` (granting read access to signals / events / alerts /
crises) and moves their CRM contact from the prospects collection
into the approved collection — which fires Exponential's welcome
automation. The local role flip is authoritative; CRM updates are
best-effort and surface as fields on the result so the admin UI
can offer a retry. Requires global `admin`.
userId: String!
requestEmailVerification
Boolean!
Request an email verification link for the authenticated user.
verifyEmail
Boolean!
Verify email using a token from the verification link.
token: String!
updateProfile
User!
Update the authenticated user's profile and notification preferences.
input: UpdateProfileInput!
createAlert
Alert!
Create an alert from an event, notifying subscribers.
input: CreateAlertInput!
updateAlert
Alert!
Update an existing alert.
id: String!input: UpdateAlertInput!
deleteAlert
Boolean!
Delete an alert.
id: String!
archiveStaleAlerts
ArchiveStaleAlertsResult!
Archive published alerts whose event.lastSignalCreatedAt is older than
olderThanDays (default: 14). Sets alerts.status to 'archived'. Admin or
pipeline only. Returns the number of rows affected.
olderThanDays: Int
createSignal
Signal!
Create a signal from a data source.
input: CreateSignalInput!
createManualSignal
Signal!
Create a manual signal from a field officer, partner, or government source.
Persists the signal and sends it to the pipeline for event grouping and auto-escalation.
input: CreateManualSignalInput!
updateSignalSeverity
Signal!
Update a signal's severity score.
id: String!severity: Int!
updateSignalGeoparsedData
Signal!
Attach the clear-pipeline geoparser's result to an existing signal.
Used for the manual-signal flow, where the signal is created via
createManualSignal before the pipeline has a chance to run the geoparser.
Stores the structured candidate verbatim; does not change locationId.
Admin/pipeline only.
id: String!geoparsedData: JSON!
deleteSignal
Boolean!
Delete a signal.
id: String!
createEvent
Event!
Create a new event from signals.
input: CreateEventInput!
updateEvent
Event!
Update an existing event.
id: String!input: UpdateEventInput!
deleteEvent
Boolean!
Delete an event.
id: String!
escalateEvent
EventEscalation!
Escalate an event: creates an alert (published) and records the user escalation.
If the event already has a published alert, just records the user escalation.
teamId (optional) admits a team_admin or field_coordinator on that team
even without a global admin/analyst role — purely an authorisation hint,
not stored on the event.
eventId: String!userId: String!teamId: String
createDataSource
DataSource!
Create a new data source.
input: CreateDataSourceInput!
updateDataSource
DataSource!
Update an existing data source.
id: String!input: UpdateDataSourceInput!
deleteDataSource
Boolean!
Delete a data source.
id: String!
createLocation
Location!
Create a new location.
input: CreateLocationInput!
ensureCountryLocation
Location!
Idempotently resolve a level-0 Country location by exact name, creating it
with a bounding-box MULTIPOLYGON geometry if absent (admin/pipeline only).
bbox is [minLng, minLat, maxLng, maxLat]. Returns the (found or created)
Country — doubles as the pipeline's name→id resolution.
name: String!bbox: [Float!]!
updateLocation
Location!
Update an existing location.
id: String!input: UpdateLocationInput!
deleteLocation
Boolean!
Delete a location.
id: String!
updateLocationGeometry
Location!
Replace a location's geometry with the given GeoJSON (admin/pipeline only).
id: String!geometry: GeoJSON!
updateLocationPopulation
Location!
Set a location's cached population (admin/pipeline only).
id: String!population: String!
updateCrisisPopulation
Crisis!
Set a crisis's populationAffected + populationInArea (admin/pipeline only).
id: String!input: UpdateCrisisPopulationInput!
upsertLocationMetadata
LocationMetadata!
Create or update a location's metadata entry for a given type (admin/pipeline only).
Upsert keyed by (locationId, type).
input: UpsertLocationMetadataInput!
upsertLocationMetadataBatch
[LocationMetadata!]!
Bulk-upsert multiple (locationId, type, data) rows in a single call (admin/pipeline only).
Returns the resulting rows. Rows whose locationId doesn't exist are skipped silently.
inputs: [UpsertLocationMetadataInput!]!
deleteLocationMetadata
Boolean!
Delete a location's metadata entry for a given type (admin only).
locationId: String!type: String!
findOrCreateLandmarkL4
FindOrCreateLandmarkL4Result!
Find an existing level-4 location matching a geoparsed candidate, or
create one. Used by the clear-pipeline geoparser to promote a landmark
hit (e.g., "Nyala Airport") into a reusable A4 instead of letting the
resolver invent a fresh point-location for every signal. When sourceLat
and sourceLng are provided, the resolver verifies that the candidate's
containing A2 matches the source coord's containing A2 — on mismatch it
aborts with abortedReason="different_a2" so the caller can fall back to
source coords. Admin/pipeline only.
input: FindOrCreateLandmarkL4Input!
upsertNominatimCache
NominatimCacheEntry!
Upsert a Nominatim geocoder cache entry (admin/pipeline only).
Replaces any existing row with the same queryHash, resetting the TTL.
input: UpsertNominatimCacheInput!
setFeatureFlag
FeatureFlag!
Set the enabled state of a feature flag, identified by its string key.
Upserts the row so the same call works whether the key is already present.
Admin only — toggling features is an org-wide change, not a per-user
preference. Returns the persisted flag so callers can update local state
without an extra round-trip.
key: String!enabled: Boolean!
createNotification
Notification!
Create a notification for a user.
input: CreateNotificationInput!
createBulkNotifications
Int!
Create notifications for multiple users at once. Returns the count of notifications created.
input: CreateBulkNotificationsInput!
notifyAlertSubscribers
Int!
Notify all subscribers of a single alert (immediate frequency). Matches on event types and locations.
input: AlertNotifyInput!
notifyAlertDigest
Int!
Send a digest notification for multiple alerts to subscribers of the given frequency (daily/weekly/monthly).
input: AlertDigestInput!
deleteNotification
Boolean!
Delete a notification.
id: String!
markNotificationRead
Notification!
Mark a notification as read.
id: String!
markAllNotificationsRead
Boolean!
Mark all notifications as read for the authenticated user.
addFeedback
UserFeedback!
Add feedback (rating + optional text) to a signal or event.
input: AddFeedbackInput!
deleteFeedback
Boolean!
Delete your own feedback.
id: String!
addComment
UserComment!
Add a comment to a signal or event.
input: AddCommentInput!
replyToComment
UserComment!
Reply to an existing comment.
input: ReplyToCommentInput!
deleteComment
Boolean!
Delete your own comment.
id: String!
tagUsersInComment
UserComment!
Tag users in a comment.
commentId: String!userIds: [String!]!
createOrganisation
Organisation!
Create a new organisation. The creator becomes the first org_admin.
input: CreateOrganisationInput!
updateOrganisation
Organisation!
Update an existing organisation. Requires org_admin (or platform admin).
id: String!input: UpdateOrganisationInput!
addOrgMember
OrgMember!
Add a member to an organisation.
orgId: String!userId: String!role: OrgMemberRole
removeOrgMember
Boolean!
Remove a member from an organisation.
orgId: String!userId: String!
updateOrgMemberRole
OrgMember!
Change a member's role within an organisation. Requires the caller to be
a platform admin or an org_admin of the target organisation.
orgId: String!userId: String!role: OrgMemberRole!
deleteOrganisation
Boolean!
Delete an organisation and all its teams, members, and invitations. Requires global admin.
id: String!
createTeam
Team!
Create a new team within an organisation. Requires org_admin (or platform admin).
Set the locations a team is scoped to. Replaces all existing locations.
teamId: String!locationIds: [String!]!
setDefaultTeam
Team!
Set the authenticated user's default team (for frontend convenience).
teamId: String!
inviteUser
Invitation!
Invite a user to an organisation (and optionally a team). Sends invite email.
input: InviteUserInput!
acceptInvite
Boolean!
Accept an invitation. Creates user account if new, adds to org and team.
input: AcceptInviteInput!
cancelInvite
Boolean!
Cancel a pending invitation.
id: String!
resendInvite
Invitation!
Resend an invitation email (resets expiry to 7 days).
id: String!
requestPasswordReset
Boolean!
Request a password reset email (public, always returns true).
email: String!
resetPassword
Boolean!
Reset password using a token from the reset email.
token: String!newPassword: String!
subscribeToAlerts
AlertSubscription!
Subscribe to alerts for a specific type and location.
input: SubscribeToAlertsInput!
subscribeToAlertsBatch
[AlertSubscription!]!
Subscribe to alerts for multiple (location × alertType) combinations in a single call.
Returns the list of created subscriptions. Duplicates are skipped silently.
input: SubscribeToAlertsBatchInput!
updateAlertSubscription
AlertSubscription!
Update an existing alert subscription (channel, frequency, active).
id: String!input: UpdateAlertSubscriptionInput!
unsubscribeFromAlerts
Boolean!
Unsubscribe - deletes the subscription.
id: String!
createCrisisFromEvents
Crisis!
Create a new crisis from a list of event IDs. Links all provided events to the new crisis.
input: CreateCrisisFromEventsInput!
addEventToCrisis
EventCrisis!
Add an existing event to an existing crisis. Idempotent - returns the existing link if one already exists.
crisisId: String!eventId: String!
removeEventFromCrisis
Crisis
Remove an event from a crisis. Recomputes populationAffected from the
remaining events and dispatches the enrichment task so title/summary get
regenerated to reflect the new event set. If the event being removed is
the LAST event, deletes the crisis entirely and returns null. Otherwise
returns the updated crisis (title/summary still show pre-removal values
until the async enrichment task completes).
crisisId: String!eventId: String!
updateCrisisTitle
Crisis!
Edit a crisis's title in place. Any authenticated user. Pass an empty
string to clear the field.
id: String!title: String!
updateCrisisDescription
Crisis!
Edit the human-facing description on a crisis. The crisis's summary
column stores JSON of the form description+tldr — this mutation updates
just the description key and preserves any existing tldr bullets (which
the LLM enrichment task generates). Any authenticated user. Pass an
empty string to clear the description without disturbing the tldr.
id: String!description: String!
deleteCrisis
Boolean!
Delete a crisis. Cascades the eventCrises join rows, user feedback,
and user comments via the FK constraints. Any authenticated user.
id: String!
addCrisisAttachments
Crisis!
Append S3 keys to a crisis's attachments list. Idempotent — keys
already present in the list are skipped silently. Returns the updated
crisis with the new list.
id: String!keys: [String!]!
removeCrisisAttachment
Crisis!
Remove an S3 key from a crisis's attachments list. Does NOT delete
the underlying S3 object (operators can clean those up separately).
Returns the updated crisis.
id: String!key: String!
setCrisisNeedsAnalysis
Crisis!
Set the LLM-generated NRC SAF needs analysis inside the crisis's
needs JSONB. Merges generalSummary and sector keys into the existing
object so other keys on needs are preserved. Admin/pipeline only.
Upsert one or more per-locale translation rows for an event,
crisis, or location. The translated data blob mirrors the canonical
entity's JSON shape per locale. Admin/pipeline only.
input: UpsertTranslationsInput!
Types
All types in the schema, auto-generated from the running server.
DateTimescalar
ISO 8601 date-time string (e.g. 2024-01-15T09:30:00.000Z).
GeoJSONscalar
JSONscalar
Arbitrary JSON value — objects, arrays, strings, numbers, booleans, or null.
Uploadscalar
File upload scalar (via graphql-upload).
AlertOrderByenum
Value
Description
CREATED_DESC
Newest first by event.firstSignalCreatedAt.
CREATED_ASC
Oldest first by event.firstSignalCreatedAt.
SEVERITY_DESC
Highest event severity first.
SEVERITY_ASC
Lowest event severity first.
AlertStatusenum
Publication status of an alert.
Value
Description
draft
—
published
—
archived
—
Channelenum
Notification channel for alert subscriptions.
Value
Description
email
—
sms
—
DetectionStatusenum
Processing status of a detection (retained for potential future use).
Value
Description
raw
—
processed
—
ignored
—
EntityKindenum
Value
Description
signal
—
event
—
alert
—
EventOrderByenum
Value
Description
LAST_SIGNAL_DESC
Newest signal first (lastSignalCreatedAt).
LAST_SIGNAL_ASC
Oldest signal first (lastSignalCreatedAt).
CREATED_DESC
Newest first by firstSignalCreatedAt.
CREATED_ASC
Oldest first by firstSignalCreatedAt.
SEVERITY_DESC
—
SEVERITY_ASC
—
Frequencyenum
How often a user receives alert notifications.
Value
Description
immediately
—
daily
—
weekly
—
monthly
—
InvitationStatusenum
Status of an invitation.
Value
Description
pending
—
accepted
—
expired
—
NotificationStatusenum
Value
Description
PENDING
—
DELIVERED
—
FAILED
—
READ
—
OrgMemberRoleenum
Role within an organisation.
Value
Description
org_admin
—
member
—
SignalOrderByenum
Value
Description
PUBLISHED_DESC
Newest first by publishedAt.
PUBLISHED_ASC
Oldest first by publishedAt.
SEVERITY_DESC
—
SEVERITY_ASC
—
StatsGroupByenum
Value
Description
none
Single bucket — just `total`. Use this for "how many X" queries.
type
Group by event/signal type (event.types[] is unnested; signals use
their source name as the type proxy).
severity
Group by integer severity (1-5).
day
Group by day / week / month of the entity's primary timestamp.
Buckets are returned with ISO-8601 keys (`YYYY-MM-DD`, `YYYY-Www`,
`YYYY-MM`).
week
—
month
—
TeamMemberRoleenum
Role within a team.
Value
Description
team_admin
—
field_coordinator
—
team_member
—
AcceptInviteInputinput
Field
Type
Description
token
String!
—
name
String!
—
password
String!
—
ActivityLogFilterInputinput
Filter for the paginated activityLogs query.
Field
Type
Description
userId
String
—
actionPrefix
String
Action prefix match — e.g. 'crisis.' returns all crisis-related rows.
Provide exactly one of eventId, signalId, or crisisId.
signalId
String
—
crisisId
String
—
comment
String!
—
tagUserIds
[String!]
User IDs to tag in the comment.
AddFeedbackInputinput
Field
Type
Description
eventId
String
Provide exactly one of eventId, signalId, or crisisId.
signalId
String
—
crisisId
String
—
rating
Int!
Rating from 1 to 5.
text
String
Optional textual feedback.
AlertDigestInputinput
Field
Type
Description
alertIds
[String!]!
List of alert IDs to include in the digest.
frequency
String!
Frequency: daily, weekly, or monthly.
AlertNotifyInputinput
Field
Type
Description
alertId
String!
Alert ID to notify subscribers about (uses immediate frequency).
AlertsPageInputinput
Field
Type
Description
limit
Int
Page size — clamped to [1, 100]. Default 25.
offset
Int
Zero-based row offset. Default 0.
orderBy
AlertOrderBy
—
status
AlertStatus
—
teamId
String
Apply a team's location-scope filter to the underlying events.
locationId
String
Restrict to alerts whose event sits under this location (or any of
its descendants).
eventTypes
[String!]
Glide codes — alert event must contain at least one of these in its
`types` array. Case-sensitive.
severityMin
Int
Inclusive lower bound on event severity (1-5).
severityMax
Int
Inclusive upper bound on event severity (1-5).
from
DateTime
Filter on event.firstSignalCreatedAt — inclusive.
to
DateTime
Filter on event.firstSignalCreatedAt — inclusive.
includeDummy
Boolean
Hide isDummy events when false (default).
CreateAlertInputinput
Field
Type
Description
eventId
String!
The event ID to create an alert from.
status
AlertStatus
—
CreateApiKeyInputinput
Input for creating a new API key.
Field
Type
Description
name
String!
A descriptive name for this key (e.g. my-app-prod).
expiresAt
DateTime
Optional expiration date. Omit for a key that never expires.
CreateBulkNotificationsInputinput
Field
Type
Description
userIds
[String!]!
List of user IDs to notify.
message
String!
—
notificationType
String!
—
actionUrl
String
—
actionText
String
—
CreateCrisisFromEventsInputinput
Field
Type
Description
title
String
—
summary
String
—
severity
Float!
—
locationId
String
—
needs
JSON!
Needs as JSON.
eventIds
[String!]!
Event IDs to link to the newly created crisis (must not be empty).
teamId
String
Team the crisis is being filed under. When present, the caller may be
a team-level team_admin or field_coordinator on that team instead of a
platform admin/analyst. Purely an authorisation hint — the crisis itself
has no team column; team affiliation is derived from location scope.
Ignored for platform-level callers.
CreateDataSourceInputinput
Field
Type
Description
name
String!
—
type
String!
—
isActive
Boolean
—
baseUrl
String
—
infoUrl
String
—
CreateDevUserInputinput
Input for `createDevUser`.
Field
Type
Description
email
String!
The dev's email address — also the dedup key against existing users.
name
String!
Display name shown in the welcome email and in the User row.
keyName
String
Optional descriptive label for the first API key. Defaults to "Initial dev key".
CreateEventInputinput
Field
Type
Description
signalIds
[String!]!
—
title
String
—
description
String
—
descriptionSignals
JSON
—
validFrom
String!
—
validTo
String!
—
firstSignalCreatedAt
String!
—
lastSignalCreatedAt
String!
—
originId
String
—
destinationId
String
—
locationId
String
—
types
[String!]!
—
severity
Int
Severity score (1–5). Aggregated from signal severities.
populationAffected
String
—
populationDisplaced
String
Estimated population displaced (BigInt as string).
casualties
Int
Aggregated casualties for the event (max across constituent signals).
rank
Float!
—
lat
Float
Latitude for automatic geo-resolution (resolves to nearest location in hierarchy).
lng
Float
Longitude for automatic geo-resolution.
teamId
String
Team the event is being filed under. When present, the caller may be
a team-level team_admin or field_coordinator on that team instead of a
platform admin/analyst. Purely an authorisation hint — the event itself
has no team column; team affiliation is derived from location scope.
Ignored for platform-level callers.
CreateLocationInputinput
Field
Type
Description
geoId
Int
—
osmId
String
—
pCode
String
—
name
String!
—
level
Int!
—
parentId
String
—
CreateManualSignalInputinput
Field
Type
Description
sourceId
String!
Data source ID (must be field_officer, partner, or government type).
title
String!
—
description
String!
—
severity
Int
Severity score (1–5).
url
String
URL or reference link.
mediaUrls
[String!]
Media URLs (pre-uploaded via /api/upload endpoint).
media
[Upload!]
Media files (direct upload via graphql-upload, alternative to mediaUrls).
locationId
String
—
originId
String
—
destinationId
String
—
lat
Float
Latitude for automatic geo-resolution.
lng
Float
Longitude for automatic geo-resolution.
metadata
JSON
Arbitrary internal metadata stored in rawData (e.g. notes, recommendAlert).
Not surfaced in the UI - use freely without schema changes.
teamId
String
Team the signal is being filed under. When present, the caller may be
a team-level team_admin or field_coordinator on that team instead of a
platform admin/analyst. Purely an authorisation hint — the signal itself
has no team column; team affiliation is derived from location scope.
Ignored for platform-level callers.
CreateNotificationInputinput
Field
Type
Description
userId
String!
—
message
String!
—
notificationType
String!
—
actionUrl
String
—
actionText
String
—
CreateOrganisationInputinput
Fields for creating a new organisation.
Field
Type
Description
name
String!
Display name for the organisation.
slug
String!
URL-friendly identifier. Must be unique.
CreatePublicEventLinkInputinput
Input for the `createPublicEventLink` mutation.
Field
Type
Description
eventId
String!
The event to share. Caller must be able to read it via the
normal `event(id)` resolver — i.e. `requireContentReader`
passes.
ttlDays
Int
Snapshot lifetime in days. Defaults to 30, capped at 90. Smaller
values produce shorter URLs by reducing the impact of any future
URL-history scraping.
CreateSignalInputinput
Field
Type
Description
sourceId
String!
—
externalId
String
Stable upstream identifier for idempotent ingestion. If a signal with
the same (sourceId, externalId) already exists, createSignal returns the
existing row instead of creating a duplicate. Recommended prefix scheme:
"dataminr:{alertId}", "gdacs:{eventid}", "acled:{event_id_cnty}".
rawData
JSON!
—
publishedAt
String!
—
collectedAt
String
—
url
String
—
title
String
—
description
String
—
severity
Int
Severity score (1–5). From data source or estimated by pipeline.
casualties
Int
Reported casualties for the signal.
media
[String!]
Media URLs (source URLs for images, videos, etc.).
originId
String
—
destinationId
String
—
locationId
String
—
lat
Float
Latitude for automatic geo-resolution (resolves to nearest location in hierarchy).
lng
Float
Longitude for automatic geo-resolution.
geoparsedData
JSON
Optional output of clear-pipeline's text-based geoparser. Additive
enrichment, stored verbatim for downstream comparison against the
source's coords. Schema documented on the signals model.
pointName
String
Human-readable name to use when the resolver has to create a new L4
point location from `lat`/`lng`. Typically the geoparser's
top extracted candidate suffixed with " (unresolved)" when the
Nominatim lookup failed, so audit views show `al-Obeid (unresolved)`
instead of the signal's full paragraph. Ignored when `locationId`
is supplied. When omitted, the resolver falls back to a coord-based
label like `Point 15.6280, 30.2156`.
CreateTeamInputinput
Field
Type
Description
organisationId
String!
—
name
String!
—
slug
String!
—
description
String
—
EntityStatsInputinput
Field
Type
Description
entity
EntityKind!
—
groupBy
StatsGroupBy
—
teamId
String
—
locationId
String
—
eventTypes
[String!]
—
severityMin
Int
—
severityMax
Int
—
from
DateTime
—
to
DateTime
—
includeDummy
Boolean
—
EventsPageInputinput
Field
Type
Description
limit
Int
—
offset
Int
—
orderBy
EventOrderBy
—
teamId
String
—
locationId
String
—
eventTypes
[String!]
—
severityMin
Int
—
severityMax
Int
—
from
DateTime
Filter on event.firstSignalCreatedAt — inclusive.
to
DateTime
—
includeDummy
Boolean
—
FindOrCreateLandmarkL4Inputinput
Input for findOrCreateLandmarkL4. Drives geoparser-based L4 promotion
in the signal-ingestion pipeline.
Field
Type
Description
name
String!
Display name to use when creating a new L4 (e.g., 'Nyala Airport').
Reuse for kind='landmark' is keyed on a case-insensitive match of this
field within the candidate's containing A2.
lat
Float!
Candidate latitude (from the geocoder).
lng
Float!
Candidate longitude (from the geocoder).
kind
String!
'landmark' or 'admin'. Drives the reuse strategy: landmarks reuse by
exact name, admins reuse by proximity (≤100m) within the same A2.
sourceLat
Float
Source coordinate's latitude. When provided, the resolver verifies the
candidate's A2 matches the source's A2 — a mismatch aborts the promotion.
sourceLng
Float
Source coordinate's longitude. See sourceLat.
InviteUserInputinput
Field
Type
Description
email
String!
—
organisationId
String!
—
role
String
Organisation role: org_admin, member (default: member).
teams
[TeamAssignmentInput!]!
Team assignments — at least one team is required. Each entry grants the
invitee membership in that team with the given role on acceptance.
LocaleTranslationInputinput
Per-locale payload accepted by upsertTranslations. data mirrors the
canonical entity's JSON shape exactly for the given locale — e.g. for
a crisis it carries the localized title/summary/scenarios/needs with
the same keys/nesting the English columns use.
Field
Type
Description
locale
String!
BCP-47 lowercased — 'ar', 'fr'. 'en' is rejected (canonical).
data
JSON!
Translated payload. Shape mirrors the canonical entity per type.
sourceHashes
JSON!
Per-field SHA-256 hashes of the canonical English source used to produce `data`. Stored so the pipeline can detect which canonical field changed and re-translate only that field on the next pass.
ReplyToCommentInputinput
Field
Type
Description
repliedToCommentId
String!
ID of the comment to reply to.
comment
String!
—
tagUserIds
[String!]
User IDs to tag in the reply.
SignalsPageInputinput
Field
Type
Description
limit
Int
—
offset
Int
—
orderBy
SignalOrderBy
—
teamId
String
—
locationId
String
—
sourceNames
[String!]
Restrict to signals whose source name is in this list (e.g. ["acled","dataminr"]).
severityMin
Int
—
severityMax
Int
—
from
DateTime
Filter on signal.publishedAt — inclusive.
to
DateTime
—
includeDummy
Boolean
—
SubscribeToAlertsBatchInputinput
Field
Type
Description
locationIds
[String!]!
One or more location IDs.
alertTypes
[String!]!
One or more disaster/event types (glideNumbers). A subscription is created for every (location × alertType) pair.
channel
Channel!
—
frequency
Frequency!
—
minSeverity
Int
Minimum event severity (1-5). Applied to all created subscriptions.
SubscribeToAlertsInputinput
Field
Type
Description
locationId
String!
—
alertType
String!
Disaster/event type (glideNumber from disaster_types, e.g. 'fl', 'eq').
channel
Channel!
—
frequency
Frequency!
—
minSeverity
Int
Minimum event severity (1-5) to notify on. Defaults to 1 (all alerts).
TeamAssignmentInputinput
One (team, role) assignment passed to inviteUser.
Field
Type
Description
teamId
String!
—
teamRole
TeamMemberRole!
—
UpdateAlertInputinput
Field
Type
Description
status
AlertStatus
—
UpdateAlertSubscriptionInputinput
Field
Type
Description
channel
Channel
—
frequency
Frequency
—
active
Boolean
—
minSeverity
Int
Minimum event severity (1-5).
UpdateCrisisPopulationInputinput
Field
Type
Description
populationAffected
String
Population directly affected by the events (BigInt as string).
populationInArea
String
Total population residing within the event admin areas (BigInt as string).
Estimated population displaced (BigInt as string).
casualties
Int
Aggregated casualties for the event (max across constituent signals).
rank
Float
—
UpdateLocationInputinput
Field
Type
Description
geoId
Int
—
osmId
String
—
pCode
String
—
name
String
—
level
Int
—
parentId
String
—
UpdateOrganisationInputinput
Fields for updating an existing organisation.
Field
Type
Description
name
String
New display name.
slug
String
New URL-friendly identifier.
isActive
Boolean
Set active/inactive status.
UpdateProfileInputinput
Field
Type
Description
name
String
—
phoneNumber
String
—
image
String
—
enableInAppNotification
Boolean
—
enableEmailNotification
Boolean
—
enableSMSNotification
Boolean
—
language
String
Preferred UI language code (BCP-47 / ISO 639-1, e.g. "en", "ar").
UpdateTeamInputinput
Field
Type
Description
name
String
—
slug
String
—
description
String
—
UpsertLocationMetadataInputinput
Field
Type
Description
locationId
String!
—
type
String!
Type string (e.g. "iom_dtm_displacement").
data
JSON!
JSON payload for this type.
UpsertNominatimCacheInputinput
Field
Type
Description
queryHash
String!
SHA-256 hex digest of `<endpoint>:<normalised_query>`. The caller is
responsible for computing this — the server doesn't re-hash.
query
String!
Raw query string for debugging / audit.
endpoint
String!
The Nominatim endpoint that produced this response.
responseJson
JSON!
Raw JSON response to cache. Stored verbatim.
status
String!
'ok' for a usable result, 'no_result' for an empty result set,
'error' when the geocoder returned an error response. Negative results
are cached so we don't re-ask the same dead question.
ttlSeconds
Int!
How long this entry should remain valid, in seconds. The server
computes `expires_at = NOW() + ttl_seconds`.
UpsertTranslationsInputinput
Field
Type
Description
entityType
String!
One of 'event' | 'crisis' | 'location' (case-insensitive).
entityId
String!
—
translations
[LocaleTranslationInput!]!
One entry per target locale. Each row is upserted independently.
ActivityCountsByActionobject
Field
Type
Description
login
Int!
—
signalCreateManual
Int!
—
eventCreate
Int!
—
alertCreate
Int!
—
crisisCreate
Int!
—
feedbackCreate
Int!
—
total
Int!
—
ActivityLogobject
A single user-initiated action recorded for analytics.
The created/affected row's id. Null for actions like login.
metadata
JSON
Per-action context (title, severity, etc.). Shape varies by action.
ipAddress
String
—
userAgent
String
—
createdAt
DateTime!
—
ActivityStatsobject
Aggregate counts and time-series for the admin dashboard.
Field
Type
Description
from
DateTime!
Window the stats cover, in ISO-8601. Mirrored back to the client so
a paginated dashboard can know what range its numbers are based on.
to
DateTime!
—
totals
ActivityCountsByAction!
Total event counts across the window, keyed by action.
byUser
[UserActivitySummary!]!
Per-user breakdown, ordered by total activity (desc), limited to
the top 50 most-active users in the window.
byDay
[DailyActivityCount!]!
Daily activity counts across the window (UTC dates).
Alertobject
An alert created from an event, distributed to subscribed users.
Field
Type
Description
id
String!
—
event
Event!
The event this alert was created from.
status
AlertStatus!
—
createdAt
DateTime!
When the alert row was first created.
updatedAt
DateTime!
Last time the alert row was updated (e.g. status transition).
userAlerts
[UserAlert!]!
Users who received this alert.
AlertsPageobject
Field
Type
Description
items
[Alert!]!
—
totalCount
Int!
—
hasMore
Boolean!
—
AlertSubscriptionobject
A user's subscription to alerts of a specific type at a specific location.
Field
Type
Description
id
String!
—
userId
String!
—
user
User!
—
location
Location!
—
alertType
String!
Disaster/event type to subscribe to (e.g. 'fl' for flood, 'eq' for earthquake).
active
Boolean!
—
minSeverity
Int!
Minimum event severity (1-5) to notify on. Alerts with event.severity < minSeverity are suppressed for this user.
channel
Channel!
—
frequency
Frequency!
—
createdAt
DateTime!
—
updatedAt
DateTime!
—
ApiKeyobject
A personal API key for programmatic access. The full key is only shown once at creation.
Field
Type
Description
id
String!
—
name
String!
Descriptive name you chose when creating the key.
prefix
String!
Short prefix for identification (e.g. sk_live_abc1).
expiresAt
DateTime
Optional expiration date. Expired keys are rejected automatically.
lastUsedAt
DateTime
When this key was last used to authenticate a request.
revokedAt
DateTime
When this key was revoked, if applicable. Revocation is permanent.
createdAt
DateTime!
—
updatedAt
DateTime!
—
ApproveUserResultobject
Result of the admin-only `approveUser` mutation. Flips a `pending`
user's role to `viewer` and moves the matching CRM contact from
the prospects collection into the approved collection, triggering
Exponential's welcome automation.
Field
Type
Description
user
User!
The approved user (with the new role).
crmMoved
Boolean!
True when the CRM-side list move completed cleanly. False means
the user is approved locally but the CRM record still sits in the
prospects list — the admin can retry from /portal/admin without
re-approving the user.
crmWarnings
[String!]!
Non-fatal CRM warnings, if any (e.g. profileType update failed
while the list swap succeeded). Empty on the happy path.
ArchiveStaleAlertsResultobject
Result of the archiveStaleAlerts bulk mutation.
Field
Type
Description
alertsArchived
Int!
—
CommentTagobject
A tag linking a user to a comment.
Field
Type
Description
user
User!
—
comment
UserComment!
—
CreateApiKeyPayloadobject
Returned only from createApiKey. Contains the full plaintext
key that will never be retrievable again.
Field
Type
Description
apiKey
ApiKey!
—
key
String!
The full API key. Copy this immediately — it cannot be retrieved later.
CreateDevUserResultobject
Result of the admin-only `createDevUser` mutation. The plaintext API
key is returned only here — it is never stored and cannot be retrieved
later. The admin UI surfaces it once so the operator can copy-paste it
in case the welcome email bounces.
Field
Type
Description
user
User!
The newly-provisioned user.
plaintextKey
String!
The full plaintext API key (sk_live_…). Save this immediately — it
will not be retrievable from the API after this response is read.
welcomeEmailSent
Boolean!
True when the welcome email was successfully handed off to the email provider.
setPasswordTokenIssued
Boolean!
True when a long-lived set-password verification token was successfully
issued. The welcome email contains a link that consumes the token.
CreatePublicEventLinkResultobject
Returned once from `createPublicEventLink`. The token is part
of the URL and not retrievable again — same one-time-show semantics
as `createApiKey`.
Field
Type
Description
token
String!
The plaintext token. Embedded in `url` for convenience.
url
String!
Pre-built /public/event/<eventId>/<token> URL on the frontend.
Hand this straight to the share UI.
expiresAt
DateTime!
Wall-clock expiry — when the cached snapshot will be dropped
from Redis (assuming it isn't evicted earlier or revoked).
Crisisobject
A crisis aggregates multiple events into a single coherent narrative.
Field
Type
Description
id
String!
—
title
String
—
summary
String
—
scenarios
JSON
Forward-looking scenarios generated by the LLM enrichment task.
Shape: { most_likely, best_case, worst_case, description }. Null until
the enrichment task runs.
severity
Float!
Severity score (aggregated from linked events).
generalLocation
Location
General location of the crisis.
needs
JSON!
Needs associated with the crisis (JSON structure).
populationAffected
String
Population directly affected by linked events (BigInt as string).
populationInArea
String
Total population residing within the admin areas of linked events (BigInt as string).
attachments
[String!]!
Supporting documents uploaded by users (reports, photos, PDFs).
Returned as presigned URLs — the underlying storage is S3 keys, which
the resolver converts at read time so links stay short-lived.
events
[Event!]!
Events that are part of this crisis.
feedbacks
[UserFeedback!]!
User feedback on this crisis.
comments
[UserComment!]!
User comments on this crisis.
DailyActivityCountobject
Field
Type
Description
date
String!
YYYY-MM-DD in UTC.
total
Int!
—
counts
ActivityCountsByAction!
—
DataSourceobject
An external data source that feeds signals into the system.
Field
Type
Description
id
String!
—
name
String!
—
type
String!
Source type identifier (e.g. satellite, sensor, manual).
isActive
Boolean!
—
baseUrl
String
Base URL of the data source API.
infoUrl
String
URL with more information about this source.
createdAt
DateTime!
—
updatedAt
DateTime!
—
signals
[Signal!]!
Signals collected from this data source.
DauPointobject
One day in a DAU time series.
Field
Type
Description
date
String!
ISO date (YYYY-MM-DD, UTC).
uniqueUsers
Int!
Number of distinct users who logged in on this date.
DisasterLevel1object
A level-1 category with its level-2 groups.
Field
Type
Description
name
String!
—
groups
[DisasterLevel2!]!
—
DisasterLevel2object
A level-2 group with its distinct classification codes.
Field
Type
Description
name
String!
—
codes
[String!]!
Classification codes belonging to this level-2 group (usually one).
subTypes
[DisasterType!]!
Level-3 sub-types under this level-2 group.
DisasterTypeobject
A disaster classification in a 3-level hierarchy (level1 > level2 > level3).
Events store arrays of codes (GLIDE or CLEAR IDs).
Buckets when groupBy != none. Empty when groupBy = none.
Eventobject
An event grouping related signals into a coherent narrative.
Field
Type
Description
id
String!
—
title
String
—
description
String
—
descriptionSignals
JSON
LLM-generated signal descriptions as JSON.
validFrom
DateTime!
—
validTo
DateTime!
—
firstSignalCreatedAt
DateTime!
—
lastSignalCreatedAt
DateTime!
—
originLocation
Location
Origin location of the event.
destinationLocation
Location
Destination location of the event.
generalLocation
Location
General location (when no origin/destination).
types
[String!]!
Event type tags.
severity
Int
Severity score (1–5). Aggregated from signal severities.
isDummy
Boolean!
Whether this is seed/demo data.
populationAffected
String
Estimated population affected.
populationDisplaced
String
Estimated population displaced by the event (BigInt as string).
casualties
Int
Aggregated casualties for the event (max across constituent signals).
rank
Float!
—
signals
[Signal!]!
Signals linked to this event.
alerts
[Alert!]!
Alerts created from this event.
feedbacks
[UserFeedback!]!
User feedback on this event.
comments
[UserComment!]!
User comments on this event.
escalations
[EventEscalation!]!
Escalations by users.
EventCrisisobject
Link between a crisis and an event.
Field
Type
Description
id
String!
—
crisisId
String!
—
eventId
String!
—
collectedAt
DateTime!
—
crisis
Crisis!
—
event
Event!
—
EventEscalationobject
Tracks a user escalating an event, optionally to a crisis.
Field
Type
Description
id
String!
—
user
User!
—
event
Event!
—
isCrisis
Boolean!
Whether this has been escalated to a crisis.
validFrom
DateTime!
—
validTo
DateTime!
—
EventsPageobject
Field
Type
Description
items
[Event!]!
—
totalCount
Int!
—
hasMore
Boolean!
—
FeatureFlagobject
A feature toggle that controls runtime behavior.
Field
Type
Description
id
Int!
—
key
String!
Unique key used to look up this flag (e.g. dark_mode).
enabled
Boolean!
—
updatedAt
DateTime!
—
FindOrCreateLandmarkL4Resultobject
Outcome of findOrCreateLandmarkL4.
Field
Type
Description
locationId
String
The resolved L4 id. Null when the same-A2 safety check aborts.
reused
Boolean!
True when the call resolved to an existing L4, false when a new one
was created. Meaningless when locationId is null.
pointType
String
Provenance tag of the resolved L4 ('landmark-geocoded', 'gps', etc).
Null when the call aborted without producing a row.
abortedReason
String
Set to 'different_a2' when the candidate and source coords resolve to
different containing A2s. Null on success.
Invitationobject
An invitation to join an organisation, with one or more team assignments.
Field
Type
Description
id
String!
—
email
String!
—
organisation
Organisation!
—
team
Team
Single team — legacy field, populated only for invitations created
before the multi-team join existed. New invitations use `teams`.
role
String!
Organisation role assigned on acceptance.
teamRole
String
Legacy single-team role. Use `teams` for new invitations.
teams
[InvitationTeam!]!
Team assignments granted to the invitee on acceptance. Empty list
means org-only access (no team).
expiresAt
DateTime!
—
acceptedAt
DateTime
—
invitedBy
User!
—
createdAt
DateTime!
—
status
InvitationStatus!
Computed from acceptedAt and expiresAt.
InvitationInfoobject
Public invitation info returned by token lookup (limited fields).
Field
Type
Description
id
String!
—
email
String!
—
organisationName
String!
—
teamName
String
Legacy single-team name (populated only for old invitations).
role
String!
—
teamRole
String
Legacy single-team role (populated only for old invitations).
teams
[InvitationInfoTeam!]!
Team assignments the invitee will be granted on acceptance.
expiresAt
DateTime!
—
status
InvitationStatus!
—
InvitationInfoTeamobject
One (team, role) assignment as returned by the public token lookup.
Field
Type
Description
teamId
String!
—
teamName
String!
—
teamRole
TeamMemberRole!
—
InvitationTeamobject
One (team, role) assignment attached to an invitation.
Field
Type
Description
team
Team!
—
teamRole
TeamMemberRole!
—
Locationobject
A geographic location in a hierarchy (country > state > city, etc.).
Field
Type
Description
id
String!
—
geoId
Int
GeoNames identifier.
osmId
String
OpenStreetMap identifier.
pCode
String
P-Code identifier.
name
String!
—
level
Int!
Hierarchy level: 0 = country, 1 = state/province, 2 = city, etc.
geometry
GeoJSON
Geometry as GeoJSON (Point or MultiPolygon).
parent
Location
Parent location in the hierarchy.
children
[Location!]!
Child locations one level below.
ancestorIds
[String!]!
IDs of all ancestor locations (parent, grandparent, etc.).
ancestors
[Location!]!
All ancestor locations (parent, grandparent, etc.).
population
String
Population residing within this location's geometry. Null for point locations or when not yet computed.
pointType
String
Provenance of this location's geometry. Notable values:
- 'landmark-geocoded': L4 created by the pipeline geoparser from a
landmark/place name resolved via Nominatim. The location's `name`
field is meaningful for display (e.g., 'Nyala Airport').
- 'gps' / 'source-gps' / 'centroid' / 'source-centroid': see schema
documentation on the Prisma model.
- null: legacy rows (most signal-title L4s from `createPointLocation`).
metadata
[LocationMetadata!]!
Per-type metadata (IOM DTM, INFORM, etc). Pass a type argument to filter.
By default only the current value is returned (validTo is null).
Pass current: false to include the full history.
type: Stringcurrent: Boolean
createdAt
DateTime!
When the row was first created.
updatedAt
DateTime!
Last write — useful for tracking admin polygon (re-)loads.
LocationMetadataobject
Arbitrary per-location metadata keyed by type. History is preserved:
writes close the current row (set validTo = now()) and insert a new one.
The CURRENT value for a (location, type) is the row where validTo is null.
Field
Type
Description
id
String!
—
location
Location!
—
type
String!
Free-form type string (e.g. "iom_dtm_displacement", "acaps_inform").
data
JSON!
Source-specific payload stored as JSON.
validFrom
DateTime!
When this value became current.
validTo
DateTime
When this value was superseded. Null means still current.
createdAt
DateTime!
—
updatedAt
DateTime!
—
MauPointobject
One month in a MAU time series.
Field
Type
Description
month
String!
ISO month (YYYY-MM, UTC).
uniqueUsers
Int!
Number of distinct users who logged in at least once during the
calendar month.
NominatimCacheEntryobject
A cached Nominatim-protocol geocoder response.
Field
Type
Description
id
String!
—
queryHash
String!
SHA-256 hex digest of `<endpoint>:<normalised_query>`.
query
String!
Raw query string (for debugging only).
endpoint
String!
The Nominatim endpoint that produced this response (e.g. 'search', 'reverse').
responseJson
JSON!
Raw JSON response from the geocoder.
status
String!
Lookup outcome: 'ok' / 'no_result' / 'error'.
fetchedAt
DateTime!
—
expiresAt
DateTime!
—
Notificationobject
Field
Type
Description
id
String!
—
user
User!
—
message
String!
—
notificationType
String!
—
actionUrl
String
—
actionText
String
—
status
NotificationStatus!
—
emailNotificationStatus
NotificationStatus
—
smsNotificationStatus
NotificationStatus
—
createdAt
DateTime!
—
updatedAt
DateTime!
—
Organisationobject
An organisation that owns teams and has members.
Field
Type
Description
id
String!
—
name
String!
—
slug
String!
URL-friendly identifier.
isActive
Boolean!
Whether this organisation is active. Inactive organisations are hidden from non-admin users.
createdAt
DateTime!
When this organisation was created.
updatedAt
DateTime!
When this organisation was last updated.
teams
[Team!]!
Teams belonging to this organisation.
members
[OrgMember!]!
Members of this organisation.
OrganisationUserobject
Links a user to an organisation with a role.
Field
Type
Description
id
String!
—
userId
String!
—
organisationId
String!
—
role
String!
—
OrgMemberobject
Links a user to an organisation with an org-level role.
Field
Type
Description
id
String!
—
user
User!
—
role
String!
Organisation-level role: org_admin or member.
createdAt
DateTime!
When this membership was created.
PipelineCountryobject
A country the CLEAR pipeline publishes a Situation Analysis for, with the
bounding box used to create its level-0 Country location. bbox order matches
ensureCountryLocation: [minLng, minLat, maxLng, maxLat].
Field
Type
Description
name
String!
—
bbox
[Float!]!
—
PublicEventobject
The slim, unauthenticated view of an event used for share-link
rendering. Deliberately a new type — not a slim wrapper around
`Event` — so the field set is auditable in one place and field-
selection can't accidentally leak signals, comments, alerts, or any
other gated data through the public surface.
Returned by the `publicEvent(eventId, token)` query when the
Redis-cached snapshot for that token is still alive. Cache TTL
defaults to 30 days; entries can be evicted earlier under memory
pressure, in which case the link expires and the user has to
request a new one.
Field
Type
Description
id
String!
—
title
String
Localised event title (resolved to the canonical English text
when the snapshot was taken — the public page is not locale-aware).
description
String
Localised event description (canonical English at snapshot time).
severity
Float
Severity score (1–5) at snapshot time.
validFrom
DateTime!
Window during which the event is considered valid.
validTo
DateTime!
—
types
[String!]!
Disaster type codes (e.g. `fl`, `pa`). The frontend resolves
these to display names via its own disaster-type catalogue.
primaryLocationName
String
Human-readable name of the event's primary location (general
→ origin → destination, first non-null).
primaryLocationCoords
[Float!]
`[lng, lat]` of the primary location's centroid when that
location has a Point geometry. Null for polygon-only locations —
the frontend hides the minimap in that case.
populationAffected
String
Stringified bigint (matches the authenticated `Event` field
shape). Null when unknown.
populationDisplaced
String
—
signalPoints
[PublicEventSignalPoint!]!
`[lng, lat]` for every Point location attached to the event's
constituent signals (origin / destination / general fields,
deduped by location id). Polygon-only signal locations are
omitted. Empty when no signals carry Point geometry — the
frontend hides the markers list in that case.
locationPopulation
String
Population of the event's administrative area, resolved by
walking the primary location's ancestor chain in A2 → A1 → A0
order (district → state → country) and picking the deepest non-
null. Mirrors the fallback the in-app event page uses so the
share card shows the same number. Stringified bigint; null when
no level along the chain has a population. See also
`locationPopulationLevel` and `locationPopulationName`.
locationPopulationLevel
Int
Level the population number came from: `2` (district), `1`
(state), `0` (country). Null when `locationPopulation` is
null.
locationPopulationName
String
Name of the location the population number is for (e.g. "South
Darfur"). Null when `locationPopulation` is null. Lets the
frontend label the figure with context — "Population of South
Darfur" reads more honestly than a bare number when we fell back
to a country-level figure.
locationIdp
String
Internally-displaced persons count for the event's admin area,
sourced from `locationMetadata(type = "iom_dtm_displacement")`.
Same A2 → A1 → A0 fallback as `locationPopulation`. Stringified
bigint; null when no displacement metadata exists for any level.
locationIdpLevel
Int
Level the IDP number came from. Null when `locationIdp` is null.
locationIdpName
String
Name of the location the IDP figure is for. Null when
`locationIdp` is null.
sharedAt
DateTime!
When the share link was minted.
expiresAt
DateTime!
Soft expiry — the Redis TTL the cached snapshot was written
with. The frontend uses this to render "Link expires in N days".
PublicEventSignalPointobject
One Point location attached to one of the event's signals.
Field
Type
Description
name
String
Display name of the location (e.g. "Al Fasher"). Often null
for raw point-locations like "Point 15.62, 30.21".
lng
Float!
Geographic longitude.
lat
Float!
Geographic latitude.
RotateDevUserApiKeyResultobject
Result of the admin-only `rotateDevUserApiKey` mutation.
Field
Type
Description
user
User!
The user whose key was rotated.
plaintextKey
String!
The fresh plaintext API key — same one-time-delivery rules as createDevUser.
notificationEmailSent
Boolean!
True when the rotation-notice email was successfully handed off.
Signalobject
A signal derived from a data source.
Field
Type
Description
id
String!
—
source
DataSource!
The data source this signal was collected from.
externalId
String
Stable upstream identifier (e.g. "dataminr:{alertId}"). Used to
deduplicate ingestion — (source, externalId) is unique.
publishedAt
DateTime!
—
collectedAt
DateTime!
—
url
String
—
title
String
—
description
String
—
severity
Int
Severity score (1–5). From data source or estimated by pipeline.
casualties
Int
Reported casualties for the signal. Sourced from ACLED's fatalities
field; for Dataminr, parsed from raw text via regex.
media
[String!]!
Media URLs (S3 keys for manual uploads, or source URLs for pipeline signals).
isDummy
Boolean!
Whether this is seed/demo data.
originLocation
Location
Origin location of the signal.
destinationLocation
Location
Destination location of the signal.
generalLocation
Location
General location (when no origin/destination).
events
[Event!]!
Events this signal is linked to.
feedbacks
[UserFeedback!]!
User feedback on this signal.
comments
[UserComment!]!
User comments on this signal.
SignalsPageobject
Field
Type
Description
items
[Signal!]!
—
totalCount
Int!
—
hasMore
Boolean!
—
StatsBucketobject
Field
Type
Description
key
String!
Bucket label — depends on groupBy: glide code, severity number as
string, or ISO date/week/month.
count
Int!
—
Teamobject
A team within an organisation, scoped to specific locations.
Field
Type
Description
id
String!
—
name
String!
—
slug
String!
URL-friendly identifier, unique within the organisation.
description
String
—
organisation
Organisation!
The organisation this team belongs to.
members
[TeamMember!]!
Members of this team.
locations
[Location!]!
Locations this team is scoped to. Empty means global monitoring.
createdAt
DateTime!
—
updatedAt
DateTime!
—
TeamMemberobject
Links a user to a team with a team-level role.
Field
Type
Description
id
String!
—
user
User!
—
role
String!
Team-level role: lead, analyst, or viewer.
createdAt
DateTime!
—
TranslationCoverageobject
Per-(entity_type, locale) coverage snapshot used by the admin
dashboard to see how much of the catalog has been translated.
- canonicalCount: total entities of this type that *could* be
translated (i.e. exist in the canonical table).
- translatedCount: number with a row in the translations sidecar
for this locale.
The fraction translatedCount / canonicalCount is the live coverage
for that (type, locale) cell — anything < 1.0 means the next read of
one of the missing entities by a user on that locale will fall back
to canonical English (and trigger the lazy-on-read enqueue, see
utils/translation-loader.ts).
Field
Type
Description
entityType
String!
—
locale
String!
—
canonicalCount
Int!
—
translatedCount
Int!
—
TranslationRowobject
A single translation row, returned by the admin/pipeline-only
translations(entityType, entityId) query so the pipeline can compare
stored source-hashes against the canonical row and decide which fields
(if any) need re-translating.
Field
Type
Description
locale
String!
—
data
JSON!
Translated payload, same shape as the canonical entity per type.
sourceHashes
JSON
Per-field SHA-256 hashes of the canonical English source that was
used to produce `data`. Null on rows written before hashes were
introduced — treat null as "all fields stale".
createdAt
DateTime!
—
updatedAt
DateTime!
—
UpsertTranslationsResultobject
Result of upserting one or more locale rows for a given entity. Carries
the locales that were written so the caller (typically clear-pipeline)
can confirm coverage without a follow-up read.
Field
Type
Description
entityType
String!
—
entityId
String!
—
locales
[String!]!
—
Userobject
A registered user with role-based access.
PII fields (`email`, `phoneNumber`, `role`, `isActive`) and the
private relation set (`alerts`, `notifications`, `organisations`,
`teamMemberships`, `feedbacks`, `comments`, `escalations`) are
gated server-side:
- PII: returned when caller IS the user, is a global admin, OR
shares at least one organisation with the user. Otherwise null
(PII) or empty array (private relations).
- Private relations: returned only when caller IS the user OR is
a global admin. Sharing an organisation does NOT grant access
to another member's inbox / comment history.
Schema makes these fields nullable so the gate can return null when
the caller is not authorised, instead of throwing — a logged-in
analyst browsing an event's comments shouldn't see a hard error on
the commenter's email.
Field
Type
Description
id
String!
—
email
String
—
name
String!
—
emailVerified
Boolean!
—
phoneNumber
String
—
image
String
—
role
String
User role: viewer, editor, or admin. Null when caller is not
authorised to see this user's role.
isActive
Boolean
Null when caller is not authorised to see this field.
language
String!
Preferred UI language code (BCP-47 / ISO 639-1, e.g. "en", "ar"). Defaults to "en".
enableInAppNotification
Boolean!
—
enableEmailNotification
Boolean!
—
enableSMSNotification
Boolean!
—
createdAt
DateTime!
—
updatedAt
DateTime!
—
alerts
[UserAlert!]!
Alerts received by this user. Empty for non-self / non-admin
callers.
notifications
[Notification!]!
Empty for non-self / non-admin callers.
defaultTeam
Team
The user's default team (last selected). Null for non-self /
non-admin callers.
organisations
[OrganisationUser!]!
Empty for non-self / non-admin callers.
teamMemberships
[TeamMember!]!
Empty for non-self / non-admin callers.
feedbacks
[UserFeedback!]!
Empty for non-self / non-admin callers.
comments
[UserComment!]!
Empty for non-self / non-admin callers.
escalations
[EventEscalation!]!
Empty for non-self / non-admin callers.
UserActivitySummaryobject
Field
Type
Description
user
User!
—
total
Int!
—
counts
ActivityCountsByAction!
—
UserAlertobject
Tracks an alert delivered to a user — view status.
Field
Type
Description
id
String!
—
user
User!
—
alert
Alert!
—
viewedAt
DateTime
When the user viewed this alert.
UserCommentobject
A user comment on a signal, event, or crisis, with reply support.
Field
Type
Description
id
String!
—
user
User!
—
event
Event
—
signal
Signal
—
crisis
Crisis
—
comment
String!
—
isCommentReply
Boolean!
Whether this comment is a reply to another comment.
repliedToCommentId
String
ID of the comment being replied to, if any.
tags
[CommentTag!]!
Users tagged in this comment.
createdAt
DateTime!
—
updatedAt
DateTime!
—
UserEngagementMetricsobject
Point-in-time engagement summary derived from auth.login activity.
All three windows are trailing from `asOf` (inclusive).
Field
Type
Description
asOf
DateTime!
Reference moment the windows are anchored to. Defaults to NOW()
when the caller doesn't specify it.
dau
Int!
Unique users with at least one login in the trailing 24 hours.
wau
Int!
Unique users with at least one login in the trailing 7 days.
mau
Int!
Unique users with at least one login in the trailing 30 days.
dauMauRatio
Float!
Stickiness ratio (DAU / MAU) as a percentage. Industry benchmark:
≥20% indicates a frequently-returning user base. Returns 0 when MAU
is 0 so the field is safe to chart without null-handling.
UserFeedbackobject
User feedback on a signal, event, or crisis — rating and optional text.