Skip to content

Developer

Build with pipit.page

One API, one MCP server, one page of docs. Publish from scripts, CI, or an AI agent in minutes.

Quick start

From nothing to a live page in three steps.

  1. 1

    Create an API key in the dashboard. The full secret is shown exactly once, so save it right away.

  2. 2

    Publish with one request - markdown or HTML, your slug or a generated one.

  3. 3

    Share the URL that comes back. Your page is already live.

Publish a markdown page

curl -X POST https://pipit.page/api/v1/pages \
  -H "Authorization: Bearer pip_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"source_type":"markdown","content":"# hello world","title":"hello world"}'

The 201 response

HTTP/2 201
{
  "page": {
    "id": "0b9e7a1c-6c2d-4f8a-9b1e-3d5a7c2e4f6b",
    "slug": "quiet-forest",
    "status": "published",
    "url": "https://quiet-forest.pipit.page"
  }
}

Authentication

Authenticated requests carry an API key in the Authorization header as a Bearer token. Keys look like pip_live_... and are created at /dashboard/keys. Session tokens from the dashboard work on the same routes.

curl https://pipit.page/api/v1/pages \
  -H "Authorization: Bearer pip_live_YOUR_KEY"

The full secret is shown exactly once when you create a key; after that only a hashed copy is stored. Lost one or leaked one? Revoke it instantly at /dashboard/keys and make a new one.

Scopes

A key carries only the scopes you pick when you create it.

ScopeAllows
pages:publishCreate new pages
pages:readList and read your pages, plus the account overview
pages:writeUpdate pages and their publish state
pages:deleteRemove pages

Key management itself is session-only by design: keys are created and revoked from the dashboard, never with another key. A leaked key cannot mint more access.

Endpoints

Everything lives under https://pipit.page/api/v1 today (a dedicated api.pipit.page subdomain comes later). The paths below are shown in full, so there is nothing to prefix. Everything is JSON in, JSON out.

POST /api/v1/pages pages:publish

Create and publish a page. Returns 201 with the new page, including its public URL.

Omit slug to get a generated two-word slug like quiet-forest. Without an Authorization header this becomes the guest path the homepage uses (Turnstile token required, page expires after 10 minutes) - scripts should always send a key.

Example request

curl -X POST https://pipit.page/api/v1/pages \
  -H "Authorization: Bearer pip_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"source_type":"html","content":"<h1>Launch day</h1>","slug":"launch-notes"}'
GET /api/v1/pages pages:read

List your pages, newest first.

Example response

{
  "pages": [
    {
      "id": "0b9e7a1c-6c2d-4f8a-9b1e-3d5a7c2e4f6b",
      "slug": "quiet-forest",
      "title": "hello world",
      "status": "published",
      "url": "https://quiet-forest.pipit.page",
      "source_type": "markdown",
      "size_bytes": 13,
      "view_count": 42,
      "published_at": "2026-06-10T09:30:00.000Z",
      "created_at": "2026-06-10T09:30:00.000Z",
      "updated_at": "2026-06-10T09:30:00.000Z"
    }
  ]
}
GET /api/v1/pages/:id pages:read

Read one page. The response carries the same fields as the list plus content. Pages you do not own return 404, so existence stays hidden.

Example request

curl https://pipit.page/api/v1/pages/PAGE_ID \
  -H "Authorization: Bearer pip_live_YOUR_KEY"
PATCH /api/v1/pages/:id pages:write

Update title, content, slug, or status. status must be one of "published", "draft", or "unpublished". Changing to a taken slug returns 409.

Example request

curl -X PATCH https://pipit.page/api/v1/pages/PAGE_ID \
  -H "Authorization: Bearer pip_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"draft","title":"hello again"}'
DELETE /api/v1/pages/:id pages:delete

Soft-delete a page. The public URL stops resolving right away.

Example request

curl -X DELETE https://pipit.page/api/v1/pages/PAGE_ID \
  -H "Authorization: Bearer pip_live_YOUR_KEY"
GET /api/v1/slugs/check public

Check whether a slug is still available before you publish. Public, no auth needed.

Example request

curl "https://pipit.page/api/v1/slugs/check?slug=launch-notes"

{ "available": true }
GET /api/v1/account pages:read

Plan and usage overview for the authenticated account.

Example response

{
  "account": {
    "user_id": "8a1d2f4e-0c3b-4e7d-9a52-6b1c8d0e2f4a",
    "plan": "free",
    "active_page_limit": 5,
    "member_since": "2026-05-02T08:14:00.000Z"
  },
  "usage": {
    "total_pages": 4,
    "published_pages": 3,
    "draft_pages": 1,
    "unpublished_pages": 0,
    "total_views": 1280,
    "storage_bytes": 18432
  }
}

Errors always come back as { "error": "what went wrong" } with a matching status code: 400 invalid input, 401 bad credentials, 403 missing scope, 404 not found (or not yours), 409 slug taken, 413 content too large. Slugs are 3-48 characters of lowercase a-z, 0-9, and single hyphens - no leading or trailing hyphen, unique case-insensitively, and reserved names like api, docs, and admin are rejected.

MCP server

Rolling out now

The pipit.page MCP server connects your AI client straight to your account, so it can publish, edit, and manage pages from a conversation. It speaks Streamable HTTP at https://mcp.pipit.page/mcp (with /sse for older clients). The REST API is live today; the MCP server is rolling out right behind it.

Install in Claude Code

claude mcp add --transport http pipit https://mcp.pipit.page/mcp
publish_page

Create and publish a new page

list_pages

List the pages on your account

get_page

Read one page, including its source content

update_page

Edit title, content, slug, or publish status

delete_page

Remove a page so its URL stops resolving

check_slug

See whether a slug is still available

When your client connects, you sign in with your pipit.page account over OAuth - no key pasting. The server enforces the same ownership rules, sanitisation, and plan limits as the REST API.

For AI agents

Working with Claude, Cursor, or any other agent? Paste this into your project instructions and it knows everything it needs to publish for you. Set PIPIT_API_KEY in the environment first.

## Publishing to pipit.page

Create a page with one request:
  POST https://pipit.page/api/v1/pages
  Authorization: Bearer $PIPIT_API_KEY  (read the key from the environment)
  Content-Type: application/json

Body fields:
  source_type  required, "markdown" or "html"
  content      required, the page source as one string
  title        optional display title
  slug         optional, 3-48 chars of a-z 0-9 and single hyphens,
               no leading or trailing hyphen; omit it to get a
               generated two-word slug like quiet-forest

The 201 response has page.url - that is the shareable public link
(https://<slug>.pipit.page). Show it to the user.

Update later with PATCH /api/v1/pages/:id using any of title, content,
slug, or status ("published", "draft", "unpublished"). Content is
sanitised server-side; scripts will not run on published pages.
Errors return { "error": "reason" } with a matching status code.

Once the MCP server reaches your client, prefer it over raw HTTP - the same capabilities with sign-in and tool discovery handled for you.

Limits and safety

  • Free plan includes five active pages

    Each account has an active_page_limit (5 on free). Pages published through the API and the MCP server count against the same limit.

  • 10 MB per page

    Authenticated publishes accept up to 10 MB of source content per page. Guest publishes from the homepage cap at 1 MB and expire after 10 minutes.

  • Sanitised on every path

    Markdown is rendered then sanitised; HTML is sanitised directly, with scripts and event handlers stripped. The same rules apply from the dashboard, the API, and MCP - the API is not an escape hatch.

  • Some slugs are reserved

    Names that collide with infrastructure or routes (www, api, mcp, docs, admin, and friends) are rejected, and uniqueness is case-insensitive.

  • See something off?

    If a published page is abusive, write to hello@pipit.page and we will take a look.

Ready to publish your first page?

Grab a key, send one request, share the link. The free plan is waiting.