Quickstart

List the posts, then read one by slug:

curl https://mashprime.dev/api/v1/posts
curl https://mashprime.dev/api/v1/posts/one-folder-to-autonomy
curl "https://mashprime.dev/api/v1/search?q=memory"

Responses are JSON. Every endpoint, parameter and response schema is described in the OpenAPI 3.1 spec, which you can load straight into an LLM tool-calling layer: every operation has a unique operationId, a description and typed schemas.

Authentication

None. The API is public and read-only, so there are no API keys, tokens or accounts. Send requests from anywhere; CORS is open (Access-Control-Allow-Origin: *).

Endpoints

Base URL: https://mashprime.dev/api/v1

MethodPathoperationIdWhat it does
GET /api/v1 getApiIndex API index: version, documentation links, and available endpoints
GET /api/v1/site getSiteInfo Who Mash Prime is, what the site covers, and where the machine-readable resources live
GET /api/v1/posts listPosts List published blog posts, newest first
GET /api/v1/posts/{slug} getPost Read one blog post, including its full markdown text
GET /api/v1/search searchPosts Search blog posts by keyword across titles, descriptions, and full text

posts pages with optional limit (1–100) and offset, and reports total. search takes a required q (1–200 characters) and an optional limit. posts/{slug} returns the post's metadata plus its full text in markdown.

Errors

Every 4xx and 5xx response is an RFC 9457 application/problem+json object. Branch on the stable code; show detail to humans; follow hint to recover.

{
  "type": "https://mashprime.dev/developers/#error-post_not_found",
  "title": "Post not found",
  "status": 404,
  "detail": "No published post has the slug 'no-such-post'.",
  "instance": "/api/v1/posts/no-such-post",
  "code": "post_not_found",
  "hint": "Get valid slugs from GET /api/v1/posts.",
  "documentation": "https://mashprime.dev/developers/#errors"
}
StatuscodeMeaning and fix
400 invalid_slug Invalid post slug. Slugs are lowercase letters, digits, and hyphens. Get valid slugs from GET /api/v1/posts.
400 missing_query Missing search query. Pass a keyword in the q parameter, e.g. GET /api/v1/search?q=memory.
400 invalid_parameter Invalid query parameter. limit must be a whole number from 1 to 100; offset must be a whole number of 0 or more.
400 query_too_long Search query too long. Keep q to 200 characters or fewer.
404 not_found Resource not found. See GET /api/v1 for the available endpoints.
404 post_not_found Post not found. Get valid slugs from GET /api/v1/posts.
404 unsupported_version Unsupported API version. Supported versions: v1. Use paths under /api/v1/.
405 method_not_allowed Method not allowed. This API is read-only. Use GET (or HEAD / OPTIONS).
429 rate_limited Rate limit exceeded. Wait for the number of seconds in Retry-After, then retry. Watch the RateLimit header to stay under the limit.
500 internal_error Internal error. Retry with exponential backoff. If it persists, report it via https://mashprime.dev/contact/.
502 upstream_unavailable Content source unavailable. The site's content index could not be read. Retry with exponential backoff.

Rate limits

60 requests per 60 seconds per client IP. Every response, including errors, tells you where you stand:

RateLimit-Policy: "default";q=60;w=60
RateLimit: "default";r=57;t=42
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1790467242

RateLimit and RateLimit-Policy follow the IETF RateLimit header fields draft: r is requests remaining, t is seconds until the window resets. The X-RateLimit-* headers carry the same numbers, with X-RateLimit-Reset as Unix epoch seconds. Over the limit you get a 429 with code: "rate_limited" and a Retry-After header in seconds. Throttle when r gets low rather than waiting for the 429.

Versioning and deprecation

Currently deprecated: the unversioned /api/posts.json build index. It still works and has no sunset date yet; it sends Deprecation and a successor link to /api/v1/posts.

MCP server

A remote Model Context Protocol server gives Claude, ChatGPT and other agents the site as native tools. Transport: streamable HTTP (stateless). No auth.

Claude Code:

claude mcp add --transport http mashprime https://mashprime.dev/mcp

Clients that take a JSON config:

{
  "mcpServers": {
    "mashprime": {
      "type": "http",
      "url": "https://mashprime.dev/mcp"
    }
  }
}

CLI

mashprime is a zero-dependency Node CLI that reads the site from a terminal: mashprime posts, mashprime read <slug>, mashprime search <query>, mashprime mcp. It is built on this API and published on npm as mashprime (Node 18+). No install needed:

npx mashprime
npx mashprime read one-folder-to-autonomy

Or install it: npm install -g mashprime. The in-browser terminal runs the same commands.

Machine-readable files

FileWhat it is
/openapi.jsonOpenAPI 3.1 description of the Mash Prime API
/.well-known/api-catalogRFC 9727 API catalog (linkset)
/.well-known/mcp.jsonMCP server card
/llms.txtAgent-readable site index
/rss.xmlRSS feed of posts
/sitemap-index.xmlSitemap

Every HTML page also has a markdown variant: send Accept: text/markdown. This page's is /developers/index.md.

Sandbox

The API is read-only, so production is the sandbox: nothing you send can change anything. Try a request (it counts toward your rate limit).

GET /api/v1

Response status, rate-limit headers and body appear below.

// response will appear here