Markdown document API

Keep Markdown in the cloud and read it back over plain HTTP — from a script, a CI job, or an agent. Raw .md URLs, content negotiation, and conditional writes so two writers cannot silently overwrite each other.

Authentication

Send a token as a bearer credential. Tokens begin mdt_, carry the scopes you chose when creating them, and can be revoked at any time from your settings.

List your documents
curl https://www.markdowntools.io/api/v1/documents \
  -H "Authorization: Bearer $MDT_TOKEN"

Every response includes RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. A 429 carries Retry-After.

Endpoints

MethodPathDoesScope
GET/api/v1/documentsList your documents, newest first.documents:read
POST/api/v1/documentsCreate a document from JSON or raw Markdown.documents:write
GET/api/v1/documents/{id}Read one document as JSON or Markdown.documents:read
PUT/api/v1/documents/{id}Replace the content. Requires If-Match.documents:write
PATCH/api/v1/documents/{id}Change title, star or trash state.documents:write
DELETE/api/v1/documents/{id}Delete a document permanently.documents:write
POST/api/v1/documents/{id}/sharePublish a read-only link.documents:write
DELETE/api/v1/documents/{id}/shareWithdraw the link.documents:write
POST/api/v1/import-urlImport Markdown from a public URL.documents:write
GET/api/v1/accountExport every document you hold.documents:read

Creating and reading

Both JSON and raw Markdown bodies are accepted, so a shell pipeline does not have to wrap a document in an object just to send a document.

Create from a file
# Straight from a file — the body is the document
curl -X POST https://www.markdowntools.io/api/v1/documents \
  -H "Authorization: Bearer $MDT_TOKEN" \
  -H "Content-Type: text/markdown" \
  -H "X-Document-Title: Release notes" \
  --data-binary @NOTES.md
Read as JSON or as Markdown
# JSON, with metadata
curl https://www.markdowntools.io/api/v1/documents/$ID \
  -H "Authorization: Bearer $MDT_TOKEN"

# The same document as raw Markdown
curl https://www.markdowntools.io/api/v1/documents/$ID \
  -H "Authorization: Bearer $MDT_TOKEN" \
  -H "Accept: text/markdown"

Conditional writes, so nothing is lost

The ETag is the document revision. A PUT must state the revision it is replacing, and the write fails rather than clobbering an edit made in the meantime.

Read, then write conditionally
# Read, and keep the ETag
ETAG=$(curl -sI https://www.markdowntools.io/api/v1/documents/$ID \
  -H "Authorization: Bearer $MDT_TOKEN" | grep -i '^etag:' | cut -d' ' -f2 | tr -d '\r')

# Write only if nobody else has since
curl -X PUT https://www.markdowntools.io/api/v1/documents/$ID \
  -H "Authorization: Bearer $MDT_TOKEN" \
  -H "Content-Type: text/markdown" \
  -H "If-Match: $ETAG" \
  --data-binary @NOTES.md
# 412 Precondition Failed means it changed; re-read and merge.

Sharing and raw URLs

A published document is readable with no credential — by .md suffix, or by asking for Markdown at the page URL. Responses carry Vary: Accept, so caches keep the two representations apart.

Publish and fetch
# Publish, then read it back with no credential at all
curl -X POST https://www.markdowntools.io/api/v1/documents/$ID/share \
  -H "Authorization: Bearer $MDT_TOKEN"

curl https://www.markdowntools.io/d/$SHARE_ID.md
curl https://www.markdowntools.io/d/$SHARE_ID -H "Accept: text/markdown"

CLI and MCP server

The same API, packaged. @swarmclawai/markdowntools on npm is a command line that pulls your documents into a folder and pushes edits back with conditional writes, and an MCP server that gives Claude Desktop, Claude Code, Cursor or any other MCP client tools to list, read, search, create, update and share documents. It is a thin adapter over the endpoints above — nothing it does is out of reach of curl.

Pull, edit, push
npx @swarmclawai/markdowntools login              # paste a token once; kept in ~/.config/markdowntools
npx @swarmclawai/markdowntools pull ./docs --all   # every document as <title>.md, plus a manifest
npx @swarmclawai/markdowntools push ./docs         # changed files go up with If-Match; a 412 is reported, never overwritten

pull writes a .markdowntools.jsonmanifest next to the files with each document's id and revision. push reads it back as If-Match, so a document edited elsewhere in the meantime is reported as a conflict with both versions intact. The token lives in MARKDOWNTOOLS_TOKEN or ~/.config/markdowntools/config.json, readable by you only.

Connect an agent
# Claude Code
claude mcp add markdowntools -e MARKDOWNTOOLS_TOKEN=mdt_... -- npx -y @swarmclawai/markdowntools mcp

# Claude Desktop or Cursor: an mcpServers entry
{
  "markdowntools": {
    "command": "npx",
    "args": ["-y", "@swarmclawai/markdowntools", "mcp"],
    "env": { "MARKDOWNTOOLS_TOKEN": "mdt_..." }
  }
}

The server's update_document tool takes the revision the agent read and returns the current one on a conflict, so an agent re-reads rather than overwrites. Source and README: packages/markdowntools.

Errors

Every failure is a JSON object with a stable error.code.

401unauthorizedMissing, malformed or revoked credential.
403forbiddenThe token lacks the scope this call needs.
404not_foundNo such document, or not yours.
409 / 410goneThe share link was revoked.
412precondition_failedIf-Match did not match; re-read and retry.
413payload_too_largeOver the per-document size limit.
428precondition_requiredPUT without If-Match.
429rate_limitedSlow down; see Retry-After.

Frequently Asked Questions

Is the Markdown API free?

Yes. It is included with a free account and there is no paid tier. Fair-use rate limits apply: 120 reads and 40 writes per minute per token, and 10 URL imports per minute.

How do I get an API token?

Create an account, open Settings and API access from your workspace, and create a token with the scopes you need. The token is shown once and stored only as a SHA-256 hash, so it cannot be recovered later — create a new one and revoke the old one if you lose it.

How do I avoid overwriting a document an agent is also editing?

Every response carries an ETag, which is the document revision. Send it back as If-Match on a PUT and the write is rejected with 412 Precondition Failed if the document changed in the meantime. PUT requires If-Match for exactly this reason; send If-Match: * only when you genuinely mean to overwrite whatever is there.

Can an agent read a document without a token?

Only if the owner published a share link. A shared document is readable at /d/{shareId}.md, or at /d/{shareId} with an Accept: text/markdown header, with no credential. Everything else needs a bearer token, and documents are private by default.

What are the size limits?

A single document may hold up to 256 KB of Markdown, and an account may hold up to 1,000 documents.

Does it support MCP?

Yes. The @swarmclawai/markdowntools package on npm runs an MCP server over stdio (npx -y @swarmclawai/markdowntools mcp) with tools to list, read, search, create, update and share documents. An update carries the revision the agent read, so a stale write fails with the current revision instead of overwriting. The REST API stays the substrate: any agent that can make an HTTP request can use it without MCP at all.