Reference

The public API, such as it is

Merge & Tell publishes two things to the open internet without a login: the changelog feed an account owns, and the MCP server. This page documents the feeds, and the discovery endpoints that let a machine find either one without reading any of this.

Start here

Discovery

Three URLs, none of which need a key:

  • /.well-known/api-catalog is the catalog defined by RFC 9727. It lists every public API on this domain as an RFC 9264 linkset, served as application/linkset+json.
  • /openapi.json is the OpenAPI 3.1 description of everything below.
  • /status.json answers 200 when the datastore behind the feeds is reachable and 503 when it is not, naming the check that failed either way.

The catalog names two APIs: the changelog feeds, documented below, and the MCP server. Each entry anchors on the API and links its description, its documentation and its health check. The changelog entry reads like this.

{
  "anchor": "https://merge.tel/changelog",
  "service-desc": [
    { "href": "https://merge.tel/openapi.json",
      "type": "application/openapi+json" }
  ],
  "service-doc": [
    { "href": "https://merge.tel/docs/api", "type": "text/html" }
  ],
  "status": [
    { "href": "https://merge.tel/status.json",
      "type": "application/json" }
  ]
}

The API

The changelog feeds

Every account gets a changelog it owns, at /changelog/<accountId>. Add .json to the last path segment for JSON Feed 1.1 instead of Atom. Add a social set id for that set’s entries alone. The format lives in the path rather than an Accept header so each URL is its own cache key and pastes into a reader without ambiguity.

# Atom, the whole account
curl https://merge.tel/changelog/<accountId>

# JSON Feed 1.1, same entries
curl https://merge.tel/changelog/<accountId>.json

# One social set only
curl https://merge.tel/changelog/<accountId>/<setId>.json

Newest first, up to 50 entries. The account-wide feed carries every published entry whatever set it went out under, including the ones filed under none. Adding sets narrows nothing that was already there. Your own feed URL is on the changelog screen inside the app; our updates page is this same endpoint pointed at us, if you want to see one running before you have an account.

Access

Auth, CORS and limits

There is no key and no token. The uuid in the path is the credential: it is random, it is not derived from your account name, and anyone holding it can read that one feed and nothing else. Treat a feed URL the way you would treat an unlisted link, and share it as widely as you would like the changelog read.

Browsers can read the feeds cross-origin. By default the response carries Access-Control-Allow-Origin: *, so a widget on any site can fetch one. An operator who sets an origin allow-list on their account narrows that to the listed origins, and every other origin gets no header and is blocked by the browser. Preflights are answered on the same URLs.

Feeds are cached publicly for five minutes. There is no published rate limit; poll on the cache interval and nobody will ever have to write one.

Failure

Errors

An empty changelog is a 200 with no entries, so a feed URL can be subscribed to before the first entry exists. That makes the other codes mean something specific:

  • 404: no such account or set, or a path segment that is not a uuid. A set id belonging to a different account is a 404 too, not an empty feed that looks like agreement.
  • 500: the feed could not be read. The changelog is down. Do not treat this as “nothing published today”.

If you are polling on a schedule, that distinction is the whole reason /status.json exists. Check it before you conclude that a quiet feed means a quiet week.

Scope

What is not here

No write API over HTTP, and no read API for anything inside an account: drafts, the queue, connected accounts and pull request data all need a session and live under /app. If you want to read or change those from a program, that is what the MCP server is, and it has its own auth and its own scopes.

The inbound webhook endpoints under /api are callbacks that GitHub, Stripe and Postmark post to with a shared secret. They are not endpoints you can call, and they are deliberately absent from the catalog.

If you want something in this list, say so. The catalog is the place new public endpoints will show up first.

Public API — Merge & Tell