Agent Trial
Trading Prediction Markets AI Agent Context Fastest News API Agent Trial Log In Sign Up

Real-Time News API Documentation for LLMs & Agents

Maintained by the oruk Engineering Team · Last updated: May 2026

oruk's REST and SSE API delivers corroborated breaking news from 240 live radio, TV, and structured feeds in 7 regions, with stories typically hitting the wire 30–90 seconds after they're spoken on air. The public feed is free; an account-bound key unlocks full filters, deeper history, the SSE stream, the MCP server, and webhooks. Most evaluation work fits inside the free tier (100 calls/month).

https://api.oruk.ai
Checking API…

About This Documentation

These docs are maintained by the oruk Engineering Team, which works across broadcast media ingestion, low-latency speech recognition, event extraction, and source corroboration. They describe the production API and the same live speech intelligence pipeline used on oruk.ai.

For sourcing rules, transcript handling, and quality controls, read the methodology. To learn who builds oruk, visit about oruk.

Runnable docs

Try the API with your key

Sign up for a free key and run real production calls from this page. The key is kept in this browser and sent only when you click a demo: REST examples go through a same-origin docs proxy that forwards your key to api.oruk.ai without storing it, while SSE examples connect directly to api.oruk.ai with ?api_key= because EventSource cannot set custom headers. Server examples should use X-API-Key.

Saving uses sessionStorage, so it survives refreshes in this tab and clears when the tab session ends. Avoid sharing screenshots that reveal your key.

Stories and filtersFresh stories, full-text search, impact/category/region filters, cursor pagination, CSV, and JSONL exports.
Story audit trailFetch a story by evt_... id with timeline, corroboration, source details, and quotes.
Live streamsTrader, agent trial, developer, and enterprise keys can use direct SSE for story and transcript updates; one open SSE connection counts as one API call.
AutomationUse the MCP server, webhooks on eligible keys, system stats, source catalogues, and region heatmaps.
Live output Ready
Sign up for a free key, then run an example. REST examples show status, timing, quota headers, and response data. SSE examples append live story or transcript events for streaming tiers.

How do I authenticate with the oruk API?

Send your API key in the X-API-Key header or Authorization: Bearer. Browser-only demos and SSE clients that cannot set headers can use the ?api_key= query param. Three read endpoints — /health, /v1/health, and /v1/stories/feed — are public and don't need a key; everything else under /v1/* does.

The full open-vs-keyed surface:

EndpointAuthNotes
GET /healthPUBLICLiveness probe.
GET /v1/healthPUBLICDetailed health: streams, stories, uptime.
GET /v1/stories/feedPUBLICThe latest ~100 stories, no filters.
Everything else under /v1/*REQUIRES KEYFull filter surface, story lookups, sources, stats, SSE, webhooks, key management.

Pass your key via any of these:

MethodHeader / ParamExample
API KeyX-API-KeyX-API-Key: ork_x9f2...
Bearer TokenAuthorizationAuthorization: Bearer ork_x9f2...
Query Paramapi_key?api_key=ork_x9f2... (for browser demos and SSE / EventSource clients that can't set headers)

Free includes 100 API calls per month and 1 key, with a 5-minute API delay. Pro includes 1,000 calls per month, 2 keys, and real-time API responses. Trader includes 10,000 calls per month, 2 keys, the real-time story and transcript SSE streams, and a 300 req/min rate limit. Developer keys are provisioned for API partners and agent integrations with real-time REST/SSE. Enterprise limits are customized per contract and can use per-minute or per-second windows.

How do I get started with the oruk API in 5 minutes?

Start with the public GET /v1/stories/feed?limit=10 endpoint, then sign up with email and generate an API key from the dashboard when you need authenticated story filters, full-text search with q, story detail lookup, sources, stats, SSE, or MCP access. The Free tier includes 100 keyed calls/month and 1 key — enough to verify the integration before picking a plan.

1. Create an account

Sign up at oruk.ai/signup with your email. You'll receive a 6-digit verification code to confirm your account.

2. Generate an API key

Head to the dashboard and click Generate Key. Free accounts get 1 key with 100 calls/month (5-minute API delay). Upgrade for higher quotas and real-time responses: Pro (1k/mo, real-time), Trader (10k/mo + SSE), or Enterprise (1M+/mo).

3. Pick a plan that fits your usage

Most evaluation work fits on Free. Upgrade from the pricing page when you need higher monthly call quotas, SSE stream access, or more keys.

4. Fetch live events

Pick your stack — the tab choice persists across every snippet on this page. We don't ship official SDKs yet; these are copy-paste templates against the public REST and SSE endpoints.

Latest 10 stories from the public feed
curl -H "X-API-Key: ork_xxxxxxxx" \
  "https://api.oruk.ai/v1/stories/feed?limit=10"

5. Stream events live

SSE access by tier: Free, Pro, and Legacy do not include SSE (403). Trader ($49 first month, then $99/mo), Developer, and Enterprise stream in real time with the same wire as the public homepage — one connection, every new or corroborated story.

Subscribe to the SSE stream
curl -N -H "X-API-Key: ork_xxxxxxxx" \
  https://api.oruk.ai/v1/stream

How do I fetch the latest news without an API key?

Call GET /v1/stories/feed — it's open to anyone and returns up to ~100 of the freshest stories with no filters required. Use it as your default endpoint for "what's new right now"; upgrade to /v1/stories with a key when you need filters, full-text search, or pagination.

GET/v1/stories/feed PUBLIC  ·  powers the public wire on oruk.ai and the no-key fallback in oruk-mcp.

ParameterTypeDescription
limitintMax results (1-100, default 20)
sortstringrecent (default) or impact
since_hoursintWindow in hours, 1-168 (default 4)
curl "https://api.oruk.ai/v1/stories/feed?limit=10"

Response

{
  "stories": [{
    "id": "evt_3d22dc5b1d09",
    "headline": "Angola Quits OPEC After Six Decades",
    "summary": "Angola's oil minister announced...",
    "body": "Angola has formally exited OPEC...",
    "category": "economy",
    "categories": ["economy", "diplomacy"],
    "topics": ["OPEC", "oil", "Angola"],
    "urgency": "developing",
    "impact": 8,
    "confidence": 0.95,
    "sourceName": "BBC World Service",
    "eventCity": "Luanda", "eventCountry": "AO", "eventRegion": "Africa",
    "eventLat": -8.84, "eventLon": 13.23,
    "firstSeenAt": "2026-04-28T22:13:42Z",
    "updatedAt":   "2026-04-28T22:14:08Z",
    "corroboration": {"count": 3, "sources": ["BBC", "NPR", "RFI"],
                       "sourceDetails": [{"region":"Europe","language":"en","medium":"audio_radio"}, ...]},
    "timeline": [{"at":"...", "text":"..."}],
    "sources": [{"station":"BBC World Service", "quote":"Angola has formally..."}, ...]
  }],
  "meta": {"count": 10}
}

The feed returns up to ~100 of the freshest events. For older stories, use /v1/stories?since=… with an API key.

How do I search and filter stories with full filters?

Call GET /v1/stories with an API key and any combination of category, q, since, region, country, urgency, min_impact, min_confidence, and topics. Results paginate with a stable cursor, and you can switch the response format to csv or jsonl for bulk export.

GET/v1/stories REQUIRES KEY

ParameterTypeDescription
limitintMax results (1-100, default 20)
cursorstringStory id from a previous response
categorystringpolitics, conflict, economy, disaster, diplomacy, science, health, technology, culture, environment, sports, other
sinceISO 8601Only stories after this timestamp
topicsstringComma-separated topic filter
qstringFull-text search across headline / summary / body / source / city
regionstringNorth America, South America, Europe, Middle East, Africa, Asia-Pacific
countrystringISO 3166-1 alpha-2 (e.g. US, IL, DE)
urgencystringbreaking, developing, or routine
min_impactintLower bound on impact (0-10)
min_confidencefloatLower bound on confidence (0.0-1.0)
formatstringjson (default), csv, or jsonl for bulk export
curl -H "X-API-Key: ork_xxxx" \
  "https://api.oruk.ai/v1/stories?category=conflict&min_impact=7&limit=20"

Response

{
  "stories": [{ /* same shape as /v1/stories/feed */ }],
  "meta": {"count": 5, "cursor": "evt_7c2a1f", "hasMore": true}
}

How do I fetch a single story with its full timeline?

Call GET /v1/stories/{evt_id} with an API key. The response includes the full body, the developmental timeline, every independent corroborating source with the verbatim quote it used, the multi-category list, and event coordinates — everything you need to audit the story without trusting our judgement on its face.

GET/v1/stories/{id} REQUIRES KEY

curl -H "X-API-Key: ork_xxxx" \
  https://api.oruk.ai/v1/stories/evt_8f3a2b

How do I stream news events in real time over SSE?

Open a long-lived GET /v1/stream connection with your API key — it returns text/event-stream with three event types (story, corroboration, heartbeat) and stays open until your client disconnects. SSE is included on Trader ($49 first month, then $99/mo), Developer, and Enterprise. Free, Pro, and Legacy tiers receive HTTP 403 with an upgrade hint.

GET/v1/stream REQUIRES KEY

EventDescription
storyNew story detected
corroborationExisting story confirmed by additional source
heartbeatSystem pulse for connection health

Optional stream filters

Leave filters out to receive the full live wire. Add one or more filters to receive only matching events. Repeated params and comma-separated values both work.

ParameterExampleMatches
categoryconflictPrimary event category
topicsoil,central bankAny story topic overlap
region / regionsEuropeEvent region or source region
sourceKey / sourceKeysBBC,NPRSource keys from /v1/sources
station / broadcastBBC World ServiceStation/source name, including corroborating sources
languageenStory language or source language
sourceTypeaudioaudio broadcasts or text structured sources

Example output

event: story
data: {"id":"evt_9c4d1f","category":"conflict","confidence":0.96,"body":"..."}

event: corroboration
data: {"storyId":"evt_8f3a2b","count":5,"newSource":"NPR"}

event: heartbeat
data: {"ts":"2026-04-04T14:22:30Z","status":"live"}

JavaScript

const es = new EventSource(
  "https://api.oruk.ai/v1/stream?api_key=YOUR_KEY"
);
es.addEventListener("story", (e) => {
  const story = JSON.parse(e.data);
  console.log(`[${story.urgency}] ${story.body.slice(0, 100)}`);
});

Python

import httpx, json

with httpx.stream("GET", "https://api.oruk.ai/v1/stream",
                   headers={"X-API-Key": "YOUR_KEY"},
                   params={"category": "conflict", "regions": "Europe,Middle East"}) as r:
    for line in r.iter_lines():
        if line.startswith("data:"):
            event = json.loads(line[5:].strip())
            print(event)

How do I stream live transcript fragments over SSE?

Open GET /v1/transcripts/stream with a Trader, Developer, or Enterprise key to receive raw live transcript fragments from audio sources as they arrive. This is the lowest-level live speech surface: use it when you need every station-level update, then layer your own entity extraction, alerts, or matching logic on top.

GET/v1/transcripts/stream REQUIRES KEY

ParameterTypeDescription
sourceKey / sourceKeysstringOptional source key filter, such as station keys returned by /v1/sources. Supports repeated params and comma-separated values.
station / broadcaststringOptional station/source name filter. Partial station names are accepted for convenience.
region / regionsstringOptional source region or continent filter, such as Europe or North America.
citystringOptional source city filter.
languagestringOptional source language filter, such as en, es, or fr.
sourceTypestringOptional source type filter. Use audio for radio/TV transcript fragments or text for structured sources.

Events

EventDescription
transcriptA live transcript segment with station/source metadata, sequence/timestamp fields, and text.
heartbeatKeepalive pulse with live connection status.
Subscribe to live audio transcript fragments
curl -N -H "X-API-Key: ork_xxxxxxxx" \
  "https://api.oruk.ai/v1/transcripts/stream?sourceType=audio&regions=Europe,North%20America"

How do I list every monitored broadcast source?

Call GET /v1/sources with an API key. The response is the full station catalogue across Europe, North America, Asia-Pacific, South America, Global, Middle East, and Africa, with city, region, country, language, default category, medium, live status, and polling cadence for each source.

GET/v1/sources REQUIRES KEY  ·  same data renders on /sources.

{"sources": [{
  "id": 1, "name": "BBC World Service", "city": "London",
  "region": "Europe", "lat": 51.51, "lon": -0.13,
  "defaultCategory": "politics", "status": "active",
  "lastSeenAt": "2026-04-04T14:22:00Z", "cadenceMs": 5000
}]}

How do I get system statistics from the oruk API?

Call GET /v1/stats with an API key for an instantaneous snapshot of system health, total stories, transcription volume, reconciliation latency, and the top categories by published volume. Use it as a heartbeat for monitoring or as a "health-of-the-wire" widget on your own dashboard.

GET/v1/stats REQUIRES KEY

{
  "wireStatus": "live",
  "storiesTotal": 142,
  "geminiCycles": 87,
  "transcriptions": 52000,
  "topCategories": [{"category": "conflict", "count": 38}],
  "lastCycleMs": 4800,
  "uptimeSeconds": 3600
}

How do I get geographic story counts for map overlays?

Call GET /v1/regions with an API key. The response is the story heatmap — an array of integer-bucketed lat/lon cells with the count of stories in each cell and the dominant category — currently ~1,800 cells globally, ready to drop into Leaflet, Mapbox, or any d3 choropleth.

GET/v1/regions REQUIRES KEY

{"regions": [
  {"lat": 52, "lon": 13, "count": 12, "topCategory": "politics"},
  {"lat": 36, "lon": 51, "count": 8, "topCategory": "conflict"}
]}

How do I manage my oruk API keys?

Generate, label, and revoke normal account keys from the Dashboard — Free accounts get 1 key, Pro and Trader get 2 keys each, and Enterprise up to 100. Each key is independently revocable and bills against the same monthly quota; rotate one without affecting any others.

GET/v1/keys REQUIRES KEY DELETE/v1/keys/{key_id} POST/v1/keys admin/provisioner only

GET /v1/keys returns metadata only: id, last four characters, label, tier, rate limit, monthly call limit, creation time, and expiration. It never returns an existing secret key. DELETE /v1/keys/{key_id} revokes a key you own. POST /v1/keys is reserved for admin/provisioner keys that mint Developer or 7-day agent-trial keys.

List active key metadata
curl -H "X-API-Key: ork_xxxxxxxx" \
  https://api.oruk.ai/v1/keys

How do I send live story updates to my app with webhooks?

Developer, Enterprise, admin, and provisioner keys can subscribe HTTPS endpoints to story and corroboration events. Webhooks are useful when you want oruk to push high-impact updates into a newsroom bot, trading system, CRM, Slack bridge, or agent queue without holding an SSE connection open.

POST/v1/webhooks REQUIRES KEY GET/v1/webhooks DELETE/v1/webhooks/{id}

Filter fieldTypeDescription
event_typesarraystory, corroboration, or both.
categoriesarrayOnly deliver matching story categories, such as conflict or economy.
min_impactintegerOnly deliver events with impact at or above this score.
min_confidencenumberOnly deliver events at or above this confidence.
countrystringISO country code, such as US or GB.
topic_matchstringSubstring match against story topics.

Payloads are signed with X-Oruk-Signature: sha256=... using the webhook secret returned at creation time. Store that secret once; list responses do not expose it again.

Create, list, and delete webhooks
curl -H "X-API-Key: ork_xxxxxxxx" https://api.oruk.ai/v1/webhooks

curl -X POST https://api.oruk.ai/v1/webhooks \
  -H "X-API-Key: ork_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/oruk/webhook",
    "filter": {
      "event_types": ["story", "corroboration"],
      "categories": ["conflict", "economy"],
      "min_impact": 7
    }
  }'

curl -X DELETE -H "X-API-Key: ork_xxxxxxxx" \
  https://api.oruk.ai/v1/webhooks/whk_123

How does the oruk MCP server work with Claude, Cursor, and Continue.dev?

Install the npm package oruk-mcp with one line — npx -y oruk-mcp — and any Model Context Protocol client (Claude Desktop, Cursor, Continue.dev) gets 12 tools, 6 resources, and 3 slash-prompts for searching corroborated real-time news. Without an API key it falls back to the public feed; set ORUK_API_KEY to lift it to the full filter surface, deeper history, and arbitrary evt_… story lookups.

The official production path today is stdio via npm: npx -y oruk-mcp. Remote MCP over Streamable HTTP is planned as a controlled beta after OAuth-compatible connector auth, quotas, origin controls, and audit logging are in place.

How it fits

The MCP runs locally on your machine (spawned by your IDE). It talks directly to api.oruk.ai on Railway — the same Python backend that powers everything else. Azure (oruk.ai) is the public website only; there is no separate dataset to query.

  Claude / Cursor / Continue.dev
       │ stdio (JSON-RPC)
       ▼
  oruk-mcp (npx -y oruk-mcp)
       │ HTTPS
       ▼
  api.oruk.ai (Railway)         oruk.ai (Azure, PHP)
  • /v1/stories/feed  PUBLIC    • /docs, /feed/, /topic/
  • /v1/stories       AUTH      • /api/stories.php (browser proxy
  • /v1/stories/{id}  AUTH         to api.oruk.ai)
  • /v1/sources       AUTH      • /api/search.php
  • /v1/stats         AUTH      • RSS, Atom, sitemaps
  • /v1/regions       AUTH
  • /v1/stream  (SSE) AUTH
  • /v1/transcripts/stream AUTH
  • /v1/webhooks      AUTH

Two modes

Tools annotate structuredContent.mode as "public" or "authed" so the LLM (and you) know which path was taken.

ModeTriggered whenSearch corpusTools that work
public ORUK_API_KEY unset Last ~100 stories on /v1/stories/feed; filters applied client-side. oruk_get_latest, oruk_search_news, oruk_get_breaking, oruk_get_topic, oruk_get_story (recent only), oruk_get_corroboration, plus all static tools (oruk_list_categories, oruk_describe_api, oruk_show_pricing, oruk_health).
authed ORUK_API_KEY set Full available corpus on the production API, with cursor pagination, full-text search, and arbitrary evt_… lookups. Everything in public mode plus oruk_list_sources, oruk_get_stats, deeper history, deeper filters.

Install

One command — no global install needed. Latest version published to npm at npmjs.com/package/oruk-mcp:

npx -y oruk-mcp

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %AppData%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "oruk": {
      "command": "npx",
      "args": ["-y", "oruk-mcp"],
      "env": { "ORUK_API_KEY": "ork_xxxxxxxxxxxx" }
    }
  }
}

Restart Claude Desktop. The oruk tools appear in the tool picker.

Cursor

Open Settings → MCP and add the same JSON block, or edit ~/.cursor/mcp.json directly.

{
  "oruk": {
    "command": "npx",
    "args": ["-y", "oruk-mcp"],
    "env": { "ORUK_API_KEY": "ork_xxxxxxxxxxxx" }
  }
}

Continue.dev (VS Code)

In ~/.continue/config.json:

{
  "mcpServers": [
    {
      "name": "oruk",
      "command": "npx",
      "args": ["-y", "oruk-mcp"],
      "env": { "ORUK_API_KEY": "ork_xxxxxxxxxxxx" }
    }
  ]
}

Tools exposed

ToolWhat it does
oruk_get_latestFreshest stories with optional category, region, country, urgency, impact, since filters.
oruk_search_newsFull-text search across recent stories.
oruk_get_breakingConvenience wrapper for high-urgency stories (urgency=breaking, impact ≥ 5).
oruk_get_storyFull detail of one story by evt_… id with timeline and verbatim source quotes.
oruk_get_topicStories in a single category, plus the editorial description of that category.
oruk_list_categoriesThe 12 oruk categories with one-line descriptions.
oruk_list_sourcesEvery monitored radio / TV / social / structured feed (requires API key).
oruk_get_statsLive system stats (requires API key).
oruk_get_corroborationIndependent sources and verbatim quotes for one story.
oruk_describe_apiFull REST/SSE reference, returned to the LLM for integration questions.
oruk_show_pricingTier comparison.
oruk_healthBackend health check.

Resources

The host can attach any of these oruk://… URIs to the model's context:

  • oruk://docs/quickstart — 60-second setup guide
  • oruk://docs/api-reference — concise REST + SSE reference
  • oruk://docs/methodology — pipeline, sourcing, quality controls
  • oruk://docs/categories — the 12-category taxonomy
  • oruk://docs/pricing — tier table
  • oruk://stories/latest — live snapshot of the freshest 25 stories

Prompts (slash commands)

  • /summarize_breaking — short briefing of urgent stories, optional category/region filter
  • /track_topic — chronological summary of a topic over the past N hours
  • /morning_briefing — structured "what happened overnight" rundown grouped by category

Without an API key

The public /v1/stories/feed endpoint is open. When ORUK_API_KEY is unset, the server falls back to a 2-hour window of the freshest 50 stories on the feed and applies all filters client-side. Good for almost every interactive query but trims older stories and omits the sources / stats endpoints. Set the env var (free key from signup or the dashboard) for the full filter surface, deeper history, and arbitrary evt_… story lookups.

Quota accounting

Every MCP tool invocation that reaches the backend counts as one API call against your key — the same quota the REST API uses (see Rate limits & quotas). The MCP holds an in-process cache for ~3 s on the public feed, so multi-tool turns inside one session usually collapse to a single backend hit. If you run into 429 from a tool, the answer is the same as for the REST API: upgrade or wait out the month.

MCP package, support, and full reference: npmjs.com/package/oruk-mcp, llms-full.txt, and support@oruk.ai.

How can autonomous agents discover the oruk API?

Hit the standard discovery URLs first — every public page links to them and they're explicitly allow-listed in robots.txt for AI-search crawlers. Each file gives an agent a different shape of context: a JSON capability manifest, an agent skill card, an operating guide, a Markdown sitemap, and curated/full-context LLM documentation.

Does oruk support machine-payable autonomous agent calls?

Not yet — production billing is API-key based through human-managed Stripe subscriptions, and existing REST/SSE endpoints do not return live 402 Payment Required challenges. An opt-in x402 beta on new /v1/x402/* endpoints is in research; existing REST, SSE, webhooks, and MCP behaviour will not change when the beta lands.

Oruk is preparing autonomous payment support as a separate beta so machine clients can pay for isolated live-data calls without navigating a human checkout page. The first safe rollout target is new opt-in endpoints such as /v1/x402/stories/feed and /v1/x402/stories/{id}, leaving existing REST, SSE, webhooks, and MCP behavior unchanged.

ProtocolStatusBest fit
x402Planned betaPay-per-request API calls, likely USDC on Base through a facilitator.
Stripe Machine Payments ProtocolAccess-gated researchSession-based or spending-limit authorization once Stripe machine-payments access is available.
Stripe subscriptionsLive nowHuman-managed recurring plans and API keys.

Until Oruk announces a beta, treat 401, 403, and 429 as the active auth and quota signals. Machine-payment status is also published in /.well-known/ai.json.

How are oruk API errors structured?

Every error response carries a stable machine-readable error code plus a human-readable message that may change. The HTTP status, the request ID echoed in x-request-id, and (on auth failures) a www-authenticate: Bearer header are everything an agent needs to recover or escalate without parsing English.

{
  "error":   "unauthorized",
  "message": "Valid API key or JWT required."
}

The error field is a stable machine-readable code; the message field is a human-readable description that may change. 401 responses also include a www-authenticate: Bearer header, and the request id is exposed via x-request-id on every response (useful when filing a support ticket).

StatusCodeWhen
400invalid_emailMalformed email at signup
400invalid_requestMalformed query parameters or body (e.g. since=yesterday)
401unauthorizedMissing or invalid API key / JWT
401invalid_codeWrong email verification code
404not_foundResource not found (story id, source id, etc.)
409email_takenEmail already registered
429rate_limit_exceededShort-window rate limit exceeded; check Retry-After header (seconds to wait)
429monthly_quota_exceededMonthly call quota exhausted for the key or account
500internal_errorBackend hiccup; retry with exponential backoff
503service_unavailablePipeline temporarily down (rare); poll /health

How are oruk rate limits and monthly quotas enforced?

oruk enforces two limits on keyed traffic: a monthly call quota per API key and a short-window request rate. Standard public tiers use per-minute windows; provisioned Enterprise keys can use custom per-minute or per-second windows. Monthly counters reset on the 1st of each month UTC. The MCP server shares the same quota; the public /v1/stories/feed, /health, and /v1/health endpoints don't count toward any quota and don't need a key at all.

TierCalls / monthShort-window rateKeysSSE streams
free 100 30 req/min 1 Not included
pro 1,000 60 req/min 2 Not included
legacy 1,000 60 req/min 2 Not included
trader 10,000 300 req/min 2 Real-time
developer10,000 300 req/min ProvisionedReal-time
enterprise1,000,000+ Custom 100 Real-time

Responses include X-RateLimit-Limit, X-RateLimit-Remaining, X-Oruk-Monthly-Limit, and X-Oruk-Monthly-Remaining. Newer custom Enterprise keys also include X-RateLimit-Window-Seconds so clients can tell whether a limit is per-minute or per-second.

What counts as one call?

  • Each REST request (GET, POST, DELETE) counts once at request-time.
  • An SSE connection counts once when the connection opens; events delivered while it stays open do not re-bill.
  • Each MCP tool invocation that reaches the backend counts as one call. Tools with structuredContent.mode: "public" use the same shared call against /v1/stories/feed.
  • The MCP holds an in-process cache for ~3 s on the public feed, so multi-tool turns inside one MCP session typically collapse to a single backend hit.
  • /health, /v1/health, and /v1/stories/feed are public; they don't require a key and don't count toward any quota.

What a 429 looks like

HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json

{"error": "rate_limit_exceeded",
 "retry_after_seconds": 60}

When the monthly quota is exhausted, the API returns monthly_quota_exceeded. Upgrade at /pricing to lift the quota, or wait until the calendar month rolls over.

What broadcasters does oruk cover?

oruk covers monitored sources across major global regions, with per-source live status and polling cadence available on /v1/sources. The table below shows representative broadcasters, social feeds, and structured feeds by region.

RegionCoverageSample broadcasters
EuropeRegionalBBC World Service, LBC, France Info, Deutschlandfunk, NDR, RAI, SER, ERT, Radio Maryja, Times Radio
North AmericaRegionalNPR, KQED, WNYC, WAMU, WBUR, KDKA, KYW, ICI Radio-Canada, CBC, Bloomberg
Asia-PacificRegionalABC Radio National, NHK World, YTN, CNR, CRI, VOV, MCOT FM, Tokyo FM
South AmericaRegionalCaracol, W Radio, Radio Bandeirantes, Radio CBN, Radio Globo, Rádio Observador, ADN
GlobalStructuredBSKY (Bluesky), MSTDN (Mastodon), GDELT, COMMOD, CGECK, PREDT, USGS, NOAA, OpenFDA
Middle EastRegionalSky News Arabia, Iran International, Radio Farda, Al Araby, Radio Orient
AfricaRegionalSAfm and regional broadcasters under expansion

Live counts come from /v1/sources; this table updates whenever the catalogue does. The full station list with city, region, language, and default category is on /sources.

What does each oruk plan include?

Four public tiers — Free, Pro ($12/mo), Trader ($49 first month, then $99/mo), Enterprise — plus provisioned Developer keys for API partners and agent integrations. The live wire on oruk.ai is real-time for everyone, no signup required. Paid and provisioned tiers add programmatic REST access; story and raw transcript SSE are available on Trader, Developer, and Enterprise.

PlanFrontendProgrammatic Access
FreeReal-time wire100 API calls/month, 1 key, REST, MCP; authenticated /v1/stories ~5 min behind the live wire; /v1/stream not included
Pro ($12/mo)Real-time wire1,000 API calls/month, 2 keys, real-time REST, MCP. SSE not included.
Trader ($49 first month, then $99/mo)Real-time wire10,000 API calls/month, 2 keys, real-time REST, story SSE, raw transcript SSE, MCP, webhooks.
Developer (provisioned)Real-time wire10,000 API calls/month, real-time REST, story SSE, raw transcript SSE, MCP, webhooks where enabled.
EnterpriseReal-time wire1M+ API calls/month or custom quota, up to 100 keys, real-time story/transcript SSE, custom support

For Enterprise access, contact enterprise@oruk.ai.

Have a referral code? Enter it at Stripe checkout for your first month of Pro free.