Developer Resources
Norsk Luftvern — Data & API
Norsk Luftvern publishes all article metadata as a machine-readable JSON index, updated on every content deploy. No authentication. No rate limits. 224 articles (129 EN · 95 NO) as of 2026-05-23.
Endpoints
| Method | URL | Content-Type | Auth |
|---|---|---|---|
GET | /api/articles.json | application/json | None |
The file is pre-built at deploy time. It reflects the state of all published articles at the moment the site last rebuilt. Typical rebuild lag after a new article is published is under five minutes.
Response schema
The response is a JSON object with two top-level keys: meta and articles.
meta
| Field | Type | Description |
|---|---|---|
title | string | Human-readable feed name |
url | string | Canonical URL of this feed |
generated | string (ISO 8601) | Build timestamp (UTC) |
count | integer | Total number of published articles |
countByLang | object | Article count keyed by language code, e.g. {"en": 129, "no": 95} |
articles[ ]
| Field | Type | Nullable | Description |
|---|---|---|---|
slug | string | no | URL-safe identifier, unique across all articles |
url | string | no | Absolute canonical URL of the article page |
title | string | no | Full article title |
date | string (YYYY-MM-DD) | no | Original publication date |
excerpt | string | no | One-to-three sentence summary |
category | string | no | Primary category slug (e.g. analyse, missilforsvar) |
lang | "no" | "en" | no | Article language |
author | string | no | Byline |
tags | string[] | no | Lowercase hyphenated topic tags; empty array if none |
series | string | yes | Series slug if the article belongs to a series, otherwise null |
crossSeries | string[] | no | Additional series slugs for articles that appear in more than one series |
featured | boolean | no | true for editorially featured articles (at most one per language) |
readingTime | integer | no | Estimated reading time in minutes |
heroImage | string | yes | Absolute URL to the article's hero image, or null |
Example response (truncated)
{
"meta": {
"title": "Norsk Luftvern — Article Index",
"url": "https://norskluftvern.no/api/articles.json",
"generated": "2026-05-20T14:51:00.855Z",
"count": 224,
"countByLang": { "en": 129, "no": 95 }
},
"articles": [
{
"slug": "intercepting-hypersonic-glide-vehicles-physics-sensors-and-the-programs-closing-the-gap",
"url": "https://norskluftvern.no/articles/intercepting-hypersonic-glide-vehicles-...",
"title": "Intercepting Hypersonic Glide Vehicles: Physics, Sensors, and the Programs Closing the Gap",
"date": "2026-05-16",
"excerpt": "Hypersonic glide vehicles don't just fly fast — they exploit a specific altitude band...",
"category": "analyse",
"lang": "en",
"author": "Norsk luftvern",
"tags": ["hypersonic", "missile-defense", "sensors", "thaad", "arrow-4", "sm-6"],
"series": null,
"crossSeries": [],
"featured": false,
"readingTime": 10,
"heroImage": "https://norskluftvern.no/images/IMG_9678.jpeg"
},
...
]
} Code examples
curl
curl -s https://norskluftvern.no/api/articles.json | jq '.meta' JavaScript — fetch all English articles, newest 10
const res = await fetch('https://norskluftvern.no/api/articles.json');
const data = await res.json();
const latest = data.articles
.filter(a => a.lang === 'en')
.slice(0, 10);
console.log(latest.map(a => a.title)); JavaScript — filter by tag
const res = await fetch('https://norskluftvern.no/api/articles.json');
const data = await res.json();
const patriotArticles = data.articles
.filter(a => a.tags.includes('patriot')); Python — build a category index
import requests
from collections import defaultdict
data = requests.get('https://norskluftvern.no/api/articles.json').json()
by_category = defaultdict(list)
for article in data['articles']:
by_category[article['category']].append(article)
for cat, articles in sorted(by_category.items()):
print(f"{cat}: {len(articles)} articles") Python — export all English articles to CSV
import csv, requests
data = requests.get('https://norskluftvern.no/api/articles.json').json()
en = [a for a in data['articles'] if a['lang'] == 'en']
with open('norsk-luftvern-en.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['slug','title','date','category','tags','url'])
writer.writeheader()
for a in en:
writer.writerow({**a, 'tags': ','.join(a['tags'])}) Adjacent resources
Full RSS 2.0 feed of all published articles, sorted newest-first. The push alternative to polling the JSON index — suitable for feed readers and news aggregators that support Atom/RSS subscriptions.
Includes: title, pubDate, description (excerpt), link, categories (category + tags), author.
Every article page includes an embedded <script type="application/ld+json"> block with Schema.org Article markup. Useful for scrapers that need per-article structured data — headline, author, dates, image, reading time, keywords — without consuming the full index.
Fields: @type Article, headline, description, datePublished, dateModified, inLanguage, url, timeRequired, author, publisher (with logo), image, keywords.
Sitemap index generated at build time. Covers all article pages, category pages, series pages, tag pages, and pagination routes. Use this to discover all URLs on the site for crawling or archival.
Every page on the site includes two <link rel="alternate"> tags in <head>: one for the RSS feed (type="application/rss+xml") and one for this JSON index (type="application/json"). Feed readers and tools that sniff for alternate representations will discover both automatically.
Usage guidelines
Attribution
When displaying or republishing content derived from this feed, please link back to
the original article URL (available as the url field on each record) and
credit Norsk Luftvern as the source.
Caching
The JSON file is regenerated on every content deploy. We recommend caching it for
one hour on the client side. The meta.generated timestamp
lets you detect whether a cached copy is stale.
Stability
All field names listed in the schema above are stable and will not be renamed or removed
without a changelog entry. New optional fields may be added without notice — write
your parser defensively. The articles array is always sorted newest-first.
No authentication or rate limits
The endpoint is a plain static file served from the same CDN as the rest of the site. There is no API key, no OAuth, and no enforced rate limit. Please apply reasonable polling intervals — polling more often than once per hour provides no benefit given the deploy cadence.
Changelog
/api/articles.json launched with full article index.
Fields: slug, url, title, date, excerpt, category, lang, author, tags, series,
crossSeries, featured, readingTime, heroImage.
Schema.org Article JSON-LD added to all article pages.
<link rel="alternate" type="application/json"> added to all page heads.