API Reference
Base URL: /api
Authentication
All write endpoints require authentication via API key. Generate a key in Settings → API Keys and include it as a Bearer token:
Authorization: Bearer mb_your_key_here
Scopes:
- Read Only — view documents and collections
- Read / Write — create and update documents and collections
- Full Access — all permissions including delete
API keys are managed exclusively through the web interface at Settings → API Keys. There are no API endpoints for key management.
Get Current User
GET /api/user
Requires authentication. Returns the authenticated user.
Documents
List Documents
GET /api/documents
Requires authentication. Returns a paginated list of the authenticated user’s documents.
Response: 200
{
"data": [
{
"slug": "my-document",
"short_id": "a3f9b2c1",
"url": "/@username/my-document-a3f9b2c1",
"title": "My Document",
"description": null,
"version": 3,
"visibility": "public",
"markdown": null,
"html": null,
"toc": [...],
"frontmatter": {},
"commit_message": null,
"created_at": "2026-03-31T00:00:00.000000Z",
"updated_at": "2026-03-31T00:00:00.000000Z",
"version_url": "/api/documents/my-document/versions/3",
"latest_url": "/api/documents/my-document"
}
],
"links": { ... },
"meta": { ... }
}
Create Document
POST /api/documents
Requires authentication.
Body:
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | yes | Document title (max 255) |
markdown |
string | yes | Markdown content |
slug |
string | no | Custom slug (lowercase, hyphens, unique per user) |
description |
string | no | Short description (max 1000) |
visibility |
string | no | public, unlisted, or private (defaults to user setting) |
commit_message |
string | no | Version commit message (max 255) |
Response: 201
{
"data": {
"slug": "my-document",
"short_id": "a3f9b2c1",
"url": "/@username/my-document-a3f9b2c1",
"title": "My Document",
"description": null,
"version": 1,
"visibility": "public",
"markdown": "# My Document\n...",
"html": "<h1>My Document</h1>...",
"toc": [...],
"frontmatter": {},
"commit_message": null,
"created_at": "2026-03-31T00:00:00.000000Z",
"updated_at": "2026-03-31T00:00:00.000000Z",
"version_url": "/api/documents/my-document/versions/1",
"latest_url": "/api/documents/my-document"
}
}
Get Document
GET /api/documents/{slug}
Public and unlisted documents are accessible without auth. Private documents require authentication as the owner.
Response: 200 — same structure as create response.
Update Document
PUT /api/documents/{slug}
Requires authentication as the owner. Creates a new version.
Body:
| Field | Type | Required | Description |
|---|---|---|---|
markdown |
string | yes | Updated markdown content |
title |
string | no | Updated title |
commit_message |
string | no | What changed |
Response: 200
Update Metadata
PATCH /api/documents/{slug}/meta
Requires authentication as the owner. Updates title, description, or visibility without creating a new version.
Body:
| Field | Type | Required |
|---|---|---|
title |
string | no |
description |
string | no |
visibility |
string | no |
Response: 200
Delete Document
DELETE /api/documents/{slug}
Requires authentication as the owner. Soft-deletes the document.
Response: 200
{ "message": "Document deleted." }
Preview Markdown
POST /api/documents/preview
Requires authentication. Renders markdown to HTML without saving.
Body:
| Field | Type | Required |
|---|---|---|
markdown |
string | yes |
Response: 200
{
"html": "<h1>Hello</h1>",
"toc": [{ "level": 1, "id": "content-hello", "text": "Hello" }],
"frontmatter": {}
}
List Versions
GET /api/documents/{slug}/versions
Returns paginated list of all versions.
Response: 200
{
"data": [
{
"version_number": 2,
"commit_message": "Fixed typo",
"created_at": "2026-03-31T00:00:00.000000Z"
}
],
"links": { ... },
"meta": { ... }
}
Get Specific Version
GET /api/documents/{slug}/versions/{version_number}
Response: 200 — document data with the specified version’s content.
Collections
List Collections
GET /api/collections
Requires authentication. Returns a paginated list of the authenticated user’s collections with their documents.
Response: 200
{
"data": [
{
"slug": "my-collection",
"title": "My Collection",
"description": "...",
"visibility": "public",
"documents": [
{ "slug": "doc-one", "title": "Doc One", "position": 0 }
],
"created_at": "2026-03-31T00:00:00.000000Z",
"updated_at": "2026-03-31T00:00:00.000000Z"
}
],
"links": { ... },
"meta": { ... }
}
Create Collection
POST /api/collections
Requires authentication.
Body:
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | yes | Collection title (max 255) |
slug |
string | no | Custom slug |
description |
string | no | Description (max 1000) |
visibility |
string | no | public, unlisted, or private |
Response: 201
{
"data": {
"slug": "my-collection",
"title": "My Collection",
"description": "...",
"visibility": "public",
"documents": []
}
}
Get Collection
GET /api/collections/{slug}
Response: 200 — collection with nested documents.
Update Collection
PUT /api/collections/{slug}
Requires authentication as the owner.
Body:
| Field | Type | Required |
|---|---|---|
title |
string | no |
description |
string | no |
visibility |
string | no |
Response: 200
Manage Collection Documents
Set documents (sync):
POST /api/collections/{slug}/documents
Body:
{
"documents": [
{ "slug": "doc-one", "position": 0 },
{ "slug": "doc-two", "position": 1 }
]
}
This replaces the collection’s document list with the provided set.
Remove a document:
DELETE /api/collections/{slug}/documents/{document_slug}
Search
GET /api/search?q={query}
Searches public documents by title and description.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
q |
string | yes | Search query (1-255 characters) |
Response: 200
{
"data": [
{
"slug": "my-doc",
"title": "My Document",
"description": "...",
"visibility": "public"
}
]
}
Error Responses
All errors return JSON:
{
"message": "Error description.",
"errors": {
"field": ["Validation message"]
}
}
| Status | Meaning |
|---|---|
401 |
Unauthenticated — missing or invalid credentials |
403 |
Forbidden — you don’t have permission |
404 |
Not found |
410 |
Gone — document has expired |
422 |
Validation error — check errors field |
429 |
Rate limited |
Rate Limits
API requests are rate-limited per user. The current limits are returned in response headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59