News API

One GET endpoint. One bearer token. Cyber-security stories from 28 outlets, rewritten into plain-language briefs and tagged by topic, as JSON.

Authentication

Send your key as a bearer token:

Authorization: Bearer cisoai_...

X-API-Key: cisoai_... is accepted as an alternative, because clients reach for it. Bearer is the documented form.

Keys belong on your server, never in a browser

Anything in client-side JavaScript is readable by every visitor. A key in a web page is a key anyone can take, and the usage bills to you. Call this API from your backend and serve the result to your own front end — there is a worked example of exactly that below.

The endpoint

GET https://cisoai.au/api/news

That is the whole API. There is no second endpoint, no SDK, and no OAuth flow.

Parameters

ParameterTypeDefaultDescription
limitinteger20 How many stories to return. Clamped to your plan's ceiling — asking for more is not an error, you simply receive the ceiling.
categorystring— Exact match on a story's category. See the list below.
sourcestring— Exact match on the publishing outlet, e.g. Dark Reading.
distinct1— Collapse duplicate coverage so one event does not fill the page with nine versions of itself. Useful for a feed; leave it off for analysis.

Categories

Threat Intelligence · Security News · Cybersecurity Research · Government Advisory · Industry News

Sources

The Hacker News, Infosecurity Magazine, CrowdStrike, Cisco Talos, Unit 42, Project Zero, Krebs on Security, Dark Reading, CISA, ASD's ACSC, and a financial wire whose per-story publisher is used as the source name. The live list is in every response under sources, so you never have to hard-code it.

Response

{
  "articles": [ /* see fields below */ ],
  "count": 20,
  "plan": "pro",
  "limit": 20,
  "fullBody": true
}

Article fields

FieldTypeDescription
headlinestringRewritten headline.
summarystringOne sentence.
bodystringThe full rewritten article, paragraphs separated by \n\n. Paid plans only.
keyTakeawaystringOne sentence of practical advice.
tagsstring[]Topic tags assigned at ingest.
categorystringOne of the categories above.
sourcestringPublishing outlet.
originalUrlstringThe original article. Link to this when you republish.
originalTitlestringThe headline as published by the source.
publishedAtISO 8601When the source published it. Never in the future.
createdAtISO 8601When we ingested it.
slugstringStable identifier. cisoai.au/brief/<slug> is the human-readable page.
idstringInternal identifier. Prefer slug.
imageUrlstringSource image where one exists, otherwise empty. Roughly two thirds of stories have one.

Fields are additive. Nothing already published gets renamed or removed without notice, so parsing defensively for new keys is safe and parsing strictly is not.

Free and paid

FreePaid
Stories per request20200
body (full article text)Not includedIncluded
FiltersYesYes
Rate limitFair use60 requests a minute
Key requiredNoYes
Endpointapi.cisoai.au/api/newscisoai.au/api/news

Paying buys two things: the full article text, and ten times as many stories per request. Everything else — the filters, the field names, the response shape — is identical, which is why the free tier works as a complete preview rather than a teaser. It needs no key and no signing up, and moving to a paid key is a header change and nothing else.

The rate limit is listed because it should not be a surprise after you have paid. The corpus only changes when ingest runs, every three hours, so 60 requests a minute is far above what reading it needs — if you are close to it, cache the response rather than asking us for a higher ceiling.

Pricing and keys →

Errors

StatusMeaningWhat to do
401No key sent, or the key is not recognised. Check the Authorization header. Retrying will not help.
403The key is known but not active — usually past_due after a failed payment. The body names the state. Update your card. Your key resumes working; you never need a new one.
405Method other than GET.Use GET.
429Over 60 requests in a minute on this key. Wait the number of seconds in Retry-After, then continue. Your key is fine. If you are hitting this, cache your responses — the corpus only changes every three hours.
502The feed is briefly unavailable upstream. Retry with backoff. Your last good response is still valid — the corpus only changes every three hours.
503We could not verify your key. This is our problem, not a bad key.Retry with backoff.

Errors return JSON with an error field. Never treat a 5xx as an authentication failure — the two are deliberately kept distinct so you are not chasing a key problem during an outage.

Examples

curl

curl "https://cisoai.au/api/news?limit=50&category=Threat%20Intelligence" \
  -H "Authorization: Bearer $CISOAI_API_KEY"

Node

// Server-side. Never ship the key to a browser.
const response = await fetch(
  "https://cisoai.au/api/news?limit=200",
  { headers: { Authorization: `Bearer ${process.env.CISOAI_API_KEY}` } }
);
if (!response.ok) throw new Error(`news api ${response.status}`);
const { articles } = await response.json();

Python

import os, requests

r = requests.get(
    "https://cisoai.au/api/news",
    params={"limit": 200, "distinct": 1},
    headers={"Authorization": f"Bearer {os.environ['CISOAI_API_KEY']}"},
    timeout=30,
)
r.raise_for_status()
articles = r.json()["articles"]

Serving it to your own front end

The pattern to copy: a small server-side route holds the key and your page calls that route same-origin. This is how bugxhunter.com renders its feed — a Cloudflare Pages Function that proxies, with the key in a secret and never in the markup.

// functions/api/news.js — your origin, your cache, your key stays server-side
export async function onRequest({ env }) {
  const upstream = await fetch("https://cisoai.au/api/news?limit=24", {
    headers: { Authorization: `Bearer ${env.CISOAI_API_KEY}` },
  });
  if (!upstream.ok) return new Response('{"articles":[]}', {
    headers: { "Content-Type": "application/json" },
  });
  return new Response(await upstream.text(), {
    headers: {
      "Content-Type": "application/json",
      "Cache-Control": "public, max-age=300",
    },
  });
}

Note the empty-list fallback rather than an error: a news section is worth degrading, not worth breaking a page over.

Limits and freshness

Managing your key

Attribution and terms

Briefs are rewritten summaries of publicly available reporting, not reproductions of it. Every record names its source and links the originalUrl.

Questions: hello@cisoai.au
Get a key  ·  Home  ·  Coverage analysis