API
All endpoints are under https://markdown.page/api/.
The API is intentionally forgiving: if you can send text, you can publish markdown. No account, API key, or special header is required.
Publish a page
POST /api/publishPOST /api also works as a short alias.
Send markdown in the request body and get back a permanent URL. The markdown string may be up to 1 MB.
The easiest version works with no explicit content type:
curl https://markdown.page/api/publish --data-binary '# Hello world'
Publish a file:
curl https://markdown.page/api/publish --data-binary @README.md
A plain curl -d also works, even though curl labels it as form data:
curl https://markdown.page/api/publish -d '# Hello world'
Accepted request bodies:
- raw markdown text, with any content type or no content type
text/markdownortext/plain- JSON string:
"# Hello" - JSON object with one of
markdown,content,text, orbody - URL-encoded form with one of
markdown,content,text, orbody
JSON example:
curl https://markdown.page/api/publish \
-H 'Content-Type: application/json' \
-d '{"markdown":"# Hello world"}'
Browser/fetch clients get 201 with a Location header and JSON containing slug, url, and raw_url:
{
"slug": "a3x9k2b7",
"url": "https://markdown.page/a3x9k2b7",
"raw_url": "https://markdown.page/a3x9k2b7.md"
}
CLI clients such as curl/wget/httpie, or any request that asks for plain text, get just the published URL:
curl https://markdown.page/api/publish --data-binary @README.md
curl -H 'Accept: text/plain' https://markdown.page/api/publish --data-binary @README.md
Errors are returned as JSON by default:
{
"error": "empty_body",
"message": "Send markdown in the request body.",
"example": "curl https://markdown.page/api/publish --data-binary '# Hello'"
}
Common statuses:
400— empty body, invalid JSON, binary body, exceeds 1 MB, or markdown fails validation403— cross-origin browser request blocked415— multipart upload; send raw markdown instead429— fair-use rate limit exceeded500— slug allocation failure
Machine-readable docs
GET /openapi.json and GET /api/openapi.json return an OpenAPI 3.1 specification suitable for importing markdown.page into API marketplaces, gateways, and agent/tool catalogs.
GET /api returns human HTML to browsers and readable plaintext to CLI clients such as curl, wget, and httpie.
Public GET routes support content negotiation:
Accept: text/htmlreturns rendered HTMLAccept: text/plainorAccept: text/markdownreturns plaintext/markdown where supported- curl/wget/httpie with
Accept: */*receive plaintext by default - browser defaults receive HTML
Ask for markdown/plain text:
curl -H 'Accept: text/plain' https://markdown.page/api
curl https://markdown.page/api.md
Explicit .md URLs are available on public negotiated routes for bots, agents, and simple clients that do not perform HTTP content negotiation. Examples: /faq.md, /api.md, /featured/artemis-ii.md, and /{slug}.md.
For agents and automation
- Prefer
Accept: text/plainwhen you only need URLs or markdown. - Use
GET /{slug}.mdto retrieve source markdown for published pages. - Use
GET /{slug}when you want negotiated HTML or plaintext. - Published pages are public and permanent; do not publish secrets or private data.
Agentic featured purchases
Featured placements are paid promotions reviewed before publication.
Plans:
week— $9 USD for 7 daysmonth— $29 USD for 30 daysquarter— $79 USD for 90 days
Machine-readable pricing:
GET /pricing.json(alias:GET /featured/pricing.json)GET /pricing.md
Free quotes:
- x402:
GET /api/featured/purchase/{plan} - MPP:
GET /api/featured/mpp/purchase/{plan}
Dry-run validation:
POST /api/featured/validate
Paid purchase endpoints:
- x402:
POST /api/featured/purchase/{plan} - MPP:
POST /api/featured/mpp/purchase/{plan}
Both create a paid request to feature an existing article. Supported plans are week, month, and quarter.
These endpoints are for agents and use HTTP 402 Payment Required. A request without payment receives a machine-readable x402 or MPP payment challenge. After the agent pays and retries with the payment credential, the endpoint records the purchase as paid_pending_review for admin approval before launch. Review is typically within 48 hours.
Refund/rejection policy: promotions are reviewed before launch. Stripe rejections are refunded manually where appropriate. x402 and MPP payments are irreversible on-chain/testnet rails; rejected crypto-rail purchases receive manual resolution or promotion credit where technically possible while payments development continues.
Status:
GET /api/featured/purchases/{id}
Review criteria:
- Article URL or pageId must already exist on markdown.page.
- Featured slug must use lowercase letters, numbers, and hyphens.
- Featured slug must not already be used by another page or pending purchase.
- Articles must comply with markdown.page content and security rules; spam, phishing, illegal content, harassment, and malware are rejected.
Example unpaid x402 response shape:
HTTP/1.1 402 Payment Required
Payment-Required: <base64 payment requirements>
Content-Type: application/json
The decoded x402 requirements include the selected plan price, network such as base-sepolia, facilitator URL, and payTo address. Retry the same POST with the x402 payment credential headers.
Example unpaid MPP response shape:
HTTP/1.1 402 Payment Required
WWW-Authenticate: Payment <challenge parameters>
Content-Type: application/json
The MPP challenge includes amount, currency, recipient, challenge expiry, and Tempo method details. Retry the same POST with Authorization: Payment ....
Example body:
{
"articleUrl": "https://markdown.page/a3x9k2b7",
"featuredSlug": "hello-world",
"contact": "you@example.com",
"requestId": "agent-run-2026-05-31-001"
}
requestId is strongly recommended for idempotency and status lookup. It must be 8-128 characters using letters, numbers, underscore, period, colon, or hyphen. Agentic purchase ids are deterministic per rail: x402:{requestId} or mpp:{requestId}. Reusing the same requestId with the same rail and payment credential refers to the same purchase; reusing a payment credential for a different purchase is rejected.
Successful paid response:
{
"ok": true,
"id": "x402:agent-run-2026-05-31-001",
"provider": "x402",
"status": "paid_pending_review",
"pageId": "a3x9k2b7",
"featuredSlug": "hello-world",
"plan": "week",
"durationDays": 7,
"approvalRequired": true
}
MCP tools
POST /mcp exposes a public MCP-compatible HTTP JSON-RPC endpoint. No account, API key, or auth header is required. Transport is request/response HTTP JSON-RPC only; SSE streaming is not supported.
Tools:
publish_markdown({ markdown: string })
get_featured_pricing({})
validate_featured_purchase({ plan?, articleUrl? or pageId?, featuredSlug })
get_featured_purchase_status({ id: string })
publish_markdown uses the same validation, storage path, size limits, and fair-use rate limiting as POST /api/publish. Successful calls return MCP text content plus structured URL metadata: slug, url, and raw_url.
Featured commerce division of labor: MCP provides pricing discovery, pre-payment validation, and status lookup inside the agent loop; payment settlement happens over the raw HTTP 402 Payment Required endpoints above. Status is also available over HTTP at GET /api/featured/purchases/{id}.
Example JSON-RPC call:
curl https://markdown.page/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"publish_markdown","arguments":{"markdown":"# Hello from MCP"}}}'
For full MCP tool schemas, see /mcp. For agent discovery, see /llms.txt.
Get raw markdown
GET /{slug}.md
Returns the original markdown source for a published page as text/markdown; charset=utf-8. Returns 404 if the page doesn't exist.
Example:
curl https://markdown.page/a3x9k2b7.md
Markdown rules
Standard markdown plus GFM: headings, bold, italic, strikethrough, lists, task lists, links, images, inline code, fenced code blocks, blockquotes, and tables. Images must use https:// or http:// URLs. Links support https://, http://, and mailto:. Raw HTML, custom CSS, and JavaScript are not accepted. Max document size is 1 MB.