API reference
The wire speaks IPTC ninjs 3.2 — the format professional clients already parse. Registration is free: create an account, copy the key, start pulling.
Authentication
Your key has the form prefix.secret. Only the hash is stored on our side; the
plaintext is shown once, when the key is created.
curl -H "Authorization: Bearer wv_xxxxxxxx.SECRET" \
"https://wireva.mib.news/api/v1/items?language=de&limit=20"
X-Api-Key: … and ?api_key=… also work — the latter for readers that
cannot set headers. Anonymous requests are allowed and deliberately trimmed: headlines,
metadata and rights, but no body_html and no source trail, at 30 requests a minute.
Endpoints
| Path | Returns |
|---|---|
GET /api/v1/items | Wire items as ninjs. |
GET /api/v1/items/{uid} | One item in full. |
GET /api/v1/stories | Events with their language versions listed. |
GET /api/v1/stories/{uid} | One event as a ninjs composite package. |
GET /api/v1/media/{uid} | A picture with licence, provenance and delivery mode. |
GET /api/v1/feeds/{uid}/items | Items of a feed you saved in your account. |
GET /api/v1/topics · /publications · /languages | Vocabularies for building filters. |
Filters on /items
| Parameter | Example | Meaning |
|---|---|---|
language | de,uk | Language codes, comma-separated. |
country | DE,AT | Country of the desk or of the event. |
topic | politics,health | Slugs from /topics. |
publication | kernblik | Slugs from /publications. |
type | standard,update | Editorial type. |
rights | owned,agency_original | Rights class. |
redistributable | 1 | Only what you may republish in full. |
include_link_only | 0 | Drop monitoring items. |
q | Bundestag | Full-text search across all languages. |
since · until | 2026-08-21T10:00:00Z | Window on publication time. |
limit · offset | 200 · 400 | Pagination, 200 items maximum. |
body | 0 | Omit the text — for cheap sweeps. |
What an item looks like
Standard ninjs fields carry standard values. Everything ninjs has no home for — the rights
decision, the production provenance, the source trail — lives in extra under the
wireva: prefix, which is exactly what extra is for, and never instead
of a standard field.
{
"$schema": "https://iptc.org/std/ninjs/ninjs-schema_3.2.json",
"uri": "urn:newsml:wireva.mib.news:item:4e74f36e-…",
"type": "text", "profile": "standard", "version": "1",
"pubstatus": "usable", "language": "de",
"headline": "…",
"usageterms": "Subscribers may republish this item in full…",
"copyrightholder": "Haydamax OÜ",
"subject": [{ "code": "medtop:11000000", "scheme": "…/mediatopic/" }],
"associations": { "featuremedia": { "renditions": { "source": { "href": "…" } } } },
"extra": {
"wireva:rights": { "class": "agency_original", "redistribution_allowed": true,
"attribution_text": "Wireva / Kernblik",
"canonical_required": true, "canonical_url": "https://…",
"excerpt_max_chars": 0, "decided_by_rule": "agency_original_verified" },
"wireva:provenance": { "production_method": "automated", "ai_stages": {…},
"verification_status": "multi_source", "independent_confirmations": 2,
"ai_disclosure_required": true, "ai_disclosure_text": "…",
"independence_check": { "status": "passed", "score": 0.21 },
"sources": [ { "url": "…", "role": "primary", "official": false } ] },
"wireva:story": { "uri": "…", "languages": ["de","uk","fr"], "item_count": 7 }
}
}
A monitoring item (rights.class = link_only) arrives without
body_html: instead there is a body_text of at most
excerpt_max_chars and a note saying so. That is not a request option — the
serialiser cannot be talked into shipping the body of such an item.
What you agree to do with it
- Publish the credit from
wireva:rights.attribution_textwhenattribution_requiredis true. - Set
rel=canonicaltocanonical_urlwhencanonical_requiredis true — otherwise your reprint competes in search with the desk that filed it. - Carry the AI notice from
provenance.ai_disclosure_textwhenai_disclosure_requiredis true and you publish in the EU. - Respect the picture terms —
redistribution_allowed,commercial_use_allowed,modifications_allowed,share_alike_required— and take the file from wheredelivery_modepoints. - Honour
embargoed, and take down anything that turns up aspubstatus: canceled.
RSS and Atom
| Address | Contents |
|---|---|
/feed/ · /feed/atom/ | Everything. |
/feed/breaking/ | Alerts, flashes, breaking, corrections, withdrawals. |
/feed/language/{code}/ | One language desk. |
/feed/topic/{slug}/ | One subject. |
/feed/country/{cc}/ | One country. |
/feed/publication/{slug}/ | One title. |
/feed/custom/{uid}/{token}/ | Your own saved selection. |
Feeds carry the rights decision in their own namespace, so a newsroom with a reader and no
developer is not left guessing: <wireva:rights_class>,
<wireva:attribution>, <wireva:canonical_url>,
<wireva:production_method>, <wireva:ai_disclosure>.
Webhooks
Register an HTTPS endpoint in your account and receive each new item within seconds. Events:
item.published, item.updated, item.correction,
item.withdrawal. Twenty consecutive failures disable the endpoint, with the reason
recorded so you can see why.
POST /your/endpoint
X-Wireva-Event: item.published
X-Wireva-Signature: sha256=<hmac>
{ "event": "item.published", "item": { …ninjs… } }
import hmac, hashlib
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, request.headers["X-Wireva-Signature"]):
return 401
Instant on every matching item, breaking only, or a digest in the morning, at midday or in the evening — in your own timezone. Set it up in your account; every subscription carries its own unsubscribe link.
Limits and errors
Free tier: 120 requests a minute, 5 000 a day, 200 items per request. Anonymous: 30 a minute without full text. Limits are values on your account, not constants in our code — write to wire@wireva.mib.news if your workflow needs more.
| Status | Body | Cause |
|---|---|---|
| 401 | invalid_api_key · api_key_expired | Key unknown, revoked or expired. |
| 403 | subscriber_disabled · forbidden | Account disabled, or someone else's feed. |
| 404 | not_found | No such item, story or picture. |
| 429 | rate_limited · quota_exceeded | Per-minute or per-day limit; detail says which. |
Sweeping the wire politely
Do not poll /items without a window. Keep a cursor on since and page
with limit=200, or register a webhook and stop polling altogether. For a nightly
catch-up, body=0 gives you the list of uri cheaply; fetch the ones you
actually want one by one.
Coming next
NewsML-G2 XML for professional clients, CMS plugins (WordPress first) and embeddable blocks. The internal model was shaped so those are exports, not rewrites.