Developer guide · REST v1

Bring Leafy news into your app.

Published articles, summaries, and source links for your CRM or website. Public, read-only access with no API key or account required.

Start with Leafy originals

This request returns up to 20 published Leafy original articles, newest first. Omit type=ORIGINAL to include source-linked news briefs and other categories. Drafts and archived items are excluded from both endpoints.

curl --get 'https://leafyupdates.com/api/v1/news' \
  --data-urlencode 'type=ORIGINAL' \
  --data-urlencode 'limit=20' \
  --header 'Accept: application/json'
GET /api/v1/news?limit=1&type=ORIGINAL

Loads one published article without signing in.

Response example

HTTP 200, application/json. This example article is illustrative. An empty feed returns {"items":[],"nextCursor":null}.

{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000001",
      "slug": "example-leafy-article",
      "articleUrl": "https://leafyupdates.com/news/example-leafy-article",
      "type": "ORIGINAL",
      "title": "Example Leafy article",
      "summary": "A short summary for your CRM news card.",
      "body": "## Example heading\n\nThe article body is Markdown.",
      "source": "Leafy Updates",
      "sourceType": "WEBSITE",
      "externalId": null,
      "url": "https://leafyupdates.com/news/example-leafy-article",
      "publishedAt": "2026-09-01T12:00:00.000Z",
      "effectiveAt": null,
      "updatedAt": "2026-09-01T12:00:00.000Z",
      "tags": [
        "original",
        "oklahoma"
      ],
      "media": {
        "imageUrl": "https://leafyupdates.com/brand/leafy-og-news-1200x630.png",
        "alt": "Leafy Updates news"
      }
    }
  ],
  "nextCursor": null
}

nextCursor is an opaque string when more articles are available, or null at the end.

Filters and pagination

GET https://leafyupdates.com/api/v1/news

type
Omit for all news. ORIGINAL selects Leafy articles; REGULATORY, RECALL, ENFORCEMENT, BUSINESS, and SPONSORED are also supported. Case-insensitive; unrecognized values return all types.
limit
Default 20; maximum 100. Positive integers set page size; values above 100 are capped and invalid or non-positive values use the default.
tag
Include a single exact tag, such as oklahoma, federal, or licensing. Case-insensitive.
excludeTag
Exclude a single exact tag. Use other-state to match the default news page’s geography filter.
cursor
Pass nextCursor from the previous response unchanged. Keep type, tag, excludeTag, and limit the same. Omit to start with the newest articles.

URL-encode parameter values. Tags accept up to 64 characters: letters, numbers, spaces, periods, ampersands, slashes, and hyphens, beginning with a letter or number. Invalid tag filters are ignored.

const url = new URL("https://leafyupdates.com/api/v1/news");
url.searchParams.set("type", "ORIGINAL");
url.searchParams.set("limit", "100");

let cursor = null;
do {
  if (cursor) url.searchParams.set("cursor", cursor);
  const response = await fetch(url, {
    credentials: "omit",
    headers: { Accept: "application/json" },
  });
  if (!response.ok) throw new Error("Leafy HTTP " + response.status);
  const page = await response.json();
  // Upsert page.items into your CRM, keyed by item.id.
  cursor = page.nextCursor;
} while (cursor);

Fetch one article

Use a slug returned by the feed. The response wraps the article in item and adds affectedEntities.

curl 'https://leafyupdates.com/api/v1/news/{slug}' \
  --header 'Accept: application/json'
Single-article JSON example
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000001",
    "slug": "example-leafy-article",
    "articleUrl": "https://leafyupdates.com/news/example-leafy-article",
    "type": "ORIGINAL",
    "title": "Example Leafy article",
    "summary": "A short summary for your CRM news card.",
    "body": "## Example heading\n\nThe article body is Markdown.",
    "source": "Leafy Updates",
    "sourceType": "WEBSITE",
    "externalId": null,
    "url": "https://leafyupdates.com/news/example-leafy-article",
    "publishedAt": "2026-09-01T12:00:00.000Z",
    "effectiveAt": null,
    "updatedAt": "2026-09-01T12:00:00.000Z",
    "tags": [
      "original",
      "oklahoma"
    ],
    "media": {
      "imageUrl": "https://leafyupdates.com/brand/leafy-og-news-1200x630.png",
      "alt": "Leafy Updates news"
    },
    "affectedEntities": []
  }
}

Article fields

id
Stable Leafy article ID. Use this as your CRM’s deduplication key.
slug / articleUrl
Slug for the detail request and an absolute link to the Leafy article page.
title / summary / body
Headline, nullable short summary, and nullable Markdown body. Source-linked briefs may have only a summary; the body is not a copy of the external source article.
type / tags
Article category and an array of topic or geography tags.
source / url
Source name and canonical source URL. For aggregated news, url can lead to another publisher. Use articleUrl to link to Leafy.
sourceType / externalId
Source channel (such as WEBSITE or GOVERNMENT) and a nullable upstream identifier. Use id, rather than externalId, for Leafy identity.
publishedAt / updatedAt
UTC ISO 8601 timestamps. Results are ordered by publication time descending, then ID descending. Editing an older article does not move it to the top.
effectiveAt
Optional effective date of the underlying event, or null.
media
Optional media object, or null. When available, imageUrl and alt can supply the card image. Resolve relative media URLs against https://leafyupdates.com.
affectedEntities
Array of affected identifiers, when available. Included only on the single-article response.

Keep your CRM feed current

  • Poll about every 15 minutes and cache the results. Successful responses can be cached for five minutes. This polling interval is a recommendation, not an API quota.
  • Start each polling run without a cursor. Follow pages until you reach your previously fetched publication range. Cursors walk older publications; they are not change-feed checkpoints.
  • Periodically reconcile the full feed, including all pages, for older edits and archived articles. updatedAt identifies edits on returned articles. The API does not emit deletion events or provide a snapshot across pages.
  • A missing, archived, or unpublished article returns HTTP 404 from its detail URL. Account for the five-minute cache window and retry transient failures before removing cached content.
  • Browser requests can read these public endpoints across origins. Use credentials: "omit"; no authorization header or cookies are needed.

Errors and display guidance

A malformed cursor returns HTTP 400 with {"message":"Invalid news cursor."}. An unavailable article returns HTTP 404 with {"message":"News item not found."}. Back off on network errors, HTTP 429, or server errors; honor Retry-After when present.

For news cards, show the title, summary, source, publication date, and a link to articleUrl. Preserve attribution and source links. Render Markdown with raw HTML disabled and safe link handling. Use a fallback when images or article bodies are missing.

External publishers retain rights to their material. Source-linked briefs provide context and links; they do not grant permission to reproduce the source publisher’s full article. Leafy’s terms of use apply.