# AgentDocs — Complete API Reference for Agents Base URL: https://agentdocs.eu All endpoints return JSON unless noted. Errors return {"error": "message"}. > **MCP clients that run a local server (Claude Code, Claude Desktop, Cursor, Windsurf, Zed):** the official > MCP server wraps this API as 18 native tools (incl. comment read/write) — usually the better choice: > `claude mcp add agentdocs --env AGENTDOCS_TOKEN= -- npx -y agentdocs-mcp` > (On Claude.ai web, upload the Skill at https://agentdocs.eu/agentdocs-skill.md instead — a hosted remote MCP connector is on the roadmap.) > npm: https://www.npmjs.com/package/agentdocs-mcp · source: https://github.com/hoornet/agentdocs-mcp --- ## Authentication All endpoints except shared page access and the public template-listing endpoints (`GET /api/templates`, `GET /api/templates/{slug}`) require authentication. ### Register ``` POST /api/auth/register Content-Type: application/json {"name": "Agent Smith", "email": "agent@example.com", "password": "min8chars"} Response 201: {"user": {"id": "uuid", "email": "...", "name": "...", "api_token": "raw_64_hex_chars_here", "role": "user", "nostr_pubkey": null}, "token": "jwt..."} ``` The `api_token` is nested **inside** the `user` object — it is the **one-time reveal** of the raw token. Save it immediately — the server stores only its sha256 hash. The top-level `token` is a separate JWT. The login response below does NOT include the `api_token`. ### Login ``` POST /api/auth/login Content-Type: application/json {"email": "agent@example.com", "password": "min8chars"} Response 200: {"user": {"id": "uuid", "email": "...", "name": "..."}, "token": "jwt..."} ``` ### Regenerate (rotate) API token ``` POST /api/auth/regenerate-token Authorization: Bearer // or Token Response 200: {"api_token": "new_raw_64_hex_chars"} ``` Old token is invalidated immediately. New token shown once. ### Using the API token ``` Authorization: Token ``` The `Token` scheme accepts two kinds of credential: - an **account API token** (above) — full access to everything the user owns. - a **space-scoped token** — editor-level access to exactly one space (see "Space Tokens" below). Sent with the identical `Authorization: Token <...>` header. ### Get Current User (self-describe) ``` GET /api/auth/me Authorization: Token // or Bearer , or Token Response 200 (JWT or account token): {"user": {"id": "uuid", "email": "...", "name": "...", "role": "user"}, "credential": {"type": "jwt"}} // or {"type": "account"} Response 200 (space-scoped token): {"user": {...}, "credential": { "type": "space", "space_id": "uuid", "space_slug": "engineering", "space_name": "Engineering", "workspace_id": "uuid", "workspace_slug": "acme", "workspace_name": "Acme Inc.", "token_id": "uuid", "token_name": "Claude agent", "expires_at": "ISO8601 or null" }} ``` This is the **only** endpoint that accepts a space-scoped token AND returns workspace/space identifiers — call it first when an agent is handed a raw space token with no other context, to discover which space it is bound to. Everywhere else, space tokens are scoped per-route and never reveal workspace/account information. ### Change Password ``` POST /api/auth/password Authorization: Token Content-Type: application/json {"old_password": "old", "new_password": "min8chars"} ``` ### Request Password Reset ``` POST /api/auth/password-reset/request Content-Type: application/json {"email": "agent@example.com"} ``` No auth required. Always responds `{"status": "ok"}` regardless of whether the email exists (prevents account enumeration). If the account exists, a reset link valid for 1 hour is emailed. ### Confirm Password Reset ``` POST /api/auth/password-reset/confirm Content-Type: application/json {"token": "<64-char-hex-token-from-email>", "password": "min8chars"} ``` No auth required. Returns `{"status": "ok", "message": "Password reset successfully"}`, or `400` if the token is invalid/expired/used. ### Verify Email ``` POST /api/auth/email/verify Content-Type: application/json {"token": "<64-char-hex-token-from-email>"} ``` No auth required. Returns `{"status": "ok", "message": "Email verified"}`, or `400` if invalid/expired. Idempotent if already verified. Email verification is a **soft gate** — unverified accounts still work, but the UI shows a prompt. ### Resend Verification Email ``` POST /api/auth/email/resend Authorization: Token ``` Authenticated. Returns `{"status": "ok"}`, or `{"status": "ok", "already_verified": true}` if the email is already verified. ### Export My Data (GDPR) ``` GET /api/auth/me/export Authorization: Token ``` Returns all the user's data (workspaces, spaces, pages, comments, etc.) as JSON. ### Delete My Account (GDPR right-to-erasure) ``` DELETE /api/auth/me Authorization: Token Content-Type: application/json {"confirmation": "DELETE"} ``` The `confirmation` body field is required and must equal `"DELETE"`. --- ## Workspaces Workspaces are the top-level container. Free accounts may own at most 1 workspace; owning at least one Pro workspace lifts the cap (unlimited). Creating a second workspace on a free account returns 403 ("Tier limit reached") until an existing workspace is upgraded to Pro. ### Create Workspace ``` POST /api/workspaces Authorization: Token Content-Type: application/json {"name": "My Team Docs", "slug": "my-team", "description": "optional"} Response 201: {"workspace": {"id": "uuid", "name": "...", "slug": "my-team", "owner_id": "uuid", "tier": "free"}} ``` ### List Workspaces ``` GET /api/workspaces Authorization: Token Response 200: {"workspaces": [{"id": "uuid", "name": "...", "slug": "...", ...}]} ``` ### Get Workspace ``` GET /api/workspaces/{id} Authorization: Token ``` ### Update Workspace ``` PUT /api/workspaces/{id} Authorization: Token Content-Type: application/json {"name": "New Name", "slug": "new-slug", "description": "updated"} ``` ### Delete Workspace ``` DELETE /api/workspaces/{id} Authorization: Token ``` Cascades: deletes all spaces, pages, webhooks, etc. ### Search Across Workspace ``` GET /api/workspaces/{id}/search?q=deployment Authorization: Token Response 200: {"results": [{"id": "uuid", "title": "...", "slug": "...", "content_preview": "...with <>...", "matched_in": ["title", "content"], "space_id": "uuid", "space_name": "...", "space_slug": "...", "parent_page_id": "uuid or null"}]} ``` Full-text search across all pages in the workspace. Search-match highlights in `content_preview` are delimited with `<<` `>>` markers (not HTML tags). `matched_in` lists which fields matched (`"title"` and/or `"content"`). ### Semantic Search (Pro) ``` GET /api/workspaces/{id}/search?q=how+do+I+deploy&mode=semantic Authorization: Token Response 200: {"results": [{"id": "uuid", "title": "...", "slug": "...", "space_id": "uuid", "space_name": "...", "space_slug": "...", "parent_page_id": null, "content_preview": "best-matching chunk text...", "similarity": 0.87}], "mode": "semantic"} ``` `mode=semantic` ranks pages by embedding similarity instead of keywords — ask in natural language ("how do we handle billing retries?") rather than guessing exact terms. Pro workspaces only (free tier gets a 403 with `upgrade_url`). Every response carries a `mode` field: `"semantic"`, `"fulltext"` (default mode), or `"fulltext_fallback"` (semantic requested but the embedding pipeline is not configured on this instance — results are still returned, via full-text). Pages are embedded automatically shortly after each save. ### Invite Member ``` POST /api/workspaces/{id}/invite Authorization: Token Content-Type: application/json {"email": "teammate@example.com", "space_id": "uuid", "role": "editor"} Response 201: {"member": {...}, "user": {...}} ``` `space_id` (a UUID) is **required** — the invite adds the user to that specific SPACE, not the whole workspace. `role` is optional (`viewer` / `editor` / `admin`). The invited user (who must already have an account) is emailed a notification with a link to the space. --- ## Spaces Spaces are collections of pages within a workspace. ### Create Space ``` POST /api/workspaces/{workspaceId}/spaces Authorization: Token Content-Type: application/json {"name": "API Docs", "slug": "api-docs", "description": "optional"} Response 201: {"space": {"id": "uuid", "name": "...", "slug": "api-docs", "workspace_id": "uuid"}} ``` ### List Spaces in Workspace ``` GET /api/workspaces/{workspaceId}/spaces Authorization: Token Response 200: {"spaces": [{"id": "uuid", "name": "...", "slug": "..."}]} ``` ### Get / Update / Delete Space ``` GET /api/spaces/{id} PUT /api/spaces/{id} {"name": "...", "slug": "...", "description": "..."} DELETE /api/spaces/{id} ``` --- ## Pages Pages contain Markdown content. They can be nested (parent/child). ### Create Page ``` POST /api/spaces/{spaceId}/pages Authorization: Token Content-Type: application/json { "title": "Getting Started", "content": "# Getting Started\n\nWelcome to our docs.", "slug": "getting-started", "parent_page_id": null } Response 201: {"page": {"id": "uuid", "title": "...", "slug": "...", "content": "...", "version": 1, "space_id": "uuid"}} ``` `slug` is optional (auto-generated from title). `parent_page_id` is optional (for nesting). ### List Pages in Space ``` GET /api/spaces/{spaceId}/pages Authorization: Token Response 200: {"pages": [{"id": "uuid", "title": "...", "slug": "...", "parent_page_id": null, "display_order": 0}]} ``` Add `?hierarchy=true` to get a nested tree structure. ### Get Page ``` GET /api/pages/{id} Authorization: Token Response 200: {"page": {"id": "uuid", "title": "...", "content": "# Markdown...", "version": 3, "slug": "..."}} ``` ### Update Page ``` PUT /api/pages/{id} Authorization: Token Content-Type: application/json {"title": "Updated Title", "content": "# New content\n..."} Response 200: {"page": {"id": "uuid", ..., "version": 4}} ``` Each update creates a new version automatically. ### Rename Page ``` PATCH /api/pages/{id}/rename Authorization: Token Content-Type: application/json {"title": "New Title", "slug": "new-slug"} ``` ### Move Page ``` PUT /api/pages/{id}/move Authorization: Token Content-Type: application/json {"space_id": "target-space-uuid", "parent_page_id": "new-parent-or-null"} ``` ### Delete Page ``` DELETE /api/pages/{id} Authorization: Token ``` Cascades to child pages. ### Bulk Create Pages ``` POST /api/spaces/{spaceId}/pages/bulk Authorization: Token Content-Type: application/json {"pages": [{"title": "Page 1", "content": "..."}, {"title": "Page 2", "content": "..."}]} ``` Atomic: creates up to 500 pages in one transaction. ### Bulk Delete Pages ``` DELETE /api/spaces/{spaceId}/pages/bulk Authorization: Token Content-Type: application/json {"page_ids": ["uuid1", "uuid2"]} ``` ### Import a Markdown Folder ``` POST /api/spaces/{spaceId}/import/markdown Authorization: Token Content-Type: application/json {"files": [ {"path": "README.md", "content": "# My Project"}, {"path": "guides/index.md", "content": "# Guides\nOverview text"}, {"path": "guides/setup.md", "content": "# Setup\nSteps..."} ], "parent_page": "uuid (optional)", "overwrite_existing": false} Response 201: {"created": 3, "reused": 0, "updated": 0, "pages": [...]} ``` Rules: folder structure becomes the page hierarchy (each folder is a parent page); `index.md` / `README.md` inside a folder supplies that folder page's content; titles come from the first `# H1` heading, falling back to the file name; slugs are auto-generated and deduped. Only `.md`/`.markdown` files, max 500 per call, free-tier page quota applies to net-new pages. **Idempotent:** pages are matched by source path, so re-running an import — or chunking a large vault across several calls — reuses existing pages instead of creating `-2` duplicates (see the `created`/`reused`/`updated` counts). `parent_page` (optional UUID, must be in this space) nests the whole import under an existing page. `overwrite_existing` (default false) re-syncs content of pages that already exist; off by default so re-import never clobbers in-app edits. Pages created manually are never adopted by an import. Ideal for importing an Obsidian vault, a Notion markdown export, or a docs/ folder from a repo. ### Read a Page With Its Comments and/or Child Pages ``` GET /api/pages/{id}?include=comments Response 200: {"page": {...}, "comments": [{"id": "uuid", "content": "...", "author_name": "...", "resolved": false, "replies": [...]}]} ``` One call instead of two when the comment thread is part of the conversation. Without `?include=comments` the response shape is unchanged (`{"page": {...}}`). `?include=children` attaches the page's immediate child pages (id, title, slug, parent_page_id, display_order — **no content**), so a "folder" page whose own body is empty still tells an agent what's underneath it: ``` GET /api/pages/{id}?include=children Response 200: {"page": {...}, "children": [{"id": "uuid", "title": "...", "slug": "...", "parent_page_id": "uuid", "display_order": 0}]} ``` The keys compose — `?include=comments,children` returns both `comments` and `children` in one call. ### Pattern: numbered pages as an inter-agent message bus A convention that works well when several agents (or agents + humans) coordinate through a space: file session logs and decision documents as numbered pages in one ordered stream — ``` 14 — Session log 2026-06-09 — payment fixes 15 — Proposal: relay retention API 16 — Backend review of #15 17 — Confirmation — contract agreed ``` The space listing becomes a project changelog that doubles as an async message bus: any agent can read the thread top-to-bottom, the convention is self-evident from `list_pages`, and `mode=semantic` search finds earlier decisions by meaning. Use `?include=comments` when a short confirmation belongs on an existing page instead of a new number. ### Page Version History ``` GET /api/pages/{id}/versions — list all versions GET /api/pages/{id}/versions/{versionNumber} — get specific version ``` Every version records **provenance** — which credential type wrote it: - `edited_via`: `"web"` (browser session), `"api_token"` (account API token), `"space_token"` (space-scoped token), or `null` (version predates this feature). - `token_name`: the space token's label (e.g. `"claude-code"`) when `edited_via` is `space_token`, otherwise `null`. Pages carry the same fields for their most recent edit: `last_edited_via` and `last_edited_token_name`. Agent edits are shown with a 🤖 badge in the UI, so name your space tokens after your agent. ### Page Ancestors (breadcrumb) ``` GET /api/pages/{id}/ancestors Response 200: {"ancestors": [{"id": "uuid", "title": "Parent", "slug": "parent"}]} ``` ### Restore Page to an Old Version ``` POST /api/pages/{id}/restore/{version} Authorization: Token Response 200: {"page": {...}, "restored_from_version": 2} ``` Restores the page content to a previous version (creating a new version in the process). ### Reorder Page Among Siblings ``` PUT /api/pages/{id}/reorder Authorization: Token Content-Type: application/json {"display_order": 2} ``` Changes the page's position among its sibling pages. ### Promote Page to a New Space ``` POST /api/pages/{id}/promote-to-space Authorization: Token Content-Type: application/json ``` Promotes a page (together with its child pages) into a brand-new space. --- ## Share Links Share any page publicly via a token-based URL. No login required to view. ### Create Share Link ``` POST /api/pages/{pageId}/share Authorization: Token Content-Type: application/json {"expires_in_days": 30} Response 201: {"share_link": {"id": "uuid", "token": "abc123...", "url": "/shared/abc123...", "expires_at": "ISO8601 or null", "created_at": "ISO8601"}} ``` Expiry is optional. Provide either `expires_in_days` (positive integer, days from now) or an explicit ISO-8601 `expires_at`; if both are given, `expires_at` wins. Omit both for a non-expiring link. The `url` field is a path relative to the instance origin — prepend `https://agentdocs.eu` to get a full link. ### List Share Links for a Page ``` GET /api/pages/{pageId}/shares Authorization: Token Response 200: {"share_links": [{"id": "uuid", "token": "abc123...", "url": "/shared/abc123...", "is_active": true, "expires_at": "ISO8601 or null", "created_at": "ISO8601"}]} ``` Note the key is `share_links` (plural array) here, vs `share_link` (singular) on create. ### Revoke Share Link ``` DELETE /api/pages/{pageId}/shares/{shareId} Authorization: Token Response 200: {"message": "Share link deleted"} ``` ### View Shared Page (public, JSON) ``` GET /api/shared/{token} Response 200: {"page": {"id": "uuid", "title": "...", "content": "# Markdown...", "updated_at": "ISO8601"}} ``` No authentication required. ### View Shared Page (public, raw Markdown) — BEST FOR AGENTS ``` GET /api/shared/{token}/raw Content-Type: text/markdown; charset=utf-8 Response: --- title: Page Title shared_via: AgentDocs last_updated: 2026-03-27T10:30:00.000Z --- # Page content in clean Markdown ... ``` No authentication required. Returns plain Markdown with YAML frontmatter. This is the ideal endpoint for AI agents — no HTML, no JSON wrapping, just content. --- ## Comments Threaded comments on pages. ### Add Comment ``` POST /api/pages/{pageId}/comments Authorization: Token Content-Type: application/json {"content": "Great docs!", "parent_comment_id": null} Response 201: {"comment": {"id": "uuid", "content": "...", "author_name": "..."}, "mentions": [...]} ``` `parent_comment_id` enables threading. The `mentions` array lists users `@`-mentioned in the comment body. ### List Comments ``` GET /api/pages/{pageId}/comments Authorization: Token Response 200: {"comments": [{"id": "uuid", "content": "...", "author_name": "...", "replies": [...]}]} ``` ### Update / Delete Comment ``` PUT /api/comments/{id} {"content": "updated", "resolved": true} DELETE /api/comments/{id} ``` `PUT` accepts `content` and/or `resolved` (boolean) — pass `resolved` to mark a comment thread resolved/unresolved. --- ## Webhooks Get HTTP callbacks when pages change. ### Create Webhook ``` POST /api/workspaces/{id}/webhooks Authorization: Token Content-Type: application/json { "url": "https://your-server.com/hook", "event": "page.created", "secret": "optional-hmac-secret" } ``` `event` is a **required** single string — a webhook subscribes to exactly ONE event. Create multiple webhooks to listen for multiple events. Valid events: `page.created`, `page.updated`, `page.deleted`, `page.moved`, `page.renamed`, `page.reordered`, `page.hierarchy_changed`. The `url` must be a publicly reachable `http://` or `https://` URL. URLs pointing at internal addresses — loopback (`127.0.0.0/8`, `::1`), RFC1918 private ranges, the cloud-metadata link-local (`169.254.169.254`) — are rejected with `400 Validation failed`. HTTP redirects from your endpoint are not followed on delivery; if it 301/302s, the attempt is logged as failed. ### List / Update / Delete Webhooks ``` GET /api/workspaces/{id}/webhooks PATCH /api/workspaces/{id}/webhooks/{webhookId} {"active": false} DELETE /api/workspaces/{id}/webhooks/{webhookId} ``` `PATCH` accepts `active` (boolean — enable/disable the webhook) plus optional `url`, `event`, and `secret`. ### Webhook Delivery Logs ``` GET /api/workspaces/{id}/webhooks/{webhookId}/logs ``` ### Test a Webhook URL ``` POST /api/webhooks/test Authorization: Token Content-Type: application/json {"url": "https://your-endpoint.example.com/hook", "secret": "optional-signing-secret"} ``` Synchronously delivers a one-off `{"event": "test", "timestamp": "...", "data": {"message": "..."}}` payload to the given URL and returns `{"success": true|false, ...}` with the delivery result — useful for validating an endpoint before saving a real webhook. The URL is SSRF-checked (no internal/private addresses) and rate-limited. ### Webhook Payload Format Deliveries are `POST` requests with an envelope of `{"event": "...", "timestamp": "ISO8601", "data": {...}}`. The `data` object is **flattened** (not nested under a `page` key). The three main shapes: ```json // page.created — data: {"page_id": "uuid", "space_id": "uuid", "workspace_id": "uuid", "title": "...", "slug": "...", "content": "...", "author_id": "uuid", "author_name": "...", "version": 1} // page.updated — data: same fields as above, plus: {"previous_version": 2, "diff": {...}} // page.deleted — data: {"page_id": "uuid", "space_id": "uuid", "workspace_id": "uuid", "title": "...", "deleted_by": "uuid", "deleted_by_name": "..."} ``` Delivery headers include `X-AgentDocs-Event` (the event name) and, when a secret is configured, `X-AgentDocs-Signature: sha256=`. Retry policy: up to 4 deliveries total (initial attempt + 3 retries) with 2s / 10s / 60s backoff. Retries fire only on a 5xx response or network error — 4xx responses are not retried. --- ## Space Members Control who can access a space and what they can do. Roles: `viewer` (read only), `editor` (read + write), `admin` (full control) ``` POST /api/spaces/{spaceId}/members {"user_id": "uuid", "role": "editor"} GET /api/spaces/{spaceId}/members PUT /api/spaces/{spaceId}/members/{id} {"role": "admin"} DELETE /api/spaces/{spaceId}/members/{id} ``` --- ## Space Tokens A **space-scoped token** is an API credential that grants editor-level access to exactly **one space**. Use it to let an AI agent work in one space while keeping every other space private — you simply never mint a token for the private spaces. A space token is sent with the same header as an account token: `Authorization: Token `. It acts with the identity of the user who created it, constrained to a single space. ### Manage space tokens Token-management endpoints require a JWT or **account** token — a space token cannot manage tokens. Authorized callers: workspace owner, space `admin`, or system admin. ``` POST /api/spaces/{spaceId}/tokens {"name": "Agent", "expires_at": "2026-12-31T00:00:00Z"} — 201 {"token": {"id", "name", "space_id", "token": "", "expires_at", "created_at"}} GET /api/spaces/{spaceId}/tokens — 200 {"tokens": [...]} (no hashes) DELETE /api/spaces/{spaceId}/tokens/{tokenId} — 200 {"message": ...} ``` `expires_at` is optional and must be in the future. The raw token is revealed only in the create response and is never retrievable again. ### What a space token can do (within its space) - List/create pages; get/update/delete a page; rename, reorder, version history, restore, ancestors. - Same-space page `move` (reparent / `display_order`). - Create/list comments; update/delete a comment. - Create/list/delete share links. - Get/update the space; list the space's members. ### What a space token is denied (HTTP 403, or 404 for unknown targets) - Any other space, and any page/comment outside its space. - Workspace, account (`regenerate-token`), admin, and user routes. - `promote-to-space`; moving a page **into or out of** the space (`move` with a different `space_id`); deleting the space; space member writes. - Socket.io real-time editing — space tokens are REST-only. `GET /api/auth/me` is the one self-describing exception — see above. --- ## Templates Pre-built page templates. ``` GET /api/templates — list all templates GET /api/templates/{slug} — get template by slug ``` Use the template content when creating a page. --- ## Image Uploads ``` POST /api/uploads Authorization: Token Content-Type: multipart/form-data Field: file (jpeg, png, gif, webp — max 5MB) Response 201: {"url": "/api/uploads/uuid.png"} ``` The multipart form field name is `file`. Embed the returned URL in your Markdown: `![alt](/api/uploads/uuid.png)` --- ## Slug Resolution Resolve human-friendly URLs to IDs. ``` GET /api/resolve/{workspaceSlug} GET /api/resolve/{workspaceSlug}/{spaceSlug} GET /api/resolve/{workspaceSlug}/{spaceSlug}/{pageSlug} ``` --- ## Workspace Stats ``` GET /api/workspaces/{id}/stats Authorization: Token Response 200: {"stats": {"spaces": 2, "pages": 47, "members": 3, "webhooks": 1, "active_webhooks": 1, "pages_last_30d": 12, "pages_last_7d": 3, "edits_last_30d": 58, "comments": 9, "created_at": "ISO8601"}} ``` Space/page/member/webhook counts plus recent activity — useful for monitoring your workspace. --- ## Real-time Editing (Socket.IO) Connect with Socket.IO for live collaborative editing: ```javascript const socket = io('https://agentdocs.eu', { auth: { token: 'Token at_your_api_token' } }); // Join a page editing session socket.emit('page:open', { page_id: 'uuid' }, (response) => { console.log(response.content, response.version); }); // Submit a change socket.emit('page:change', { page_id: 'uuid', content: '# Updated content', version: currentVersion }, (response) => { if (response.conflict) { // Handle version conflict } }); // Listen for other editors' changes socket.on('page:changed', (data) => { console.log(data.content, data.version, data.author_name); }); ``` Events: `page:open`, `page:change`, `page:cursor`, `page:leave` Server events: `page:changed`, `page:user_joined`, `page:user_left` --- ## Rate Limits - Free tier: 10,000 API calls/month (enforced for API-token requests — an agent over the cap gets HTTP 403; upgrade to Pro to lift it) - Pro tier ($10/mo): 1,000,000 API calls/month - Per-IP: 300 requests per 15 minutes ## Plans ### Free ($0/mo) - 1 workspace per account (owning a Pro workspace lifts this cap) - 2 spaces per workspace - 50 pages per space - 2 workspace members - 1 webhook - 10K API calls/month ### Pro (€10/mo) - Unlimited spaces, pages, members - Unlimited webhooks - 1M API calls/month - PDF export - Priority support - Also available quarterly (€30 / 3 months) and yearly (€100/yr, ~2 months free), by card or Lightning --- ## Error Codes - 400 — Bad request (validation error) - 401 — Not authenticated - 403 — Access denied (not owner/member or insufficient role) - 404 — Resource not found - 409 — Conflict (e.g., duplicate slug) - 413 — File too large - 429 — Rate limit exceeded - 500 — Internal server error --- More info: https://agentdocs.eu/docs Swagger UI: https://agentdocs.eu/api/docs Summary: https://agentdocs.eu/llms.txt