JotBirdJotBird
Open app
API Reference

JotBird API

Publish Markdown programmatically.

Overview

Introduction

The JotBird API allows you to publish, manage, and remove Markdown using scripts, CI pipelines, or any HTTP client. All you need is a free JotBird account and an API key.

All endpoints accept and return JSON. The base URL for all requests is:

https://www.jotbird.com

If you prefer a CLI, the jotbird command wraps these endpoints with file tracking and slug mapping. Install it from npm:

npm install -g jotbird

An OpenAPI spec is also available for code generation and tooling.

Security

Authentication

All API requests require a personal API key, passed as a Bearer token in the Authorization header:

Authorization: Bearer jb_your_api_key_here

Generating a key

Sign up for a free account at jotbird.com, then generate an API key in two ways:

  • CLI: Run jotbird login to open the browser and generate a key automatically.
  • Browser: Visit jotbird.com/account/api-key while signed in to generate a key.

API keys start with jb_ and are shown only once at creation. Store your key securely — if lost, generate a new one.

Key limits

Each account can have up to 10 API keys. If you reach the limit, revoke an existing key before generating a new one.

Revoking a key

To revoke an API key, open the API keys panel from your account menu in the web app. Each key shows its prefix, creation date, and last usage. Click Revoke to permanently delete a key. Revoked keys stop working immediately.

Reference

Rate Limits

Publish requests are rate-limited per account on a rolling hourly window. Free accounts also have a cap on the number of active documents published via API. Active documents are documents with a live public URL that have not expired. Expired documents do not count toward the limit.

LimitFree AccountPro Account
Publishes per hour10100
Active documents10Unlimited

Response headers

Every publish response includes rate limit information:

HeaderDescription
X-RateLimit-LimitMaximum requests per hour for your account
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp (seconds) when the window resets
Retry-AfterSeconds until you can retry (only on 429 responses)

Pro accounts are for individual use only, not enterprise use. If you exceed the rate limit, the API returns a 429 status with a Retry-After header indicating when to retry.

Endpoint

Publish a document

POST/api/v1/publish

Publish a new Markdown document or update an existing one. The server renders your Markdown to HTML and hosts it at a shareable URL. Free accounts get 90-day links. Pro makes links permanent.

Request body

ParameterTypeRequiredDescription
markdownstringYesThe Markdown content to publish.
titlestringNoDocument title. If omitted, extracted from the first H1 in the Markdown.
slugstringNoSlug of an existing document to update. If the slug exists and is owned by you, the document is updated in place. Ignored for new documents.
curl -X POST https://www.jotbird.com/api/v1/publish \
  -H "Authorization: Bearer jb_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "markdown": "# Hello World\n\nThis is my document."
  }'

Response

Returns 201 for new documents, 200 for updates.

{
  "slug": "bright-calm-meadow",
  "url": "https://share.jotbird.com/bright-calm-meadow",
  "title": "Hello World",
  "expiresAt": "2026-05-10T12:00:00.000Z",
  "ttlDays": 90,
  "created": true
}

A URL slug is generated automatically for new documents. Re-publishing with the same slug updates the document in place rather than creating a new URL. Pro accounts get permanent documents — expiresAt will be null.

Image uploads are not supported through the API. Markdown image references (e.g. ![alt](url)) will render only if they point to externally-hosted images.

Free accounts are limited to 10 active documents. Updating an existing document does not count toward this limit. See Rate Limits for details.

Endpoint

List documents

GET/api/v1/documents

Retrieve all published documents for your account. Only documents with an active public URL are returned.

Request

No request body is required.

curl https://www.jotbird.com/api/v1/documents \
  -H "Authorization: Bearer jb_your_api_key_here"

Response

{
  "documents": [
    {
      "slug": "bright-calm-meadow",
      "title": "Hello World",
      "url": "https://share.jotbird.com/bright-calm-meadow",
      "source": "cli",
      "updatedAt": "2026-02-09T14:30:00.000Z",
      "expiresAt": "2026-05-10T14:30:00.000Z"
    }
  ]
}

Results are ordered by most recently updated. The source field indicates how the document was created: "cli", "web", or "api".

Endpoint

Remove a document

DELETE/api/v1/documents?slug=:slug

Permanently delete a document. This removes the public URL, the stored content, and all associated image references. This action cannot be undone.

Query parameters

ParameterTypeRequiredDescription
slugstringYesThe slug of the document to remove.
curl -X DELETE "https://www.jotbird.com/api/v1/documents?slug=bright-calm-meadow" \
  -H "Authorization: Bearer jb_your_api_key_here"

Response

{
  "ok": true
}

Permanent action

This permanently deletes the document from your account. There is no way to recover a removed document.

Reference

Errors

All error responses return a JSON object with an error field containing a human-readable message:

{
  "error": "Missing markdown field"
}

Status codes

CodeMeaningExampleCommon causes
400Bad Request"Missing markdown field"Invalid JSON, missing required fields, invalid slug format
401Unauthorized"Invalid API key"Missing or expired API key, malformed Bearer token
403Forbidden"Document not owned by user"
"Document limit reached (10)..."
Document owned by another account, or free-tier document cap reached
429Too Many Requests"Rate limit exceeded. Try again in 1800 seconds."More than 10 (free) or 100 (pro) publishes per hour
413Payload Too Large"Rendered HTML too large (max 524288 bytes)"Rendered HTML exceeds 512 KB
503Service Unavailable"Failed to allocate document slug"Database temporarily unavailable, slug allocation failed