Intelrift
Public API
A small, opinionated, read-only REST API that gives you programmatic access to the same geopolitical signal that powers the Intelrift dashboard: daily event clusters, editorial briefings and the underlying articles. Plug it into your data warehouse, research notebooks, internal dashboards or trading systems.
Quickstart
- 1.Make sure your subscription is on the Professional plan. API access is included at that tier.
- 2.Go to Settings → API, click New key, give it a recognizable name and copy the secret. The plaintext value is shown only once.
- 3.Send your first request — no SDK required:
curl https://intelrift.com/api/v1/health \
-H "Authorization: Bearer $INTELRIFT_API_KEY"Every request must carry your key in the Authorization header. No other setup is required.
Authentication
All endpoints are authenticated. Provide your API key using one of the following headers:
Keys follow the format irf_live_<40 hexadecimal chars>. The first sixteen characters form a non-secret prefix that is displayed in the dashboard so you can identify the key. The full value is never shown again after creation.
Each user may keep up to ten active keys at a time. Revoking a key from Settings → API instantly invalidates it — any request made with a revoked key is rejected with 401 invalid_api_key. Keys inherit the plan of the owner: if the subscription is downgraded below Professional, all keys stop working until the plan is restored.
Treat API keys like passwords. Never commit them to source control, never embed them in client-side JavaScript, and never send them to a third party. If you suspect a key has leaked, revoke it immediately from Settings → API and create a new one.
Base URL & versioning
The API is served over HTTPS from a single base URL:
The path segment /v1 is the version. We only make additive, backward-compatible changes inside a major version: new fields, new optional query parameters, new endpoints. Breaking changes ship under a new version path (for example /v2) and the previous version is supported for at least twelve months after the successor goes stable.
Clients should be permissive on reading: ignore unknown fields in responses, and do not rely on the ordering of keys in JSON objects.
Request format
All endpoints in v1 accept only GET requests. Parameters are passed in the URL query string. There are no request bodies and no content-type negotiation — responses are always application/json; charset=utf-8.
- Boolean query params accept
true/false(case-insensitive). - Comma-separated lists are used for multi-value filters (e.g.
country=us,de,fr). - Unknown query parameters are silently ignored — never fatal.
- All timestamps in responses are ISO-8601 UTC (for example
2026-04-05T18:44:10.000Z).
Response format
Successful responses return an envelope that always contains a data field with the payload, plus lightweight metadata. Field names use snake_case.
data | object | array | The actual payload: a single resource or an array of resources. |
count | number | For list endpoints — number of items in the current page. |
limit | number | The effective page size (after clamping). |
offset | number | The effective pagination offset. |
date | string | Calendar day represented in the response (for day-scoped endpoints). |
tz | string | Timezone used to compute the day (IANA). |
range | object | UTC start / end timestamps of the day interval. |
Error responses never contain a data field — see section 09.
Day scope & timezones
Several list endpoints (notably GET /v1/clusters) return the items for a single calendar day. The day boundary is interpreted in a timezone of your choice, so that "today" matches the one your users actually see.
The scope is controlled by two query parameters:
date— an ISO calendar day inYYYY-MM-DDformat. Defaults to today in the given timezone.tz— an IANA timezone name such asEurope/Madrid,America/New_York,Asia/Tokyo. Defaults toUTC. Invalid names fall back toUTC.
The server resolves the pair (date, tz) into a half-open UTC interval [start, end) of exactly 24 hours and returns all items updated inside that interval. The response echoes back date, tz and the resolved UTC range, so the client never has to reimplement the conversion.
Pagination
List endpoints use offset-based pagination with two parameters:
limit— number of items per page. Valid range: 1 to 100. Default: 50 (30 for briefings).offset— how many items to skip. Max: 10 000.
Iterate until the returned count is smaller than your limit. The server never returns more items than requested.
Rate limits
Limits are enforced per API key and persisted in the database, so they survive server restarts and cannot be bypassed by distributing calls across instances.
Every response (including 429) includes the following headers so clients can track their budget:
X-RateLimit-Limit-Minute: 30
X-RateLimit-Remaining-Minute: 27
X-RateLimit-Reset-Minute: 1743864120
X-RateLimit-Limit-Day: 500
X-RateLimit-Remaining-Day: 463
X-RateLimit-Reset-Day: 1743897600X-RateLimit-Reset-* values are Unix timestamps (seconds) indicating when each window resets. On 429 Too Many Requests, a Retry-After header (in seconds) is also provided — back off at least that long before retrying.
API requests do not deduct credits from your monthly allowance. Credits remain reserved for AI-powered actions inside the app (Spectre, briefing generation, strategy generation). The API is a flat read-only tier.
Errors
Errors use a single, stable envelope. code is machine-readable and part of the contract; message is human-readable and may change.
{
"error": {
"code": "rate_limit_minute",
"message": "Per-minute rate limit of 30 requests exceeded."
}
}Reference of possible error codes:
| Status | Code | When |
|---|---|---|
| 401 | missing_api_key | No API key was provided in the Authorization or X-API-Key header. |
| 401 | invalid_api_key | Key is unknown, revoked or expired. |
| 403 | insufficient_scope | Key lacks the scope required by the endpoint. |
| 403 | api_feature_disabled | Owner of the key is no longer on the Professional plan. |
| 404 | not_found | The requested resource does not exist. |
| 429 | rate_limit_minute | Per-minute rate limit exceeded. Inspect Retry-After. |
| 429 | rate_limit_daily | Daily rate limit exceeded. Retry tomorrow. |
| 500 | internal_error | Unexpected server error. Retry with exponential backoff. |
Endpoints
https://intelrift.com/api/v1/api/v1/healthHealth check
curl https://intelrift.com/api/v1/health \
-H "Authorization: Bearer $INTELRIFT_API_KEY"/api/v1/clustersList clusters for a day
datetzdate. Defaults to UTC.countrylimitoffsetcurl "https://intelrift.com/api/v1/clusters?date=2026-04-05&tz=Europe/Madrid&limit=50" \
-H "Authorization: Bearer $INTELRIFT_API_KEY"{
"date": "2026-04-05",
"tz": "Europe/Madrid",
"range": {
"start": "2026-04-04T22:00:00.000Z",
"end": "2026-04-05T22:00:00.000Z"
},
"count": 12,
"limit": 50,
"offset": 0,
"data": [
{
"id": "7a3f0e1b-2c84-4a6d-b99f-8d1f2e3a4b5c",
"title": "NATO summit concludes with new eastern-flank commitments",
"summary": "Allies agreed to ...",
"category": "diplomacy",
"severity": 78,
"confidence": 85,
"article_count": 14,
"source_count": 9,
"countries": ["us", "pl", "de", "fr"],
"primary_country": "pl",
"region": "europe",
"event_type": "diplomatic",
"threat_level": "medium",
"trend": "rising",
"urgency": "high",
"topics": ["diplomacy", "defense"],
"keywords": ["nato", "summit"],
"tags": [],
"entities": { "people": [], "organizations": [] },
"window_start": "2026-04-05T06:00:00.000Z",
"window_end": "2026-04-05T18:00:00.000Z",
"created_at": "2026-04-05T06:12:44.000Z",
"updated_at": "2026-04-05T18:44:10.000Z"
}
]
}/api/v1/clusters/{id}Get a single cluster
curl https://intelrift.com/api/v1/clusters/7a3f0e1b-2c84-4a6d-b99f-8d1f2e3a4b5c \
-H "Authorization: Bearer $INTELRIFT_API_KEY"/api/v1/clusters/{id}/articlesList articles in a cluster
limitoffsetcurl "https://intelrift.com/api/v1/clusters/7a3f0e1b-.../articles?limit=20" \
-H "Authorization: Bearer $INTELRIFT_API_KEY"/api/v1/briefingsList recent briefings
limitcurl "https://intelrift.com/api/v1/briefings?limit=7" \
-H "Authorization: Bearer $INTELRIFT_API_KEY"/api/v1/briefings/{id}Get a single briefing
Retrieves a single briefing. The {id} path segment accepts three forms:
- A UUID — direct lookup by briefing id.
- The literal string
latest— returns the most recent public briefing. - A calendar date in
YYYY-MM-DDformat — returns the briefing for that day. Respects thetzquery parameter.
tz{id} is a UUID or latest.curl https://intelrift.com/api/v1/briefings/latest \
-H "Authorization: Bearer $INTELRIFT_API_KEY"Object schemas
The three main resource types exposed by the API. All fields are documented; clients should ignore unknown fields to stay forward-compatible.
| Field | Type | Description |
|---|---|---|
id | uuid | Unique cluster identifier. |
title | string | Editor-chosen canonical title. |
summary | string | null | Narrative summary of the event. |
category | string | null | Primary category (diplomacy, conflict, economy…). |
severity | integer (0–100) | Event severity score. |
confidence | integer (0–100) | Editorial confidence in the cluster. |
article_count | integer | Number of underlying articles. |
source_count | integer | Number of distinct sources. |
countries | string[] | ISO-3166-1 alpha-2 codes, lowercase. |
primary_country | string | null | Primary country of the event. |
region | string | null | Geographic region. |
event_type | string | null | Normalized event type. |
threat_level | string | null | low / medium / high / critical |
trend | string | null | rising / stable / falling |
urgency | string | null | low / medium / high / critical |
topics | string[] | Auto-derived topics. |
keywords | string[] | Extracted keywords. |
tags | string[] | Editorial tags. |
entities | object | Named entities (people, organizations, locations). |
window_start | ISO-8601 | Start of the covered time window. |
window_end | ISO-8601 | End of the covered time window. |
created_at | ISO-8601 | Cluster creation timestamp. |
updated_at | ISO-8601 | Last cluster update. |
| Field | Type | Description |
|---|---|---|
id | uuid | Briefing identifier. |
date | YYYY-MM-DD | Calendar day of the briefing. |
items | object[] | Briefing items (cluster references with editorial commentary). |
generated_at | ISO-8601 | When the briefing was generated. |
created_at | ISO-8601 | When the briefing was persisted. |
| Field | Type | Description |
|---|---|---|
id | uuid | Article identifier. |
title | string | Article title as published by the source. |
url | string | Original URL. |
canonical_url | string | Canonical URL after normalization. |
domain | string | Source domain. |
language | string | ISO-639-1 (en, es, fr, …) |
countries | string[] | Associated country codes. |
topics | string[] | Article topics. |
snippet | string | null | Short content excerpt. |
computed_score | integer | null | Computed article score. |
published_at | ISO-8601 | null | Original publish timestamp. |
fetched_at | ISO-8601 | When Intelrift ingested it. |
Code examples
Canonical snippets in the languages most Intelrift customers use. Substitute $INTELRIFT_API_KEY with your own key — never hardcode it.
curl "https://intelrift.com/api/v1/clusters?date=2026-04-05&tz=Europe/Madrid&limit=50" \
-H "Authorization: Bearer $INTELRIFT_API_KEY"
# Follow up with a single cluster
curl https://intelrift.com/api/v1/clusters/7a3f0e1b-2c84-4a6d-b99f-8d1f2e3a4b5c \
-H "Authorization: Bearer $INTELRIFT_API_KEY"Security best practices
Store API keys in environment variables or a secret manager — never in source files.
Give each environment (production, staging, notebook) its own key so you can rotate or revoke independently.
Rotate keys regularly and immediately when a team member with access leaves.
Never call the API directly from a browser or mobile client — always proxy through your backend so the key never reaches the user agent.
Monitor the last_used_at column in Settings → API and revoke any key that looks dormant or suspicious.
Treat a revoked key as unrecoverable. Issue a new one and update your deployments.
Changelog
- Initial public release of the Intelrift API.
- Endpoints: /health, /clusters, /clusters/{id}, /clusters/{id}/articles, /briefings, /briefings/{id}.
- Rate limits: 30 requests per minute and 500 per day per key.
- Bearer / X-API-Key authentication with per-user key management in Settings → API.
Support
Found a bug, need a higher rate limit, or want a feature we don't yet expose? The fastest way to reach us is through the in-app help button, or by replying to the welcome email you received when you subscribed. Include your key prefix (never the secret) so we can correlate the request with your account.