Skip to content
Gryz Docs
API

Documents API reference

REST API for creating, reading, updating, and deleting documents with API key authentication.

Updated · Reviewed by Jacob

Answer first

Authenticated clients call /api/documents with a Bearer API key (gryz_…). Anonymous publishes use POST /api/documents from the web UI with Turnstile — not the same as MCP OAuth.

Base URL: https://www.gryz.ai

Authentication

Authorization: Bearer gryz_YOUR_KEY_HERE

Create keys at /account/api-keys/. Requires Starter tier or above.

POST /api/documents/

Create a document.

Body (JSON):

{
  "content": "# Hello",
  "content_type": "markdown",
  "title": "Optional title",
  "visibility": "public"
}

Responses:

  • 201 — { "slug": "...", "url": "..." }
  • 400 — validation error
  • 401 — missing or invalid API key
  • 413 — over tier size limit
  • 429 — rate limited

GET /api/documents/

List documents for the authenticated user. Supports pagination query params.

GET /api/documents/[slug]/

Fetch a single document you own.

PATCH /api/documents/[slug]/

Update content, title, visibility, or expiry.

DELETE /api/documents/[slug]/

Permanently delete a document you own.

Editing part of a document

These routes change one part of a document without resending the rest, and keep a history of every change. They take a Bearer API key (or a signed-in web session), act on documents you own, and share their rules, size limits, and error codes with the document editing MCP tools. They are available while the mcp_document_edit feature is on; when it is off the routes answer 404. PATCH /api/documents/[slug]/ is unchanged.

Every document has a revision such as r12. Send it as if_match to refuse a write when the document has changed since you read it.

POST /api/documents/[slug]/append/

Add text to the end (or start) of a Markdown, CSV, or Mermaid document.

curl -X POST https://www.gryz.ai/api/documents/my-log/append/ \
  -H "Authorization: Bearer gryz_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"content": "## 2026-10-07\n\nShipped the thing.", "if_match": "r12"}'

Body: content (required), position (end or start), if_match, on_conflict (fail or merge), idempotency_key.

  • 200 — { "slug", "url", "revision", "changed", "replayed", "bytes_delta", "history_trimmed" }
  • 400 — empty content, or a document type that cannot be appended to (type_not_supported_for_append)
  • 403 — not your document, or the owner limited assistants (agent_access_read_only, agent_access_suggest_only)
  • 409 — revision_conflict: the document changed since if_match; the response includes current_revision. Nothing was written.
  • 413 — size_over_tier_limit: the result would pass your plan's size limit. Nothing was written.
  • 422 — content screening rejected the added text

POST /api/documents/[slug]/edit/

Apply up to 25 operations together as one new version, or change nothing.

curl -X POST https://www.gryz.ai/api/documents/my-plan/edit/ \
  -H "Authorization: Bearer gryz_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"operations": [{"op": "set_checkbox", "text": "write docs", "checked": true}], "dry_run": true}'

Body: operations (required; replace_text, insert_before_heading, insert_after_heading, replace_section, delete_section, append_table_row, set_checkbox), if_match, on_conflict, dry_run, idempotency_key. The operations are described in the MCP tools reference.

  • 200 — the same fields as append plus operations (what each did), diff (a compact before and after), merged, merged_over, and dry_run. A dry run writes nothing.
  • 400 — an invalid operation. The response names it (operation_index) and its code, such as match_not_found or heading_ambiguous. No operation in the batch was applied.
  • 409 — revision_conflict (or merge_conflict with conflicting_sections when on_conflict is merge and the same section changed)
  • 410 — revision_expired: the version named by if_match is no longer kept; the response includes oldest_available_revision
  • 413, 403, 422 — as for append

GET /api/documents/[slug]/revisions/

List the saved versions, newest first, without their text. Query: limit (1–50), before (a revision, to page back).

curl "https://www.gryz.ai/api/documents/my-plan/revisions/?limit=10" \
  -H "Authorization: Bearer gryz_YOUR_KEY_HERE"
  • 200 — { "current_revision", "revisions": [{ "revision", "actor", "tool", "summary", "bytes_delta", "created_at" }], "next_before", "history_trimmed" }

GET /api/documents/[slug]/revisions/[rev]/

What one version changed compared with the one before it, as a compact diff. [rev] is r12 or 12. 404 or 410 when the version is no longer kept. The response includes has_parent: it is false for the first saved version and for a version whose earlier version was removed, and then diff is empty because there is nothing to compare with.

POST /api/documents/[slug]/revisions/[rev]/restore/

Bring a version back as a new version. History is never rewritten. Optional body: if_match, idempotency_key.

curl -X POST https://www.gryz.ai/api/documents/my-plan/revisions/r9/restore/ \
  -H "Authorization: Bearer gryz_YOUR_KEY_HERE"
  • 200 — { "revision", "restored_from", "changed" }
  • 410 — that version is no longer kept
  • 413 — the version is larger than your plan allows today

Suggestions and assistant permissions (web only)

POST /api/documents/[slug]/suggestions/[id]/ (body { "action": "accept" } or { "action": "reject" }) and PUT /api/documents/[slug]/agent-access/ (body { "agent_access": "direct" | "suggest" | "read_only" }) are for the signed-in owner in the web app only. They do not accept API keys, so an assistant cannot approve its own suggestion or widen its own access. They need the document_suggestions feature. Accepting returns { "revision" }, or 409 with suggestion_stale when the document changed too much, or agent_access_read_only when the document is now read only for assistants.

Errors use the shape below, with extra fields such as retryable, remedy, and current_revision where they help.

Rate limits

Publish endpoints enforce per-identity sliding-window limits. When exceeded, the API returns 429 with Retry-After.

Error shape

{
  "error": "Human-readable message",
  "code": "OPTIONAL_CODE"
}

For assistant-driven workflows, compare the MCP tools. For browser and API publishing constraints, see Choose publishing options.

Was this page helpful?