API Reference

ExploreSelf-hostDocumentationBlogSign In
Documentation
Overview
Getting Started
Getting StartedPlatform IntegrationsAgentPlaybooks in ClaudePortable Bot TeamsHermes Memory ProviderHermes for OrganisationsAgentPlaybooks Tools in HermesCLI & Editor PluginsPython SecretsCross-platform Agent BackupsRelease DistributionTeam CollaborationFederated MCP & OpenAPI ToolsMCP Registry PublishingRoadmap
Core Concepts
PlaybooksSkillsMemoryMCP Integration
Reference
ArchitectureAPI ReferenceManagement APIDeveloper GuideSelf-HostingEnvironment Setup
View on GitHub
DocsAPI Reference

API Reference

Complete reference for all AgentPlaybooks API endpoints.

Base URL

https://apbks.com/api

For self-hosted instances, replace with your domain.

Playbook identifiers

A playbook has two identifiers: its GUID, the short id in every URL and on the Integrations tab (for example a1b2c3d4e5f60718), and its id, a UUID. Every endpoint accepts either one wherever a path says :guid or :id, so use whichever you have; the GUID is the one to share.

Agent Reliability Loop

For production agent workflows, use this loop:

  • Read fresh context at task start (GET /playbooks/:guid in your preferred format, or MCP resources/tools).
  • Execute with minimal context (target specific skills/memory keys instead of loading everything).
  • Write back durable learnings (PUT /playbooks/:guid/memory/:key) with tags and description.
  • Store long-form notes in canvas (/api/playbooks/:guid/canvas*) and keep memory compact.

This mirrors the same reliability principle used in modern context systems: fresh docs + persistent learnings.


Authentication

AgentPlaybooks supports two authentication methods:

1. User Authentication (JWT)

For dashboard and management endpoints. Pass Supabase JWT token:

Authorization: Bearer <supabase_jwt_token>

2. Playbook API Key Authentication

For playbook memory write-back endpoints on a specific playbook:

Authorization: Bearer apb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

3. User API Key Authentication

For programmatic access to ALL your playbooks (used by AI agents for management):

Authorization: Bearer apb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

User API Keys work with the Management API (/api/manage/*) and Management MCP Server (/api/mcp/manage).

See Management API & MCP for details.

Human editor authorization

Signed-in editors use the same Supabase JWT/session authentication as owners. Their accepted membership authorizes content edits only. Visibility, collaborators, playbook API keys, secrets, ownership, and deletion are always owner-only. Playbook API keys cannot manage human collaborators.


Connect with ChatGPT (Custom GPT Actions)

You can connect any public playbook to ChatGPT as a Custom GPT Action. This allows ChatGPT to use your playbook's skills, read/write memory, and follow your persona's instructions.

Step-by-Step Setup

  • Open ChatGPT GPT Builder
- Go to chat.openai.com - Click "Explore GPTs" → "Create" - Or edit an existing GPT

  • Add an Action
- Go to Configure tab - Scroll to Actions → Click Create new action

  • Import OpenAPI Specification
- Click Import from URL - Enter your playbook's OpenAPI URL:
https://apbks.com/api/playbooks/{your-guid}?format=openapi
- ChatGPT will automatically parse the available endpoints

  • Set Up Authentication
- Under Authentication, select API Key - Auth Type: Bearer - API Key: Your playbook API key (e.g., apb_live_xxxxx...) > 💡 Create an API key at: Dashboard → Your Playbook → Settings → API Keys

  • Configure Privacy Policy (optional)
- Add a privacy policy URL if publishing publicly

  • Save and Test
- Click Save - Test by asking ChatGPT to use one of your playbook's skills

What ChatGPT Can Do

Once connected, ChatGPT can:

ActionEndpointDescription

Read MemoryGET /memoryAccess stored data
Search MemoryGET /memory?search=...&tags=...Find specific entries
Write MemoryPUT /memory/:keySave new data (requires API key)
Delete MemoryDELETE /memory/:keyRemove entries
List SkillsGET /skillsSee available capabilities
Get SkillGET /skills/:idGet skill metadata and SKILL.md content
List PersonasGET /personasGet AI personality instructions

Example: Using Memory

Ask ChatGPT:

"Save my preference for dark mode to the playbook memory"

ChatGPT will call:

PUT /api/playbooks/your-guid/memory/user_preferences
Authorization: Bearer apb_live_xxxxx
Content-Type: application/json

{
  "value": { "theme": "dark" },
  "tags": ["preferences", "ui"],
  "description": "User's display preferences"
}

Security Notes

  • API Key is stored encrypted by OpenAI
  • Keys only grant access to the specific playbook
  • Use separate keys for different integrations
  • Rotate keys periodically via Dashboard

OpenAPI Spec Contents

The ?format=openapi response includes:

{
  "openapi": "3.1.0",
  "info": {
    "title": "Your Playbook Name",
    "description": "Your playbook description"
  },
  "servers": [{ "url": "https://apbks.com/api" }],
  "paths": { /* memory, skills, personas endpoints */ },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key starting with apb_live_"
      }
    }
  },
  "x-playbook": {
    "guid": "your-guid",
    "persona": { /* embedded persona data */ },
    "skills": [/* full instructional skill records */],
    "mcp_servers": [/* MCP server configs */]
  }
}

The x-playbook extension provides full context to the AI, including system prompts, instructional skills, and federated tool metadata.


Public Endpoints

These endpoints don't require authentication. They only work for playbooks marked as public.

Get Playbook

Retrieve a playbook with all its contents.

GET /api/playbooks/:guid

Query Parameters:

ParameterTypeDefaultDescription

formatstringjsonOutput format: json, openapi, mcp, anthropic, markdown

Response (JSON):

{
  "id": "uuid",
  "guid": "abc123def456",
  "name": "My AI Assistant",
  "description": "A helpful coding assistant",
  "is_public": true,
  "persona": {
    "id": "uuid",
    "name": "Coder",
    "system_prompt": "You are a helpful coding assistant..."
  },
  "skills": [
    {
      "id": "uuid",
      "name": "Code review guide",
      "description": "Review code for issues",
      "content": "# Code review\nFollow these steps...",
      "licence": "MIT",
      "priority": 80
    }
  ],
  "mcp_servers": [
    {
      "id": "uuid",
      "name": "file_tools",
      "tools": [...],
      "resources": [...]
    }
  ]
}

Note: AgentPlaybooks uses 1 playbook = 1 persona. For backward compatibility, some endpoints still expose GET /personas which returns an array (length 1).

Response (OpenAPI):

Returns an OpenAPI 3.1 specification suitable for ChatGPT Custom Actions.

Response (MCP):

Returns an MCP-compatible server manifest with tools and resources.

Response (Anthropic):

Returns Anthropic-compatible federated tool definitions, instructional skills, and system prompt.

{
  "playbook": {
    "name": "My AI Assistant",
    "description": "...",
    "guid": "abc123def456"
  },
  "system_prompt": "## Coder\n\nYou are a helpful...",
  "tools": [
    {
      "name": "SERVER_NAME__code_review",
      "description": "Review code for issues",
      "input_schema": { ... }
    }
  ],
  "mcp_servers": [...]
}

Response (Markdown):

Returns a human-readable Markdown document.

Get Memory (Public Read with Search)

GET /api/playbooks/:guid/memory
GET /api/playbooks/:guid/memory?key=specific_key
GET /api/playbooks/:guid/memory?search=user
GET /api/playbooks/:guid/memory?tags=settings,preferences

Query Parameters:

ParameterTypeDescription

keystringGet specific memory by key
searchstringSearch in keys and descriptions
tagsstringFilter by tags (comma-separated, any match)

Response:

[
  {
    "key": "user_preferences",
    "value": { "theme": "dark" },
    "tags": ["settings", "user"],
    "description": "User preference settings",
    "updated_at": "2024-01-15T10:30:00Z"
  }
]

List Skills (Public Read)

Get all skills (capabilities/rules) for a playbook:

GET /api/playbooks/:guid/skills

Response:

[
  {
    "id": "uuid",
    "name": "Code review guide",
    "description": "Review code for issues and improvements",
    "content": "# Code review\nInspect correctness, security, and tests.",
    "licence": "MIT",
    "priority": 80
  }
]

Get Skill by ID

GET /api/playbooks/:guid/skills/:skillId

Supports lookup by UUID or skill name.

List Personas (Public Read)

GET /api/playbooks/:guid/personas

Response:

[
  {
    "id": "uuid",
    "name": "Coder",
    "system_prompt": "You are a helpful coding assistant...",
    "metadata": {}
  }
]


Authenticated Endpoints (User JWT Required)

These endpoints require a valid Supabase JWT token for the logged-in user.

List Playbooks

GET /api/playbooks

Response:

[
  {
    "id": "uuid",
    "guid": "abc123def456",
    "name": "My AI Assistant",
    "description": "A helpful coding assistant",
    "is_public": false,
    "persona_count": 1,
    "skill_count": 5,
    "mcp_server_count": 1,
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2024-01-15T12:00:00Z"
  }
]

Create Playbook

POST /api/playbooks
Content-Type: application/json

{
  "name": "My New Playbook",
  "description": "Optional description",
  "is_public": false,
  "config": {}
}

Response (201):

{
  "id": "uuid",
  "guid": "xyz789abc123",
  "name": "My New Playbook",
  "description": "Optional description",
  "is_public": false,
  "config": {},
  "created_at": "2024-01-15T10:00:00Z",
  "updated_at": "2024-01-15T10:00:00Z"
}

Update Playbook

PUT /api/playbooks/:id
Content-Type: application/json

{
  "name": "Updated Name",
  "description": "Updated description",
  "is_public": true
}

Delete Playbook

DELETE /api/playbooks/:id

Response:

{ "success": true }


Persona (Embedded in Playbook)

Architecture: 1 Playbook = 1 Persona

Each playbook has exactly one persona embedded directly in the playbook record. This simplifies the architecture and ensures consistent behavior.

Get Persona

The persona is returned directly with the playbook:

GET /api/playbooks/:guid

Returns:

{
  "id": "uuid",
  "guid": "abc123",
  "name": "My Playbook",
  "persona_name": "Expert Coder",
  "persona_system_prompt": "You are a helpful coding assistant...",
  "persona_metadata": { "avatar": "👨‍💻" },
  "instructions": "# Project rules\n\n- Use pnpm.",
  ...
}

persona_system_prompt carries the agent's identity; instructions carries the always-on rules of this project (AGENTS.md / CLAUDE.md content). They are stored as separate fields, and clients that need one system prompt receive them composed persona-first.

List Personas (Backward Compatibility)

For backward compatibility with existing integrations, a /personas endpoint is still available but returns a single-element array:

GET /api/playbooks/:id/personas

Response:

[
  {
    "id": "uuid",
    "playbook_id": "uuid",
    "name": "Expert Coder",
    "system_prompt": "You are a helpful coding assistant...",
    "metadata": { "avatar": "👨‍💻" }
  }
]

Update Persona

Update the persona via playbook update:

PUT /api/playbooks/:id
Content-Type: application/json

{
  "persona_name": "Updated Name",
  "persona_system_prompt": "Updated prompt...",
  "persona_metadata": { "avatar": "🤖" }
}

Or via the legacy persona endpoint (updates the playbook's embedded persona):

PUT /api/playbooks/:id/personas/:id
Content-Type: application/json

{
  "name": "Updated Name",
  "system_prompt": "Updated prompt..."
}

Note: Persona cannot be deleted separately - it's part of the playbook. Clear the values to reset to defaults.


Skills CRUD (Authenticated)

Manage skills within a playbook you own.

List Skills

GET /api/playbooks/:id/skills

Create Skill

POST /api/playbooks/:id/skills
Content-Type: application/json

{
  "name": "Code review guide",
  "description": "Use when reviewing a proposed code change",
  "content": "# Code review\n1. Inspect correctness...",
  "licence": "MIT",
  "priority": 80
}

Update Skill

PUT /api/playbooks/:id/skills/:sid
Content-Type: application/json

{
  "description": "Updated description",
  "content": "# Updated instructions\n...",
  "priority": 90
}

Delete Skill

DELETE /api/playbooks/:id/skills/:sid


Memory Write Endpoints (API Key or Owner)

Write operations require either an API key with memory:write permission or owner authentication.

Write Memory

PUT /api/playbooks/:guid/memory/:key
Authorization: Bearer apb_live_xxx
Content-Type: application/json

{
  "value": { "theme": "dark", "language": "en" },
  "tags": ["settings", "user"],
  "description": "User preference settings"
}

Request Body:

FieldTypeRequiredDescription

valueobjectYesAny JSON value to store
tagsstring[]NoTags for categorization and search
descriptionstringNoHuman-readable description

Response:

{
  "key": "user_preferences",
  "value": { "theme": "dark", "language": "en" },
  "tags": ["settings", "user"],
  "description": "User preference settings",
  "updated_at": "2024-01-15T10:30:00Z"
}

Note: If the key already exists, it will be updated (upsert behavior). Tags and description can be updated along with the value.

Delete Memory

DELETE /api/playbooks/:guid/memory/:key
Authorization: Bearer apb_live_xxx

Response:

{ "success": true }


Human Collaboration (Session Authenticated)

Owners can invite human editors without sharing a bearer API key. These endpoints require a signed-in Supabase session/JWT; playbook API keys cannot manage collaborators.

List editors and invitations

GET /api/playbooks/:id/collaborators
Authorization: Bearer <supabase_jwt_token>

Owner only. Returns active editors and pending or expired invitations. Raw invite tokens are never returned by this endpoint.

Create an editor invitation

POST /api/playbooks/:id/collaborators
Authorization: Bearer <supabase_jwt_token>

Response (201):

{
  "id": "uuid",
  "invite_expires_at": "2026-07-24T12:00:00.000Z",
  "created_at": "2026-07-21T12:00:00.000Z",
  "status": "pending",
  "invite_path": "/invite/one-time-token",
  "warning": "This invite link is shown once and expires in 72 hours."
}

The link can be accepted once and expires after 72 hours. A playbook can have at most 25 active editor and pending invite rows. Copy the URL immediately and treat it as a temporary credential.

Preview an invitation

GET /api/collaboration-invites/:token

Returns only the playbook name and expiry for a valid pending invitation. Invalid, expired, revoked, or already accepted tokens return 404.

Accept an invitation

POST /api/collaboration-invites/:token
Authorization: Bearer <supabase_jwt_token>

Atomically binds the invitation to the signed-in account. Owners cannot accept an invitation to their own playbook. Reuse returns 404 or 409 depending on whether another request won the acceptance race.

Remove an editor or revoke an invitation

DELETE /api/playbooks/:id/collaborators/:collaboratorId
Authorization: Bearer <supabase_jwt_token>

Owner only. Revocation ends membership access immediately but does not revoke any separately issued API key.

See Team Collaboration for the permission matrix and operational guidance.


API Keys Management (Authenticated)

Manage API keys for your playbooks. Only the playbook owner can access these endpoints.

List API Keys

GET /api/playbooks/:id/api-keys

Response:

[
  {
    "id": "uuid",
    "key_prefix": "apb_live_xxx...",
    "name": "Production Key",
    "permissions": ["memory:read", "memory:write"],
    "last_used_at": "2024-01-15T10:00:00Z",
    "expires_at": null,
    "is_active": true,
    "created_at": "2024-01-01T00:00:00Z"
  }
]

Create API Key

POST /api/playbooks/:id/api-keys
Content-Type: application/json

{
  "name": "Production Key",
  "permissions": ["memory:read", "memory:write", "skills:write"],
  "expires_at": "2025-01-01T00:00:00Z"
}

Available Permissions:

PermissionDescription

memory:readRead memory entries
memory:writeWrite/delete memory entries
skills:writeAdd/update skills
fullAll permissions

Response (201):

{
  "id": "uuid",
  "key_prefix": "apb_live_xxx...",
  "name": "Production Key",
  "permissions": ["memory:read", "memory:write", "skills:write"],
  "expires_at": "2025-01-01T00:00:00Z",
  "is_active": true,
  "created_at": "2024-01-15T10:00:00Z",
  "key": "apb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "warning": "Save this key now! It will not be shown again."
}

⚠️ Important: The full API key is only returned once at creation. Store it securely!

Delete API Key

DELETE /api/playbooks/:id/api-keys/:kid


Secrets

Encrypted credential storage for playbook tools and integrations. Values are AES-256-GCM encrypted with per-user derived keys.

Security model: Secret values are AES-256-GCM encrypted. By default, agents reference secrets by name and use the use_secret (GET, HEAD) and use_secret_write (POST, PUT, PATCH, DELETE) MCP tools, or the /proxy REST endpoint, to inject secrets into HTTP requests server-side. Agents can only access the raw secret value if the allow_api_key_reveal flag is set to true for that specific secret.

📘 Python integration guide: See Python Examples for ready-to-use code covering proxy, reveal, store, rotate, and delete operations.

List Secrets

GET /api/playbooks/:guid/secrets
GET /api/playbooks/:guid/secrets?category=api_key
Authorization: Bearer <jwt_or_api_key>

Returns metadata only (names, categories, usage stats). Never returns secret values.

Store Secret

POST /api/playbooks/:guid/secrets
Authorization: Bearer <jwt_or_api_key>
Content-Type: application/json

{
  "name": "OPENAI_API_KEY",
  "value": "sk-...",
  "description": "OpenAI API key for GPT-4",
  "category": "api_key",
  "expires_at": "2027-01-01T00:00:00Z",
  "allow_api_key_reveal": false
}

The value is encrypted immediately and never stored in plaintext.

expires_at is optional and must carry a timezone (Z or +02:00); a time without one is refused with 400, because the server would otherwise have to guess which instant it means. Once it passes, the secret can no longer be used: the proxy, use_secret, federated servers, and reveal by API key all refuse it with 403, and the refusal is recorded in the audit log. The owner can still reveal it in the dashboard, in order to replace it.

Reveal Secret

GET /api/playbooks/:guid/secrets/reveal/:name
Authorization: Bearer <jwt_or_api_key>

Returns the decrypted value. If called with an API key, the request will only succeed if the secret has allow_api_key_reveal set to true. Otherwise, it will return a 403 Forbidden error (Proxy Only mode).

Load Runtime Secrets

For application startup loading, use POST /api/playbooks/:guid/secrets/resolve with names, optional optional_names, and auth_mode (api_key or mtls). API keys require secrets:read. Certificate clients require a Cloudflare-verified, owner-registered certificate with explicit allowed names. Both require the secret's allow_api_key_reveal flag and refuse expired secrets. The response contains values and missing_optional; a failed batch contains no plaintext values. Maximum 100 distinct names. See Python Secrets for the client package, Docker examples, and owner-only certificate management endpoints.

Use Secret (Proxy)

POST /api/playbooks/:guid/secrets/proxy
Authorization: Bearer <api_key>
Content-Type: application/json

{
  "secret_name": "OPENAI_API_KEY",
  "url": "https://api.openai.com/v1/models",
  "method": "GET",
  "header_name": "Authorization",
  "header_prefix": "Bearer "
}

Makes an HTTP request with the secret injected server-side into the request to the provider. The caller authenticates with the owner's session JWT or a playbook API key with secrets:read / full permission. The provider key is not included in the proxy response. Set allowed_hosts on the secret to trusted provider hosts; the provider controls its response body.

By default (response_mode: "json"), the response is buffered and returned as { "status": 200, "status_text": "OK", "body": ... }. Existing callers keep this format.

Streaming REST/OpenAPI without MCP

For interactive model output, call this HTTP endpoint directly with response_mode: "stream". APB forwards response bytes as they arrive, without assembling a JSON envelope, parsing SSE events, or truncating the output. This works with browser fetch, Python, curl, and other HTTP clients. Use the provider's own streaming option as well (often body.stream: true); the proxy cannot make a non-streaming provider generate incremental output.

The endpoint is also advertised as proxySecretRequest in each playbook's generated OpenAPI 3.1 document:

GET /api/playbooks/:guid?format=openapi

The operation declares response_mode, the SSE, NDJSON, JSON, and binary response media types, and the x-streaming: true extension. Generated clients may still buffer responses by default, so configure the client to expose the raw response stream.

curl --no-buffer --request POST \
  "https://agentplaybooks.ai/api/playbooks/$PLAYBOOK_GUID/secrets/proxy" \
  --header "Authorization: Bearer $PLAYBOOK_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "secret_name": "MODEL_API_KEY",
    "url": "https://provider.example/v1/chat/completions",
    "method": "POST",
    "response_mode": "stream",
    "body": {"model": "MODEL_ID", "messages": [{"role": "user", "content": "Hello"}], "stream": true}
  }'

// In the APB frontend: authFetch uses the signed-in owner's session.
import { authFetch } from "@/lib/auth-fetch";

const abort = new AbortController();
const response = await authFetch(`/api/playbooks/${guid}/secrets/proxy`, {
  method: "POST",
  signal: abort.signal, // Call abort.abort() from your Stop button.
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    secret_name: "MODEL_API_KEY",
    url: providerEndpoint,
    method: "POST",
    response_mode: "stream",
    body: { model: modelId, messages, stream: true },
  }),
});
if (!response.ok) throw new Error(`Model request failed (${response.status})`);
if (!response.body) throw new Error("Missing response stream");

const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
try {
  while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    // Raw provider text. Feed this into your provider's incremental SSE/NDJSON
    // parser: one network chunk may contain partial or multiple events.
    console.log(value);
  }
} finally {
  await reader.cancel();
  reader.releaseLock();
}

External browser applications use fetch with an authorized APB credential and must be in the deployment's ALLOWED_ORIGINS. The provider key stays in the vault. CLI/backend callers can use a scoped APB API key; no MCP client or session initialization is required.

Streaming mode preserves the upstream HTTP status, including JSON error responses such as 429. SSE, JSON, NDJSON and binary content types are retained; other content types are served as application/octet-stream with nosniff. Cookies, redirects and arbitrary provider headers are not forwarded. Retry-After is retained. APB validation errors before streaming remain JSON errors. An upstream failure or timeout after headers have been sent terminates the stream; consumers must handle read failures.

timeout_ms covers the upstream request and response stream: streaming defaults to 300,000 ms with the same maximum; buffered mode defaults to 30,000 ms and is capped at 60,000 ms. Hosting infrastructure may impose a shorter limit. Cancelling the response or aborting the request cancels upstream work. Forwarding follows consumer demand, and usage/audit writes happen at stream completion or interruption, so they do not delay the first chunk. Responses disable caching and request that intermediaries avoid transformation/buffering.

MCP itself supports SSE transport, but APB's use_secret / use_secret_write tools currently collect a response into one tool result. Use those tools for agent workflows; use direct HTTP streaming for incremental model output. The vault's server-side credential injection does not depend on MCP.

Rotate Secret

PUT /api/playbooks/:guid/secrets/:name
Authorization: Bearer <jwt_or_api_key>
Content-Type: application/json

{
  "value": "sk-new-key-...",
  "description": "Updated key"
}

Rotating keeps the expiry: it is the owner's rule, not part of the value. To bring an expired secret back, send a later expires_at, or null to remove it.

Delete Secret

DELETE /api/playbooks/:guid/secrets/:name
Authorization: Bearer <jwt>

Owner only. Permanently deletes the secret.

Audit Trail

Vault operations are recorded in the same audit_logs trail as federated MCP calls, namespaced secret.* in operation, and read at the shared endpoint:

GET /api/playbooks/:guid/audit?operation=secret.
GET /api/playbooks/:guid/audit?operation=secret.use,secret.reveal&secret=OPENAI_API_KEY&limit=200
Authorization: Bearer <jwt_or_user_api_key>

Every operation — secret.create, secret.rotate, secret.update, secret.delete, secret.reveal, secret.use, secret.list — is recorded, including the ones that were refused. Each entry carries the outcome (success, denied, error), who acted (the owner's user id, or an API key's prefix), the destination host in target for secret.use, and a short error_code such as not_authorized, destination_not_allowed or reveal_not_permitted_for_api_key.

Entries never contain a secret value, a full outbound URL (a path or query string carries data of its own), or an API key.

Owner access only: a session, or a user API key with playbooks:read. A playbook API key — the credential agents use to perform vault operations — cannot read the record of them.

{
  "logs": [
    {
      "id": "…",
      "mcp_server_id": null,
      "operation": "secret.use",
      "target": "attacker.example.com",
      "status": "denied",
      "error_code": "destination_not_allowed",
      "actor_type": "api_key",
      "actor_id": "apb_live_a1b2",
      "secret_name": "OPENAI_API_KEY",
      "request_id": "…",
      "created_at": "2026-08-19T09:12:44.000Z"
    }
  ]
}

limit defaults to 100 and is capped at 500. operation takes a comma-separated list of exact names, or a single trailing-dot prefix (secret.) to mean every vault event; secret filters by name, which keeps working after the secret itself is deleted. The same endpoint answers at the original GET /api/mcp/audit/:guid.

Secret Categories

CategoryDescription

api_keyAPI keys (OpenAI, Anthropic, etc.)
passwordDatabase or service passwords
tokenOAuth tokens, webhook tokens
certificateTLS/SSL certificates
connection_stringDatabase connection strings
generalOther credentials


User API Keys (Account-level)

User API Keys provide access to ALL your playbooks, enabling AI agents to create and manage playbooks programmatically. Manage these at Dashboard Settings.

List User API Keys

GET /api/user/api-keys

Create User API Key

POST /api/user/api-keys
Content-Type: application/json

{
  "name": "Claude Desktop",
  "permissions": ["playbooks:read", "playbooks:write", "skills:write", "memory:read", "memory:write"]
}

Available Permissions:

PermissionDescription

playbooks:readList and view your playbooks
playbooks:writeCreate, update, delete playbooks (incl. persona)
skills:writeAdd/update/delete skills
memory:readRead memory entries
memory:writeWrite/delete memory entries
fullAll permissions

Response (201):

{
  "id": "uuid",
  "key_prefix": "apb_live_xxx...",
  "name": "Claude Desktop",
  "permissions": ["playbooks:read", "playbooks:write", "skills:write", "memory:read", "memory:write"],
  "is_active": true,
  "created_at": "2024-01-15T10:00:00Z",
  "key": "apb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "warning": "Save this key now! It will not be shown again."
}

Delete User API Key

DELETE /api/user/api-keys/:kid


Management API (User API Key)

For programmatic playbook management by AI agents. See Management API Documentation for details.

EndpointDescription

GET /api/manage/playbooksList all playbooks
POST /api/manage/playbooksCreate playbook
GET /api/manage/playbooks/:idGet playbook with contents
PUT /api/manage/playbooks/:idUpdate playbook (incl. persona fields)
DELETE /api/manage/playbooks/:idDelete playbook
POST /api/manage/playbooks/:id/skillsAdd skill
PUT/DELETE /api/manage/playbooks/:id/skills/:sidUpdate/Delete skill
GET /api/manage/playbooks/:id/memoryList/search memories
GET /api/manage/playbooks/:id/memory/:keyGet specific memory
PUT /api/manage/playbooks/:id/memory/:keyWrite memory
DELETE /api/manage/playbooks/:id/memory/:keyDelete memory
GET /api/manage/openapi.jsonOpenAPI specification

MCP Server: /api/mcp/manage


Skill Attachments

Skills can have file attachments for additional context (code files, docs, etc.).

List Attachments

GET /api/manage/skills/:skillId/attachments

Get Attachment

GET /api/manage/skills/:skillId/attachments/:attachmentId
GET /api/manage/skills/:skillId/attachments/:attachmentId?raw=true

Create Attachment

POST /api/manage/skills/:skillId/attachments
Content-Type: application/json

{
  "filename": "helper.py",
  "content": "def helper(): ...",
  "file_type": "python",
  "description": "Helper functions"
}

Supported file types: typescript, javascript, python, go, rust, sql, markdown, json, yaml, text, cursorrules, shell

Limits: 50KB per file, 10 files per skill

Update Attachment

PUT /api/manage/skills/:skillId/attachments/:attachmentId

Delete Attachment

DELETE /api/manage/skills/:skillId/attachments/:attachmentId

MCP Endpoints

Model Context Protocol endpoints for Claude and MCP-compatible clients.

Get MCP Manifest

GET /api/mcp/:guid

Response:

{
  "protocolVersion": "2025-03-26",
  "serverInfo": {
    "name": "My AI Assistant",
    "version": "1.0.0"
  },
  "capabilities": {
    "tools": {},
    "resources": {}
  },
  "tools": [
    {
      "name": "code_review",
      "description": "Review code for issues",
      "inputSchema": { ... }
    }
  ],
  "resources": [
    {
      "uri": "playbook://abc123/memory",
      "name": "Memory",
      "mimeType": "application/json"
    }
  ]
}

MCP JSON-RPC

POST /api/mcp/:guid
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

Supported Methods:

MethodDescription

initializeInitialize MCP connection
tools/listList available tools
resources/listList available resources
resources/readRead a resource
tools/callCall a tool (limited)


Public Repository

Browse Skills

GET /api/public/skills
GET /api/public/skills?tags=coding,automation
GET /api/public/skills?search=code+review

Query Parameters:

ParameterTypeDescription

tagsstringComma-separated tags to filter by
searchstringSearch in name and description

Response:

[
  {
    "id": "uuid",
    "name": "Code Reviewer",
    "description": "Reviews code for bugs and improvements",
    "tags": ["coding", "review"],
    "usage_count": 1234,
    "is_verified": true
  }
]

Get Skill Details

GET /api/public/skills/:id

Browse MCP Servers

GET /api/public/mcp
GET /api/public/mcp?tags=database,automation

Get MCP Server Details

GET /api/public/mcp/:id


Agent Skills Discovery (.well-known/skills)

The .well-known/skills convention lets any agent client install skills straight from a website — no registry, no sign-up, no credential. Point a client at a base URL and it reads the index.

GET /.well-known/skills/index.json
GET /.well-known/skills/:name/SKILL.md
GET /.well-known/skills/:name/:file

The same three routes exist per playbook, which is the form to hand a team: it publishes exactly that playbook's skills, with no chance of another publisher's name shadowing one of theirs.

GET /playbooks/:guid/.well-known/skills/index.json
GET /playbooks/:guid/.well-known/skills/:name/SKILL.md

Index response:

{
  "skills": [
    {
      "name": "code-review",
      "description": "Review a diff for bugs. Use when a pull request needs review.",
      "files": ["SKILL.md", "references/CHECKLIST.md"]
    }
  ]
}

SKILL.md is served as text/markdown and is the complete document, including frontmatter fields outside the Agent Skills spec (version, platforms, metadata..*) exactly as the author wrote them. files lists what the skill bundles; each is fetched from :name/:file and is restricted to the spec's directories (scripts/, references/, assets/, examples/, templates/).

Notes:

  • Public playbooks only. These routes are unauthenticated, so a private or
unlisted playbook is never published through them — use the CLI's pull for those.
  • Names are unique. A skill name is a directory name, so the site-wide index
serves one skill per name (the most recent) rather than the same name twice.
  • Responses are cacheable (max-age=300) and CORS-enabled (GET, OPTIONS).

Example — installing into Hermes Agent:

hermes skills search https://agentplaybooks.ai/playbooks/<guid> --source well-known
hermes skills install well-known:https://agentplaybooks.ai/playbooks/<guid>/.well-known/skills/<name>


Health Check

GET /api/health

Response:

{
  "status": "ok",
  "timestamp": "2024-01-15T10:00:00.000Z"
}


Error Responses

All endpoints return consistent error responses:

{
  "error": "Error message here"
}

HTTP Status Codes:

CodeDescription

200Success
201Created
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing authentication
403Forbidden - No permission for this resource
404Not Found - Resource doesn't exist or is private
500Internal Server Error


Rate Limits

Application-level rate limits are planned but are not currently part of the API contract. The hosting platform may still throttle abusive traffic. Clients should handle 429 Too Many Requests responses with exponential backoff and must not rely on X-RateLimit-* headers until versioned limits are documented here.


Endpoint Summary

Playbook CRUD

MethodEndpointAuthDescription

GET/api/playbooksJWTList user's playbooks
POST/api/playbooksJWTCreate playbook
GET/api/playbooks/:guidPublicGet playbook (format param)
PUT/api/playbooks/:idJWTUpdate playbook
DELETE/api/playbooks/:idJWTDelete playbook

Personas, Skills, Memory

MethodEndpointAuthDescription

GET/api/playbooks/:id/personasJWT/PublicGet persona (singleton array)
PUT/api/playbooks/:id/personas/:pidJWTUpdate embedded persona
GET/POST/api/playbooks/:id/skillsJWT/PublicList/Create skills
PUT/DELETE/api/playbooks/:id/skills/:sidJWTUpdate/Delete skill
GET/api/playbooks/:guid/memoryPublicRead memory
PUT/api/playbooks/:guid/memory/:keyAPI Key/JWTWrite memory
DELETE/api/playbooks/:guid/memory/:keyAPI Key/JWTDelete memory

API Keys

MethodEndpointAuthDescription

GET/api/playbooks/:id/api-keysJWTList playbook API keys
POST/api/playbooks/:id/api-keysJWTCreate playbook API key
DELETE/api/playbooks/:id/api-keys/:kidJWTDelete playbook API key
GET/api/user/api-keysJWTList user API keys
POST/api/user/api-keysJWTCreate user API key
DELETE/api/user/api-keys/:kidJWTDelete user API key

Human Collaboration

MethodEndpointAuthDescription

GET/api/playbooks/:id/collaboratorsOwner JWTList editors and invitations
POST/api/playbooks/:id/collaboratorsOwner JWTCreate a one-time editor invite
DELETE/api/playbooks/:id/collaborators/:collaboratorIdOwner JWTRemove editor or revoke invite
GET/api/collaboration-invites/:tokenInvite tokenPreview valid invite
POST/api/collaboration-invites/:tokenJWT + invite tokenAccept invite

Management API (AI Automation)

MethodEndpointAuthDescription

GET/api/manage/playbooksUser KeyList all playbooks
POST/api/manage/playbooksUser KeyCreate playbook
GET/api/manage/playbooks/:idUser KeyGet playbook with all contents
PUT/api/manage/playbooks/:idUser KeyUpdate playbook (incl. persona)
DELETE/api/manage/playbooks/:idUser KeyDelete playbook
POST/api/manage/playbooks/:id/skillsUser KeyAdd skill
PUT/DELETE/api/manage/playbooks/:id/skills/:sidUser KeyUpdate/Delete skill
GET/api/manage/playbooks/:id/memoryUser KeyList/search memories
GET/api/manage/playbooks/:id/memory/:keyUser KeyGet specific memory
PUT/api/manage/playbooks/:id/memory/:keyUser KeyWrite memory with tags
DELETE/api/manage/playbooks/:id/memory/:keyUser KeyDelete memory
GET/api/manage/openapi.jsonNoneOpenAPI specification
GET/POST/api/mcp/manageUser KeyManagement MCP Server

Skill Attachments

MethodEndpointAuthDescription

GET/api/manage/skills/:sid/attachmentsPublic/User KeyList attachments
GET/api/manage/skills/:sid/attachments/:aidPublic/User KeyGet attachment
POST/api/manage/skills/:sid/attachmentsUser KeyUpload attachment
PUT/api/manage/skills/:sid/attachments/:aidUser KeyUpdate attachment
DELETE/api/manage/skills/:sid/attachments/:aidUser KeyDelete attachment

Public Repository & MCP

MethodEndpointAuthDescription

GET/api/public/skillsNoneBrowse public skills
GET/api/public/mcpNoneBrowse public MCP servers
GET/api/public/playbooksNoneBrowse public playbooks
GET/POST/api/mcp/:guidPublicPlaybook MCP Server
GET/api/healthNoneHealth check

Notes:

  • Public endpoints work without auth for public playbooks, or with JWT for private playbooks you own.
  • User Key = User API Key (created at /dashboard/settings)
  • API Key = Playbook-specific API Key
Edit this page on GitHub
On this page
Base URLPlaybook identifiersAgent Reliability LoopAuthentication1. User Authentication (JWT)2. Playbook API Key Authentication3. User API Key AuthenticationHuman editor authorizationConnect with ChatGPT (Custom GPT Actions)Step-by-Step SetupWhat ChatGPT Can DoExample: Using MemorySecurity NotesOpenAPI Spec ContentsPublic EndpointsGet PlaybookGet Memory (Public Read with Search)List Skills (Public Read)Get Skill by IDList Personas (Public Read)Authenticated Endpoints (User JWT Required)List PlaybooksCreate PlaybookUpdate PlaybookDelete PlaybookPersona (Embedded in Playbook)Get PersonaList Personas (Backward Compatibility)Update PersonaSkills CRUD (Authenticated)List SkillsCreate SkillUpdate SkillDelete SkillMemory Write Endpoints (API Key or Owner)Write MemoryDelete MemoryHuman Collaboration (Session Authenticated)List editors and invitationsCreate an editor invitationPreview an invitationAccept an invitationRemove an editor or revoke an invitationAPI Keys Management (Authenticated)List API KeysCreate API KeyDelete API KeySecretsList SecretsStore SecretReveal SecretLoad Runtime SecretsUse Secret (Proxy)Rotate SecretDelete SecretAudit TrailSecret CategoriesUser API Keys (Account-level)List User API KeysCreate User API KeyDelete User API KeyManagement API (User API Key)Skill AttachmentsList AttachmentsGet AttachmentCreate AttachmentUpdate AttachmentDelete AttachmentMCP EndpointsGet MCP ManifestMCP JSON-RPCPublic RepositoryBrowse SkillsGet Skill DetailsBrowse MCP ServersGet MCP Server DetailsAgent Skills Discovery (.well-known/skills)Health CheckError ResponsesRate LimitsEndpoint SummaryPlaybook CRUDPersonas, Skills, MemoryAPI KeysHuman CollaborationManagement API (AI Automation)Skill AttachmentsPublic Repository & MCP