# Edgepedia API

More than 500,000 encyclopedia articles and constantly growing, as JSON. Free. No key, no sign-up. Commercial use with credit. AI training open to everyone.

## Try it

- [www.edgepedia.org/api/v1/search?q=koala](https://www.edgepedia.org/api/v1/search?q=koala)
- [www.edgepedia.org/api/v1/articles/koala](https://www.edgepedia.org/api/v1/articles/koala)
- [www.edgepedia.org/api/v1/random](https://www.edgepedia.org/api/v1/random)
- [www.edgepedia.org/api/v1/topics](https://www.edgepedia.org/api/v1/topics)

Read routes use GET; migration, batches, and text you send use POST. Every route answers JSON to any program or web page (CORS allows every origin). Machine-readable description: [/openapi.json](https://www.edgepedia.org/openapi.json), with an example answer for every route; the same in OpenAPI 3.0, function definitions for models, TypeScript types, and request collections are listed under Generated files, below.

## Reference cards

An article's title, full summary, and Edgepedia credit in a card for your website.

`/embed/{id}?theme=auto` serves a card by its canonical article ID. Appearance can be `auto`, `light`, or `dark`. The optional `/assets/edgepedia-embed.js` script fits the frame to its contents; without it the frame remains readable and scrollable. Cards use published summaries and require no key or sign-up.

`/embed/{slug}` works too: it redirects to the card at the article's ID, keeping the theme. Edgepedia is also an oEmbed provider: `GET /oembed?url={article or card URL}&format=json` returns the same embed code as the builder above as `html`, with the title, width, and height; `maxwidth` and `maxheight` are honored. Every General article page links its oEmbed address in its `<head>`, so WordPress, Discourse, and other oEmbed consumers turn a pasted Edgepedia link into a card.

## Routes

| Route | Returns |
|---|---|
| `/api/v1/search?q=words` | Matches titles and other names, best first. Search for a subject's name, not a question. Each result: id, title, top-level topic, preview text, links, and how it matched (`match`, `confidence`). Words that name a topic, like "science fiction writers", also return `topics`, a link to its articles. `limit` is the page size, 1 to 30 (default 10); `page` turns pages, and a page past the end is empty. Other names and misspellings work: "zhu yuanzhang" finds the Hongwu Emperor, and "siddartha" returns `did_you_mean`. More options: Search, below. |
| `/api/v1/articles/{slug}` | The article as Markdown, its topic path, its places on the geography tree (`geo`), its last-updated date, and the credit line to show. Any name works (`Mount_Fuji`, a title, a whole address), and options return a section, an outline, passages, or other forms: Reading an article, below. |
| `/api/v1/articles?id={id}` | The same, by id. Old article ids continue resolving after a corpus migration; topic ids can change when the tree is revised. An address can move; the old one still answers, with `moved_from`. `ids=` takes up to 10 at once. |
| `/api/v1/leads?ids={id},{id}` | Up to 50 articles by id, each as a search result (id, title, top-level topic, preview text, links), for a page of cards. Migrated and merged ids return the survivor, keyed by the requested id; the result's `id` is canonical. Unknown or unavailable ids are left out. |
| `/api/v1/random` | One random article. `new=1` picks from the newest articles; `topic=` or `geo=` picks under a node. |
| `/api/v1/related/{slug}` | An article's neighbors in one call: up to 10 nearest it in its own topic, 3 from each of up to 8 neighboring topics, and up to 10 nearest it in each geography node it sits in. Also `?id={id}`. `by=links` gives the articles cited together with it instead. |
| `/api/v1/topics` | The top of the topic tree. |
| `/api/v1/topics/{id}` | A topic's path, its sub-topics with article counts, and every article under it, 30 to a page. `format=mermaid` draws its subtree. |
| `/api/v1/geo` | The geography tree: its regions, each with its periods. |
| `/api/v1/geo/{id}` | A geography node, shaped like a topic: its path, narrower nodes, and articles, 30 to a page. A region lists its periods only. |
| `POST /api/v1/ids/translate` | With the v1.5 migration enabled: send `{"ids":["old-id", "another-id"]}` (up to 500 distinct ids). The response maps moved ids to their canonical survivors; unchanged or unknown ids are omitted. Checkpoint completed batches and honor `Retry-After`. |

Preview text uses the corpus snippet when available and the article opening otherwise. Records and results with a snippet also include it as `snippet`; `markdown` remains the full article text. `node`, when present, is the article's current concept-tree node.

Every article is also Markdown at its own address. Add `.md`: [www.edgepedia.org/koala.md](https://www.edgepedia.org/koala.md).

## MCP server

`https://www.edgepedia.org/mcp`. Add it to Claude as a custom connector, to ChatGPT with Developer mode on, to [VS Code](https://vscode.dev/redirect/mcp/install?name=edgepedia&config=%7B%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fwww.edgepedia.org%2Fmcp%22%7D) or [Cursor](https://cursor.com/install-mcp?name=edgepedia&config=eyJ1cmwiOiJodHRwczovL3d3dy5lZGdlcGVkaWEub3JnL21jcCJ9) in one click, or to any other MCP client by its address. No key, no sign-in. Five read-only tools: `search` (a subject's name in, matching articles out, and a topic when the words name one), `fetch` (one article as Markdown, with its credit line, topic path, and geography; `citations: false` for a text about a quarter shorter; a `topic:` id lists that topic's parent, narrower topics, and articles, 120 to a `page`; `topic:root` and `topic:geo` are the tops of the topic and geography trees), `related` (an article's neighbors in its topic, nearby topics, and geography; `by: "links"` for the articles cited with it), `connect` (`from`, `to`: the chain of links between two articles, as `/api/v1/path` gives it), and `resolve` (`name`, with optional `context` and `type`: the article a name most likely means, as `/api/v1/resolve` gives it). When no title matches a `search`, articles whose text does follow the title matches, marked `match: fulltext`, within `limit` and counted in `pages`. A tool error is text the model reads (with `did_you_mean` ids for an id no article has); its code rides `_meta["ai.edgechat/error"]`, never `structuredContent`. `fetch` with `links: "in"` takes `links_page` for the next 30 articles linking there.

`search` takes `limit` (1 to 30, default 10), `page`, `first`, `topic`, and `sort`, and answers `page` and `pages`; `fetch` takes the article options below and `ids` for several at once. Every result carries `canonical_id`, the article's permanent id: `fetch` takes it, and when an id or address you stored has moved, `fetch` answers the article with `moved_from` set to what you asked for. Results name the corpus release in `_meta.corpus_version`. Clients on protocol 2025-06-18 or later also get one `resource_link` per article.

Resources: `edgepedia://article/{slug}` (an article as Markdown, the same text as `fetch`) and `edgepedia://topic/{id}` (a topic's narrower topics and articles), with completion for both; completion also suggests article titles for any argument that names an article. The Agent Skill is served over MCP too (`skills/list`, `skills/get`), as `skill://edgepedia/SKILL.md`. A `GET` of `/mcp` returns the server card as JSON. Clients that accept only `text/event-stream` get each answer as one SSE `message` event. The tool listing's sha256 rides each answer's `_meta` (`ai.edgechat/tools-sha256`), so a change to a tool's description is visible.

Windows (preview, build 26220.7262 or later): `odr.exe mcp add --uri https://www.edgepedia.org/mcp`. Setup lines for every other client, an Agent Skill, and examples: [github.com/EdgePlat/edgepedia-mcp](https://github.com/EdgePlat/edgepedia-mcp).

No MCP, or a client that speaks only the older SSE transport? Give your model two functions that call `/api/v1/search` and `/api/v1/articles/{slug}`, or take them ready-made from [/tools.json](https://www.edgepedia.org/tools.json). The older transport's addresses (`/sse`, `/mcp/sse`) answer 404 with a body naming `https://www.edgepedia.org/mcp`.

## Limits

600 requests a minute and 100,000 a day per IP address, the API and the MCP server alike. Every answer names both windows in `RateLimit-Policy`. Past them, the API answers 429 with `Retry-After` and `RateLimit`; an MCP tool call answers a tool error whose `retry_after` gives the seconds. The counts are kept per server instance, so they are a ceiling to stay under, not an exact meter. Please cache. Translation counts each requested id separately; `/leads` batches that probe old ids are charged per old id too. Other batches count each id or name as one request, and annotate one per 1,000 characters.

## License

[Edgepedia Community License 1.0](https://www.edgepedia.org/edgepedia/license): free with credit, commercial use included. AI training is open to everyone, and a model's output needs no credit. For other uses, organizations over USD 100 million in revenue or 100 million monthly users license separately.

Credit: show each article's `credit` line, with its link, wherever you show its text. Article answers also carry it ready to paste as `credit_md` and `credit_html`, and `license.spdx` (`LicenseRef-Edgepedia-Community-1.0`). API article and lead answers carry `Link: <https://www.edgepedia.org/edgepedia/license>; rel="license"` and `X-License: LicenseRef-Edgepedia-Community-1.0`.

The EdgeChat app, its Edge Apps, and our software are free of charge but proprietary: no source code is provided, and they may not be copied, modified, or redistributed ([EdgeChat License Agreement](https://www.edgechat.ai/eula)).

## Errors

JSON: `{ "error": { "code": "not_found", "message": "…" } }`. 400 missing `q`, 404 not found, 410 removed, 413 text too long, 429 too many requests, 503 try again. A 404 names the next call: `hint`, `next` (a URL), and, for an article address that answers nothing, `did_you_mean` with the three closest titles. The MCP `fetch` tool's not-found error carries the same `did_you_mean`.

## Changes

Version 1 keeps its shape: fields may be added, never renamed or removed. Edgepedia's own changes are at [/edgepedia/updates](https://www.edgepedia.org/edgepedia/updates). When a release reorganizes the topic tree, as 1.8.0 did, a topic id that moved answers 301 with its new id, and `/api/v1/changes?since=<release>` lists every article added, changed, moved, or removed since that release.

[/api/v1](https://www.edgepedia.org/api/v1) reports `corpus_version`, `corpus_updated`, and `release_notes`. These identify the published General-corpus release and its release date, not the date every article was last edited. The same metadata appears in MCP server instructions. Corpus releases do not change the API or MCP software version. `id_policy` there says what an id promises: ids can be renumbered or merged by a release, as 1.5 did, and old ids keep answering, through a 308 and `POST /api/v1/ids/translate`.

Something broken? [Report it](https://www.edgechat.ai/bugreport).

## Reference

Routes and fields read from derived data (importance, reading grades, links, dates, other names, and the full-text index) answer 503 with `Retry-After`, or leave the field out, until that data is published with the store.

### Reading an article

`/api/v1/articles/{slug}` and MCP `fetch` take these options; without them the answer is the whole article, as always.

| Option | Returns |
|---|---|
| `section={heading}` | One section, by its heading or a word of it (`section=etymology` finds "Name and etymology"; `section=lead` is the opening), with its subsections. An unknown heading answers 404 with the article's `sections`. |
| `outline=1` | `outline`: every heading with its size in tokens. |
| `max_tokens={n}` | The text cut to about n tokens at a section or paragraph boundary, with `tokens_estimate`, `truncated`, and `next_cursor`; pass it as `cursor` with the same `max_tokens` for the rest. |
| `length=snippet`, `length=lead` | The snippet, or the title and opening paragraph, in place of the whole text. |
| `format=text`, `html`, `jsonld`, `turtle`, `tables` | The answer as plain text, the rendered body, or JSON-LD or Turtle of its public fields; `tables` gives each table as `columns` and `rows`, as `csv`, and with its citations moved into `cites` and `sources`. |
| `chunks=1` | `chunks`: the article as paragraphs, each with a stable id from its heading path (`geology-2`) and a `cite_url`. |
| `q={words}&k={1–10}` | `passages`: the k paragraphs (default 3) that best match the words, each with a `cite_url`. |
| `quote={sentence or chunk id}` | `cite_url`: the article's address with a text fragment that opens the page at that passage; `quote_found` says whether the article holds it. |
| `cite={format}` | `cite`: a reference to the article, as `/api/v1/cite` gives it. |

Every article answer also carries `speakable` (the snippet as a voice assistant can read it). `importance` and `rank` (PageRank over the links between articles; 1 is the most central; a link count, not a judgment of the subject), `words`, `reading_grade` (Flesch-Kincaid), and `reading_minutes` come only when `fields=` names them (`?fields=title,importance,rank`), so a plain fetch looks nothing up; MCP `fetch` always has them. `next=1` adds up to 5 articles to read next. `citations=false` gives [n] markers in place of the inline source links, in `markdown`, `chunks`, and `passages`, as MCP's `citations: false` does. An address no article holds is read as an article's id (`/api/v1/articles/ep7rbwcy0a`) or as its title, case and accents aside (`/api/v1/articles/paris`); a lowercase hyphenated address looser than that is a 404 unless you add `?suggest=1`, while an address with capitals, spaces, or underscores (`/api/v1/articles/Albert_Einstein`) is read as a name, so a near miss returns the best search match with `resolved_by: search`. When the name you gave is not the article's address, the answer says how it was read (`resolved_from`, `resolved_by`: address, title, or search) and lists the 3 `nearest` other articles. `/api/v1/articles?ids={slug or id},{name}` returns up to 10 as `articles` (each with the name it answers as `asked`) and `missing`; every option applies to each.

### Citing an article

`/api/v1/cite/{slug}?format=` gives a reference in `csl` (CSL-JSON, the default), `bibtex`, `ris`, `apa`, `mla`, `chicago`, or `harvard`, with the credit line as text, Markdown, and HTML; `/api/v1/cite?ids={id},{slug}` does the same for up to 50. The author is Edgepedia (EdgeChat); APA, MLA, Chicago, and Harvard mark the italic title with asterisks, as Markdown does. Reference cards carry the same citation invisibly, as COinS and JSON-LD, for reference managers.

### Search

| `match` | When | `confidence` |
|---|---|---|
| `exact` | The title is the query. | 1.0 for the first such result, 0.9 for a later one |
| `alias` | Another name, or the title's initials ("mlk"), matched. | 0.8; 0.7 for a first result holding no query word; 0.6 for a transliterated query |
| `misspelling` | The search corrected the query (`did_you_mean`). | 0.5 × the share of the typed query the correction kept |
| `partial` | Some query words are in the title, or only in the text. | 0.2 + 0.5 × the share of query words in the title; 0.2 for text only |
| `fulltext` | No title or other name matched, so the articles' text was searched (BM25): a description finds the article whose name you do not know. | at least 0.2 |
| `none` | Nothing matched. The answer is empty. | 0 |

Confidence is a fixed rule, not a calibrated probability; an answer whose best result scores below 0.2 comes back empty. Each result carries `highlight`, the sentence of its summary that holds the most query words. A search that finds nothing is tried once more in Latin letters (Cyrillic, Greek, kana, and Hangul transliterated, pinyin tone numbers dropped, doubled romaji vowels shortened), and the answer names it as `searched_as`. Chinese characters are not transliterated.

| Option | What it does |
|---|---|
| `first=true` | Only the best match, or none. For glossaries and hover cards. |
| `topic={id}`, `geo={id}` | Only articles under that topic or geography node; `geo` filters every match up to 1,000, and `scope` says how far the answer reaches. |
| `sort=central` | The most-linked subjects first, among every match up to 1,000. |
| `max_grade={grade}` | Only articles at or below that reading grade. |
| `facets=1` | Counts of the matches by top-level topic and by geography region, over every match up to 1,000 (`facets.counted`). |

### Every answer

`fields=a,b` keeps only those keys of each result (or of the answer, when it has no results); the envelope (`total`, `page`, `next`, `license`) stays. A 200 that can be cached carries an `ETag`: send it back as `If-None-Match` and an unchanged answer is a `304` with no body. `Last-Modified` is the corpus release date and only informational. `Edgepedia-Corpus-Version` names the corpus release, and `Content-Digest` is the SHA-256 of the body (RFC 9530); an article's `.md` carries both too.

### More routes

| Route | Returns |
|---|---|
| `/api/v1/articles?after={id}&limit={1..1000}` | Every General article, walked in a fixed order: `{id, slug, title, api_url}` and `next` (null at the end). `after=` empty starts at the beginning, and a walk resumes after any id, even a removed one. |
| `/api/v1/trees`, `/api/v1/trees/topic`, `/api/v1/trees/geo` | The topic and geography trees whole: `nodes: [[id, label, parent index, own articles]]`; an id beginning with a dot continues its parent's id. |
| `/api/v1/releases` | Corpus releases, newest first, and `current`. |
| `/api/v1/health` | `application/health+json`: `pass`, `warn`, or `fail` (503). |
| `/api/v1/manifest` | A redirect to one gzip JSONL file, a line per article: `{ id, slug, title, updated, sha256, topic }` (`sha256` of the article's `.md`). Fetch it once to mirror Edgepedia. The checksum is of the published text, before reader fixes: an article a reader-reported fix has changed since the release will not match it until the next release. |
| `/api/v1/changes?since={release}` | The change files from that release to the current one, in order (the feed starts at 1.5: `since=1.5` is the earliest); each line is `{ op, id, … }`, `op` one of `added`, `changed`, `moved` (`from_slug` is the old address), or `removed`. |
| `/api/v1/events/{slug}` | The sentences of an article that state a date: `{ date, precision, text, para }`, `date` as `YYYY`, `YYYY-MM`, or `YYYY-MM-DD` (negative before the common era: `-0044-03-15`). BC dates follow the historical convention, not astronomical years: `-0044` is 44 BC (a standard ISO 8601 parser would read it as 45 BC). The sentence is the evidence: read it before you treat the date as a fact. |
| `/api/v1/aliases/{id}` | Other names of an article, including the acronyms the articles state ("NASA"); misspellings and case variants are left out, and of two spellings of one name the undotted is kept ("WHO", not "W.H.O."). |

### Resolve, annotate, and reconcile

Free text in, article ids out, with no model and no embeddings. Text sent to annotate, classify, and geoparse is never logged or kept.

| Route | Returns |
|---|---|
| `/api/v1/resolve?name=Mercury&context=planet` | The article a name most likely means: `result`, `confidence`, `ambiguous`, `match` (`exact`, `alias`, `anchor`, `partial`, or `none`), and `alternatives`. `type=` keeps candidates under one topic id (when none of the name's first 30 matches sits there, a single name looks through its next 60); `limit=` 1 to 10. `POST` takes up to 50: `{ "names": ["Paris", "Koala"] }` or `{ "queries": [{ "name": "Mercury", "context": "planet" }] }`. A name alone that does not settle one article answers `ambiguous: true` with the best guess as `result`; pass `context` to choose. |
| `/api/v1/surface?form=mercury` | Every article the corpus's own links meant by this exact phrase, with link counts and each one's share (`commonness`). |
| `/api/v1/suggest?prefix=koa` | The article titled exactly so first, then one another name names exactly, then titles beginning with the prefix, then other names that do (`matched` gives that name), for search boxes and voice interfaces. |
| `POST /api/v1/annotate` | `{ "text": "…" }` (at most 20,000 characters): each linked phrase with its offsets (`start`, `end`, in UTF-16 code units, as JavaScript indexes strings: in Python, a character outside the Basic Multilingual Plane, such as an emoji, counts as two), article, and confidence. `?format=html` also returns the text, HTML-escaped, with each phrase linked. |
| `POST /api/v1/classify` | `{ "text": "…" }`: the topics the text is about, scored by the topic paths of the articles it mentions, and the top-level shares. |
| `POST /api/v1/geoparse` | `{ "text": "…" }`: the places and periods it names, on the geography tree (`nodes`, `regions`, `places`, `periods`); the tree's non-geographic branch (`geo.nongeo`) is never a place. |
| `/api/v1/mentions?term=CRISPR` | Articles that mention a subject without linking to its article; `complete: false` means the list of linking articles was cut. |
| `/api/v1/reconcile` | A [Reconciliation Service API 0.2](https://www.w3.org/community/reports/reconciliation/CG-FINAL-specs-0.2-20230410/) endpoint: the manifest, batch `queries` (GET or POST), entity, type, and property suggest, a preview, and data extension (`title`, `url`, `excerpt`, `topic`, `topic_path`, `importance_rank`). JSONP with `callback=`. In OpenRefine: Reconcile › Start reconciling › Add standard service, and paste `https://www.edgepedia.org/api/v1/reconcile`. |

### The link graph, dates, and lists

Every article links to others in its text. These routes read that graph, the dates in the articles, and the two trees. Diagrams (`format=mermaid`) are Mermaid text for a host that renders it.

| Route | Returns |
|---|---|
| `/api/v1/links/{slug}` | The article's links to other articles, in reading order, each with its anchor text and sentence. |
| `/api/v1/backlinks/{slug}?page=` | The articles that link to it, 30 a page, the most important first, with their anchor text. |
| `/api/v1/path?from=&to=` | The shortest chain of links between two articles (at most 6 hops, avoiding hubs where it can), with the sentence that makes each hop. The MCP server calls it `connect`. |
| `/api/v1/compare?a=&b=` | Two articles side by side: leads, topic paths, the deepest topic they share, the chain between them, shared and own links, and each one's Key facts table. |
| `/api/v1/graph/{slug}?depth=1\|2&limit=` | Up to `limit` (default 50, at most 200) of its most important neighbors, and every link among them. `complete: false` (here, on backlinks, and on rank/top) means the route's time budget of about a second cut the answer short; such an answer is cached for a minute only. |
| `POST /api/v1/context` | `{ "ids": [...] }`, up to 50 ids or addresses (as `/rank?ids=` and `/leads?ids=` also take them): the links among them, the articles most of them link with, the deepest topic and place they share, and each one's lead. |
| `/api/v1/rank?ids=`, `/api/v1/rank/top?topic=&limit=` | Importance by PageRank: `pr` sums to 1 over the corpus, rank 1 is the most central. Note the names: `importance` on /search and articles is this rank as a 0-to-1 percentile; /resolve's `importance` is the raw `pr`, and /leads' is `{ pr, rank }`. |
| `/api/v1/timeline?topic=\|geo=&from=&to=` | Dated sentences from a topic's or a place's articles, oldest first, 50 a page; years negative for BC. A node keeps at most 200 events spread over its dates, and `from` and `to` filter that sample; an answer drawn from a full sample says `sampled: true` and its `cap`, and its `total` counts the sample. |
| `/api/v1/onthisday?date=MM-DD`, `/api/v1/year/{year}` | Events on a day of the year (today in UTC by default), or in one year (-9999 to 2100). A day holds at most 500 events and a year 2,000; a full one says `sampled: true`. |
| `/api/v1/featured?date=`, `/api/v1/featured.xml` | The featured article of the day (the landing's Today's fact), and an Atom feed of the last ten days. |
| `/api/v1/list?topic=\|geo=&period=&type=person` | Articles of a topic, or of a place and period (TBC, T500, T1000, T1800, T1946, T2001, T2021, NODATE), 30 a page; `type=person` keeps the people. A geography list's rows carry `geo` and no `id` (fetch the article for it). |
| `/api/v1/keyterms?topic=\|geo=&limit=` | Titles and other names for a subtree, to prime a speech recognizer. |
| `/api/v1/stats?topic=\|geo=&by=period` | Counts only: articles, links, and other names for the corpus or a node and its children. Here `articles` counts distinct articles; on `/geo` and `/trees/geo` it counts placements, so an article in two periods of a region counts twice there. |

### Discovery and other protocols

- MCP server card: [/.well-known/mcp/server-card.json](https://www.edgepedia.org/.well-known/mcp/server-card.json) (also `/mcp/server-card`): name, endpoint, tools, and versions, without connecting. Registry configuration: `/.well-known/mcp/config-schema.json` and `/.well-known/mcp/examples.json`.
- AI catalog: [/.well-known/ai-catalog.json](https://www.edgepedia.org/.well-known/ai-catalog.json): every way in (MCP, this API, A2A, NLWeb, and the Agent Skill) with example queries.
- API catalog: [/.well-known/api-catalog](https://www.edgepedia.org/.well-known/api-catalog), an RFC 9727 linkset naming this API, its description, and these docs.
- Agent Skill: [/.well-known/agent-skills/index.json](https://www.edgepedia.org/.well-known/agent-skills/index.json) lists `SKILL.md` with its sha256 digest.
- OpenSearch: [/opensearch.xml](https://www.edgepedia.org/opensearch.xml) adds Edgepedia as a search provider.
- A2A: `https://www.edgepedia.org/a2a` (JSON-RPC; A2A 1.0 `SendMessage` and 0.3 `message/send`; card at `/.well-known/agent-card.json`). A subject's name returns the top five articles; an article's address returns the article as Markdown with its credit line. The answer is always a message, never a task, and the same methods are answered on `/mcp`.
- NLWeb: `https://www.edgepedia.org/ask?query=Mount%20Fuji` (GET, or POST with a JSON or form body) answers in NLWeb's list shape, a schema.org `schema_object` per result; `streaming=true` sends the list as server-sent events. No model is called.
- Machine forms of an article: its address answers the form an `Accept` header names: `text/markdown` (with an `x-markdown-tokens` estimate), `application/json` (this API's answer), or `application/ld+json`; anything else gets the page. Article pages carry a `Link` header naming these forms, the license, the API catalog, and the OpenAPI description.

### Generated files

Built from [/openapi.json](https://www.edgepedia.org/openapi.json), so they never drift from it.

| File | What it is |
|---|---|
| [/openapi-3.0.json](https://www.edgepedia.org/openapi-3.0.json) | The same description in OpenAPI 3.0.3, for tools that do not read 3.1. |
| [/arazzo.json](https://www.edgepedia.org/arazzo.json) | An Arazzo 1.0 workflow: search, fetch the best match, then its related articles. |
| [/tools.json](https://www.edgepedia.org/tools.json) | Every JSON route as a function a model can call, in OpenAI, Anthropic, and Gemini formats, and as JSON Schema with its route. |
| [/edgepedia.d.ts](https://www.edgepedia.org/edgepedia.d.ts) | TypeScript types for every answer and every route's parameters. |
| [/edgepedia.postman_collection.json](https://www.edgepedia.org/edgepedia.postman_collection.json), [/edgepedia.bruno.json](https://www.edgepedia.org/edgepedia.bruno.json), [/edgepedia.insomnia.json](https://www.edgepedia.org/edgepedia.insomnia.json), [/edgepedia.http](https://www.edgepedia.org/edgepedia.http) | One example request per route for Postman, Bruno, Insomnia, and VS Code or JetBrains. |

Please send a `User-Agent` that names your program, as the collections do (`edgepedia-collection/1`).
