Skip to main content
API reference · V1

Endpoints, authentication, and rate limits.

The Zaviye API is REST over HTTPS with JSON request / response bodies. Authentication is bearer-token via a key you generate in your developer dashboard. MCP is available atzaviye.news/api/mcp/mcp for Claude and other MCP-compatible clients.

Quickstart

Sign up at /developers/keys, grab a key, make a call:

$ curl https://zaviye.news/api/v1/feed \
    -H "Authorization: Bearer zv_live_••••" \
    -G --data-urlencode "lang=fa,ku,ar,he,tr,en" \
        --data-urlencode "limit=20"

Response is a JSON object with clusters, next_cursor, and usage. See Cluster schema.

Authentication

Bearer tokens, passed in the Authorization header:

Authorization: Bearer zv_live_Kf9…

Keys are issued in the dashboard and rotate by button click. There is no rotation API — we think accidental automated key-churn is a bigger risk than manual inconvenience.

Every response includes a usage object with your current period's calls and remaining quota. Monitor it.

Rate limits

Per-key monthly quota by tier. Within a month, bursts are allowed up to 10 requests/second sustained. Go over and you get 429 Too Many Requests with a Retry-After header.

Hit 100% of quota → reads continue at a throttled rate (no hard cutoff, we don't surprise-bill). Hit 150% → hard throttle. Configure a soft cap at a lower percentage in the dashboard if you prefer.

Endpoints

Feed

GET/api/v1/feed

The live cluster feed. Paginated, most recent first.

Query parameters
  lang      comma-separated list of FA, KU, AR, TR, EN
  limit     1–200, default 50
  cursor    opaque pagination cursor from previous response
  since     ISO-8601 timestamp; only clusters updated after this time
  region    mideast | europe | global | centralasia | southasia | …
  topic     free-text topic match, AND-combined with other filters

Cluster

GET/api/v1/cluster/:id

Full detail for a single cluster. Includes article list, framing (paid tiers), bias breakdown (paid tiers), and translations.

GET/api/v1/search

Keyword search across indexed sources, optionally scoped by language corpus.

Query parameters
  q         required, search query (UTF-8, 1–256 chars)
  lang      comma-separated language filter
  limit     1–100, default 20

Languages

GET/api/v1/languages/:lang

Clusters carried by a specific language corpus. :lang is one of fa | ku | ar | he | tr | en.

Coverage gaps

GET/api/v1/coverage-gaps

Clusters with large inter-corpus disparity. The primary media-monitoring primitive.

Query parameters
  min_disparity  0.0–1.0, default 0.6 (share of coverage concentrated in one language)
  since          ISO-8601
  limit          1–100

Annotations (paid tiers)

GET/api/v1/cluster/:id/framing

Per-corpus framing analysis. One framing string per language where coverage exists.

GET/api/v1/cluster/:id/bias

Source-level bias breakdown, state-media flags, composite visual-bias scores where available.

GET/api/v1/cluster/:id/translations

Title + summary translation pairs across corpora.

Account

GET/api/v1/account/usage

Current period call count, quota, and soft-cap settings.

GET/api/v1/account/keys

List of issued API keys with last-used timestamps (the keys themselves are only revealed at issuance).

Cluster schema

{
  "id": "clu_8Q3Hk2J…",
  "headline": "…",
  "ai_summary_short": "…",
  "article_count": 18,
  "languages": {
    "fa": 9, "ku": 5, "tr": 3, "ar": 1, "en": 1
  },
  "blind_spot": true,
  "blind_spot_corpus": "en",
  "region": "mideast",
  "topics": ["infrastructure", "corridor"],

  // paid tiers only
  "framing": {
    "fa": "…",
    "ku": "…",
    "ar": "…",
    "tr": "…",
    "en": "…"
  },
  "bias": { "left": 4, "center": 6, "right": 8 },
  "factuality_label": "High",

  "sources": [
    {
      "source_key": "irna-fa",
      "source_name": "IRNA",
      "lang": "fa",
      "bias": -1,
      "state_media": true,
      "url": "https://…",
      "title": "…",
      "published": "2026-04-19T13:42:00Z"
    }
  ],
  "updated_at": "2026-04-20T09:04:12Z"
}

Errors

Errors come back as JSON with error and message fields.

HTTP/1.1 429 Too Many Requests
Retry-After: 23

{
  "error": "rate_limited",
  "message": "You've reached 150% of your monthly quota. Upgrade or wait.",
  "usage": { "calls_this_period": 75230, "quota": 50000 }
}

Common codes:

  • · 401 unauthenticated — missing or invalid bearer token
  • · 403 forbidden — endpoint requires a higher tier
  • · 404 not_found — cluster id does not exist or is outside your data window
  • · 429 rate_limited — see above
  • · 503 pipeline_busy — transient; retry with backoff

MCP — Model Context Protocol

Zaviye also exposes an MCP server at zaviye.news/api/mcp/mcp. Claude Desktop, Claude Code, and other MCP-compatible clients can connect via OAuth at /mcp/authorize.

Tool names map 1:1 to endpoint names: news_feed, news_cluster, news_search, coverage_gaps, account_usage.

MCP tokens share a rate bucket with your REST key at the same plan. Your free tier applies to MCP too — which means Claude users can use Zaviye for personal reading without signing up for a paid plan.

Changelog

  • 2026-04-20 · v1.0
    Initial public surface. Starter / Developer / Studio / Press / Enterprise tiers defined. MCP server at /api/mcp/mcp live. REST endpoints listed above; implementation rolling out on the existing cluster store. Usage tracking and per-key rate limiting land first; annotation endpoints follow.