{
  "components": {
    "headers": {
      "ApiVersion": {
        "description": "The API version that produced this response. Present on every response, including errors.",
        "schema": {
          "enum": [
            "1"
          ],
          "type": "string"
        }
      },
      "Deprecation": {
        "description": "RFC 9745. Present once an operation or version is retiring: the date the deprecation took effect. Paired with `Sunset` and a `Link` at `rel=\"deprecation\"`.",
        "schema": {
          "format": "http-date",
          "type": "string"
        }
      },
      "Sunset": {
        "description": "RFC 8594. The earliest date the operation may stop answering. Never less than 90 days after `Deprecation`.",
        "schema": {
          "format": "http-date",
          "type": "string"
        }
      }
    },
    "parameters": {
      "ApiVersion": {
        "description": "Pin the API version. Omit it to get the current version. A version this server does not serve is refused with 400 rather than answered by another one.",
        "example": "1",
        "in": "header",
        "name": "Api-Version",
        "required": false,
        "schema": {
          "enum": [
            "1"
          ],
          "type": "string"
        }
      }
    },
    "schemas": {
      "AgentSignupComplete": {
        "additionalProperties": false,
        "description": "The signup is verified. Returned once with the raw key: store it now, because a later poll answers `consumed`.",
        "properties": {
          "apiKey": {
            "additionalProperties": false,
            "properties": {
              "id": {
                "type": "string"
              },
              "key": {
                "description": "The raw `db_` API key. Send it as a bearer token.",
                "type": "string"
              },
              "prefix": {
                "type": "string"
              },
              "scopes": {
                "items": {
                  "enum": [
                    "read",
                    "write"
                  ],
                  "type": "string"
                },
                "type": "array"
              }
            },
            "required": [
              "id",
              "key",
              "prefix",
              "scopes"
            ],
            "type": "object"
          },
          "email": {
            "format": "email",
            "type": "string"
          },
          "mcp": {
            "additionalProperties": false,
            "description": "Paste-ready configuration for the hosted MCP server, authorized with the new key.",
            "properties": {
              "claude": {
                "description": "A `claude mcp add` command line.",
                "type": "string"
              },
              "cursor": {
                "description": "A Cursor `mcp.json` object.",
                "type": "object"
              },
              "headers": {
                "additionalProperties": false,
                "properties": {
                  "Authorization": {
                    "type": "string"
                  }
                },
                "required": [
                  "Authorization"
                ],
                "type": "object"
              },
              "url": {
                "format": "uri",
                "type": "string"
              }
            },
            "required": [
              "claude",
              "cursor",
              "headers",
              "url"
            ],
            "type": "object"
          },
          "ok": {
            "const": true,
            "type": "boolean"
          },
          "status": {
            "const": "complete",
            "type": "string"
          },
          "user": {
            "additionalProperties": false,
            "properties": {
              "email": {
                "format": "email",
                "type": "string"
              },
              "id": {
                "type": "string"
              }
            },
            "required": [
              "email",
              "id"
            ],
            "type": "object"
          },
          "workspace": {
            "additionalProperties": false,
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "urlKey": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "name",
              "urlKey"
            ],
            "type": "object"
          }
        },
        "required": [
          "apiKey",
          "email",
          "mcp",
          "ok",
          "status",
          "user",
          "workspace"
        ],
        "type": "object"
      },
      "AgentSignupConsumed": {
        "additionalProperties": false,
        "description": "The key was already handed out. Sign in with `donebear auth login` instead.",
        "properties": {
          "message": {
            "type": "string"
          },
          "ok": {
            "const": true,
            "type": "boolean"
          },
          "status": {
            "const": "consumed",
            "type": "string"
          }
        },
        "required": [
          "message",
          "ok",
          "status"
        ],
        "type": "object"
      },
      "AgentSignupPending": {
        "additionalProperties": false,
        "description": "A verification email is on its way to the human. Keep `pollToken` secret: it redeems the API key.",
        "properties": {
          "email": {
            "format": "email",
            "type": "string"
          },
          "expiresInSeconds": {
            "type": "integer"
          },
          "instructions": {
            "additionalProperties": false,
            "properties": {
              "agent": {
                "type": "string"
              },
              "human": {
                "type": "string"
              }
            },
            "required": [
              "agent",
              "human"
            ],
            "type": "object"
          },
          "ok": {
            "const": true,
            "type": "boolean"
          },
          "pollToken": {
            "type": "string"
          },
          "status": {
            "const": "pending",
            "type": "string"
          },
          "verifyUrl": {
            "description": "The link from the email. The human opens it; the agent does not.",
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "email",
          "expiresInSeconds",
          "instructions",
          "ok",
          "pollToken",
          "status",
          "verifyUrl"
        ],
        "type": "object"
      },
      "AgentSignupPollPending": {
        "additionalProperties": false,
        "description": "The human has not verified yet. Poll again.",
        "properties": {
          "ok": {
            "const": true,
            "type": "boolean"
          },
          "status": {
            "const": "pending",
            "type": "string"
          }
        },
        "required": [
          "ok",
          "status"
        ],
        "type": "object"
      },
      "AgentSignupStartRequest": {
        "additionalProperties": false,
        "properties": {
          "email": {
            "description": "The human's real address. They must verify it, so never invent one.",
            "format": "email",
            "maxLength": 320,
            "type": "string"
          },
          "name": {
            "description": "Display name for the new account.",
            "maxLength": 100,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "type": "object"
      },
      "AgentSignupVerifyRequest": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "description": "The 6-digit code from the verification email.",
            "pattern": "^\\d{6}$",
            "type": "string"
          },
          "pollToken": {
            "maxLength": 128,
            "minLength": 16,
            "type": "string"
          }
        },
        "required": [
          "code",
          "pollToken"
        ],
        "type": "object"
      },
      "ErrorResponse": {
        "additionalProperties": false,
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          },
          "statusCode": {
            "type": "integer"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "GraphQLRequest": {
        "additionalProperties": false,
        "properties": {
          "operationName": {
            "type": [
              "string",
              "null"
            ]
          },
          "query": {
            "type": "string"
          },
          "variables": {
            "additionalProperties": true,
            "type": "object"
          }
        },
        "required": [
          "query"
        ],
        "type": "object"
      },
      "GraphQLResponse": {
        "additionalProperties": false,
        "properties": {
          "data": {
            "additionalProperties": true,
            "type": [
              "object",
              "null"
            ]
          },
          "errors": {
            "items": {
              "$ref": "#/components/schemas/GraphQLTopLevelError"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "GraphQLTopLevelError": {
        "additionalProperties": false,
        "properties": {
          "extensions": {
            "additionalProperties": false,
            "properties": {
              "code": {
                "description": "Typed domain code such as WORKSPACE_NOT_FOUND or ACCESS_DENIED.",
                "type": "string"
              }
            },
            "type": "object"
          },
          "message": {
            "type": "string"
          },
          "path": {
            "items": {
              "type": [
                "string",
                "integer"
              ]
            },
            "type": "array"
          }
        },
        "required": [
          "message"
        ],
        "type": "object"
      },
      "HealthResponse": {
        "additionalProperties": true,
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "type": "object"
      },
      "ReadyResponse": {
        "additionalProperties": false,
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "type": "object"
      },
      "SyncMutateRequest": {
        "additionalProperties": true,
        "description": "Server-sequenced mutation batch. Field names follow the sync protocol, not GraphQL.",
        "properties": {
          "actions": {
            "items": {
              "type": "object"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "UserError": {
        "additionalProperties": false,
        "description": "Typed GraphQL mutation error. Also returned on mutation payloads as `errors`.",
        "properties": {
          "code": {
            "type": "string"
          },
          "field": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ],
        "type": "object"
      },
      "WebhookDelivery": {
        "additionalProperties": false,
        "properties": {
          "attemptCount": {
            "type": "integer"
          },
          "completedAt": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "endpointId": {
            "format": "uuid",
            "type": "string"
          },
          "eventId": {
            "format": "uuid",
            "type": "string"
          },
          "eventType": {
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "lastAttemptAt": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "lastError": {
            "type": [
              "string",
              "null"
            ]
          },
          "lastResponseSnippet": {
            "type": [
              "string",
              "null"
            ]
          },
          "lastStatusCode": {
            "type": [
              "integer",
              "null"
            ]
          },
          "nextAttemptAt": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "payload": {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          "status": {
            "enum": [
              "pending",
              "succeeded",
              "failed"
            ],
            "type": "string"
          }
        },
        "required": [
          "attemptCount",
          "createdAt",
          "endpointId",
          "eventId",
          "eventType",
          "id",
          "payload",
          "status"
        ],
        "type": "object"
      },
      "WebhookEndpoint": {
        "additionalProperties": false,
        "properties": {
          "consecutiveFailures": {
            "type": "integer"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "disabledAt": {
            "format": "date-time",
            "type": [
              "string",
              "null"
            ]
          },
          "disabledReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "eventTypes": {
            "description": "Empty means every event type.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          },
          "url": {
            "format": "uri",
            "type": "string"
          },
          "workspaceId": {
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "consecutiveFailures",
          "createdAt",
          "description",
          "enabled",
          "eventTypes",
          "id",
          "updatedAt",
          "url",
          "workspaceId"
        ],
        "type": "object"
      },
      "WebhookEndpointCreate": {
        "additionalProperties": false,
        "properties": {
          "description": {
            "maxLength": 255,
            "type": "string"
          },
          "eventTypes": {
            "description": "Omit or send empty to receive every event type.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "description": "Public HTTPS URL. Private and loopback addresses are refused.",
            "format": "uri",
            "type": "string"
          },
          "workspaceId": {
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "url",
          "workspaceId"
        ],
        "type": "object"
      },
      "WebhookEndpointUpdate": {
        "additionalProperties": false,
        "properties": {
          "description": {
            "maxLength": 255,
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "eventTypes": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "url": {
            "format": "uri",
            "type": "string"
          }
        },
        "type": "object"
      },
      "WebhookEvent": {
        "additionalProperties": false,
        "description": "The body of every delivery. `data.object` is the full record after the change (before it, for a delete); `data.changes` names the fields that differ from the previous state on an update.",
        "properties": {
          "apiVersion": {
            "type": "string"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "data": {
            "additionalProperties": false,
            "properties": {
              "changes": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "object": {
                "additionalProperties": true,
                "type": "object"
              }
            },
            "required": [
              "changes",
              "object"
            ],
            "type": "object"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "syncActionId": {
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "type": "string"
          },
          "workspaceId": {
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "apiVersion",
          "createdAt",
          "data",
          "id",
          "type",
          "workspaceId"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "bearerFormat": "API key or JWT",
        "description": "Done Bear API key (`db_…`) or a Supabase JWT. API keys carry scoped permissions: `read`, `write`, and `admin`.",
        "scheme": "bearer",
        "type": "http"
      },
      "OAuth2": {
        "description": "OAuth 2.1 authorization code for the hosted MCP server and API. Request only the scopes the agent needs.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://mcp.donebear.com/authorize",
            "scopes": {
              "admin": "Manage workspaces, billing, members, and API keys.",
              "read": "Read tasks, projects, labels, teams, and workspace metadata.",
              "write": "Create and update tasks, projects, labels, and checklists."
            },
            "tokenUrl": "https://mcp.donebear.com/token"
          }
        },
        "type": "oauth2"
      },
      "SignupPollToken": {
        "bearerFormat": "Signup poll token",
        "description": "The `pollToken` from `POST /api/agent-signup`. It is good for one signup for 10 minutes and is not an API key.",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "externalDocs": {
    "description": "Done Bear developer resources",
    "url": "https://donebear.com/developers"
  },
  "info": {
    "contact": {
      "email": "hello@donebear.com",
      "name": "Done Bear",
      "url": "https://donebear.com/contact"
    },
    "description": "Done Bear is a local-first GTD task manager.\nUse GraphQL for reads and workspace administration, `/sync/mutate` for task writes,\nand the hosted MCP server for agent tools.\n\nScoped permissions:\n- `read`: list and show tasks, projects, labels, and teams\n- `write`: create and edit those records (includes `read`)\n- `admin`: workspaces, billing, members, and API keys (includes `write` and `read`)\n\nMCP OAuth advertises `read` and `write`. API keys accept `read`, `write`, and `admin`.\n\nGetting access:\n- The Free plan needs no card and includes API keys and MCP access (up to 250 active tasks and 2 teams).\n- An agent can open an account itself: `POST /api/agent-signup` with the human's email, the human verifies by link or 6-digit code, and the signup returns a `db_` API key scoped `read` and `write` (tag Onboarding).\n- There is no separate sandbox or test-mode API. https://donebear.com/playground is a sample workspace in the browser that needs no sign-in.\n\nVersioning: the version travels in the `Api-Version` request header, not the path.\nEvery response carries `Api-Version`. A version this server does not serve is refused\nwith 400 rather than answered by another one.\nA retiring operation or version gains `Deprecation` (RFC 9745) and `Sunset` (RFC 8594)\nheaders at least 90 days before it stops answering, with a `Link` at `rel=\"deprecation\"`.\nPolicy: https://donebear.com/docs/api/versioning",
    "license": {
      "name": "Proprietary",
      "url": "https://donebear.com/terms"
    },
    "title": "Done Bear API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/agent-signup": {
      "post": {
        "description": "Open a Free account for a human and get an API key without a browser session. No credentials needed. Done Bear emails the human a link and a 6-digit code. Once they verify, `GET /api/agent-signup/poll` or `POST /api/agent-signup/verify` returns a `db_` key scoped `read` and `write`, plus MCP config. An address that already has an account gets 409: sign in instead. Limits: 3 signups per email per hour, 5 per caller address per 10 minutes.",
        "operationId": "agentSignupStart",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentSignupStartRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentSignupPending"
                }
              }
            },
            "description": "Verification email sent."
          },
          "400": {
            "description": "The body failed validation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "This email already has an account."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Too many signups for this email or caller address."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Signup is not configured on this server."
          }
        },
        "security": [],
        "summary": "Start an agent signup",
        "tags": [
          "Onboarding"
        ]
      }
    },
    "/api/agent-signup/poll": {
      "get": {
        "description": "Check whether the human has verified. Answers `pending` until they do, then `complete` with the API key once, then `consumed`. Poll every few seconds.",
        "operationId": "agentSignupPoll",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/AgentSignupPollPending"
                    },
                    {
                      "$ref": "#/components/schemas/AgentSignupComplete"
                    },
                    {
                      "$ref": "#/components/schemas/AgentSignupConsumed"
                    }
                  ]
                }
              }
            },
            "description": "The signup's current state."
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "The signup expired or is unknown. Start again."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "No poll token was sent."
          }
        },
        "security": [
          {
            "SignupPollToken": []
          }
        ],
        "summary": "Poll an agent signup",
        "tags": [
          "Onboarding"
        ]
      }
    },
    "/api/agent-signup/verify": {
      "get": {
        "description": "The link in the verification email, for the human to open in a browser. Answers an HTML page; agents use `POST` with the code instead.",
        "operationId": "agentSignupVerifyLink",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "in": "query",
            "name": "token_hash",
            "required": true,
            "schema": {
              "maxLength": 512,
              "minLength": 16,
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "default": "email",
              "enum": [
                "email"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "Verified. The agent's next poll returns the key."
          },
          "400": {
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "The link is invalid or expired."
          }
        },
        "security": [],
        "summary": "Verify a signup from the email link",
        "tags": [
          "Onboarding"
        ]
      },
      "post": {
        "description": "Verify with the 6-digit code the human read out of the email, and get the API key in the same response. Five wrong codes end the signup.",
        "operationId": "agentSignupVerifyCode",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentSignupVerifyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/AgentSignupComplete"
                    },
                    {
                      "$ref": "#/components/schemas/AgentSignupConsumed"
                    }
                  ]
                }
              }
            },
            "description": "Verified."
          },
          "400": {
            "description": "The code is wrong, the signup expired, or the body failed validation."
          }
        },
        "security": [],
        "summary": "Verify a signup with the emailed code",
        "tags": [
          "Onboarding"
        ]
      }
    },
    "/api/webhooks": {
      "get": {
        "description": "List the webhook endpoints of a workspace. Requires the admin scope and an owner or admin membership.",
        "operationId": "webhooksList",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "in": "query",
            "name": "workspaceId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "endpoints": {
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      },
                      "type": "array"
                    },
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "endpoints",
                    "ok"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Endpoints in the workspace."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "admin"
            ]
          }
        ],
        "summary": "List webhook endpoints",
        "tags": [
          "Webhooks"
        ]
      },
      "post": {
        "description": "Create a webhook endpoint. The signing secret is returned once, in this response, and never again; rotate it to get a new one. Up to 10 endpoints per workspace.",
        "operationId": "webhooksCreate",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "endpoint": {
                      "$ref": "#/components/schemas/WebhookEndpoint"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "secret": {
                      "description": "`whsec_`-prefixed signing secret. Shown once.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "endpoint",
                    "ok",
                    "secret"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The endpoint and its secret."
          },
          "402": {
            "description": "Endpoint limit reached."
          },
          "503": {
            "description": "Webhooks are not configured on this deployment."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "admin"
            ]
          }
        ],
        "summary": "Create a webhook endpoint",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/api/webhooks/event-types": {
      "get": {
        "description": "The event types an endpoint can subscribe to.",
        "operationId": "webhooksEventTypes",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "eventTypes": {
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "eventTypes",
                    "ok"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Subscribable event types."
          }
        },
        "summary": "List webhook event types",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/api/webhooks/{id}": {
      "delete": {
        "description": "Delete an endpoint and its delivery history.",
        "operationId": "webhooksDelete",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted."
          },
          "404": {
            "description": "No such endpoint."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "admin"
            ]
          }
        ],
        "summary": "Delete a webhook endpoint",
        "tags": [
          "Webhooks"
        ]
      },
      "get": {
        "description": "Fetch one endpoint.",
        "operationId": "webhooksGet",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "endpoint": {
                      "$ref": "#/components/schemas/WebhookEndpoint"
                    },
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "endpoint",
                    "ok"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The endpoint."
          },
          "404": {
            "description": "No such endpoint."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "admin"
            ]
          }
        ],
        "summary": "Get a webhook endpoint",
        "tags": [
          "Webhooks"
        ]
      },
      "patch": {
        "description": "Update the URL, description, subscriptions, or enabled flag. Re-enabling clears the failure count.",
        "operationId": "webhooksUpdate",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "endpoint": {
                      "$ref": "#/components/schemas/WebhookEndpoint"
                    },
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "endpoint",
                    "ok"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The updated endpoint."
          },
          "404": {
            "description": "No such endpoint."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "admin"
            ]
          }
        ],
        "summary": "Update a webhook endpoint",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/api/webhooks/{id}/deliveries": {
      "get": {
        "description": "Delivery attempts for an endpoint, newest first. Page backwards with `before`.",
        "operationId": "webhooksDeliveriesList",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "before",
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "deliveries": {
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      },
                      "type": "array"
                    },
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "deliveries",
                    "ok"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "Deliveries."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "admin"
            ]
          }
        ],
        "summary": "List webhook deliveries",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/api/webhooks/{id}/deliveries/{deliveryId}/retry": {
      "post": {
        "description": "Queue one more attempt for a delivery that succeeded or failed.",
        "operationId": "webhooksDeliveryRetry",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "deliveryId",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Queued."
          },
          "404": {
            "description": "No such endpoint or delivery."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "admin"
            ]
          }
        ],
        "summary": "Retry a webhook delivery",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/api/webhooks/{id}/rotate-secret": {
      "post": {
        "description": "Issue a new signing secret. Deliveries carry signatures under both secrets for 24 hours so consumers can switch without a gap.",
        "operationId": "webhooksRotateSecret",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "endpoint": {
                      "$ref": "#/components/schemas/WebhookEndpoint"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "secret": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "endpoint",
                    "ok",
                    "secret"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "The endpoint and its new secret."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "admin"
            ]
          }
        ],
        "summary": "Rotate a webhook secret",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/api/webhooks/{id}/test": {
      "post": {
        "description": "Queue an `endpoint.test` event so the consumer can check its handler.",
        "operationId": "webhooksTest",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Queued."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "admin"
            ]
          }
        ],
        "summary": "Send a test webhook",
        "tags": [
          "Webhooks"
        ]
      }
    },
    "/graphql": {
      "post": {
        "description": "Execute a GraphQL query or mutation. Task writes belong on `/sync/mutate`. Query depth is capped at 10. Rate limit: 100 requests per 60 seconds per IP.",
        "operationId": "graphqlExecute",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GraphQLRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphQLResponse"
                }
              }
            },
            "description": "GraphQL execution result. Domain failures also appear as typed `UserError` objects on mutation payloads."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer credentials."
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded."
          }
        },
        "security": [
          {
            "BearerAuth": []
          },
          {
            "OAuth2": [
              "read"
            ]
          }
        ],
        "summary": "Execute a GraphQL operation",
        "tags": [
          "GraphQL"
        ]
      }
    },
    "/graphql/schema.graphql": {
      "get": {
        "description": "The GraphQL SDL as a file, served from the API origin. It carries `@deprecated(reason: ...)` inline; introspection hides deprecated fields unless the caller passes `includeDeprecated: true`.",
        "operationId": "graphqlSchemaGet",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "Schema definition language document."
          }
        },
        "summary": "GraphQL schema (SDL)",
        "tags": [
          "GraphQL"
        ]
      }
    },
    "/health": {
      "get": {
        "description": "Process liveness for the API origin. Does not wait on the database, Redis, or MCP.",
        "operationId": "healthGet",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            },
            "description": "API process is up."
          }
        },
        "summary": "Health check",
        "tags": [
          "Meta"
        ]
      }
    },
    "/openapi.json": {
      "get": {
        "description": "This OpenAPI document.",
        "operationId": "openapiGet",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "OpenAPI 3.1 specification."
          }
        },
        "summary": "OpenAPI specification",
        "tags": [
          "Meta"
        ]
      }
    },
    "/ready": {
      "get": {
        "description": "Optional readiness for the API origin. 200 when Postgres answers a cheap read-only ping, 503 when it does not. Not a Fly health check; /health stays process-only.",
        "operationId": "readyGet",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadyResponse"
                }
              }
            },
            "description": "Database answered."
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadyResponse"
                }
              }
            },
            "description": "Database did not answer."
          }
        },
        "summary": "Readiness check",
        "tags": [
          "Meta"
        ]
      }
    },
    "/sync/bootstrap": {
      "post": {
        "description": "Download the current workspace snapshot for a sync client. Requires `read`.",
        "operationId": "syncBootstrap",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "Bootstrap payload for the requesting workspace."
          },
          "401": {
            "description": "Missing or invalid bearer credentials."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "read"
            ]
          },
          {
            "OAuth2": [
              "read"
            ]
          }
        ],
        "summary": "Bootstrap a sync session",
        "tags": [
          "Sync"
        ]
      }
    },
    "/sync/deltas": {
      "get": {
        "description": "Fetch server-sequenced deltas since a client cursor. Requires `read`.",
        "operationId": "syncDeltas",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          },
          {
            "description": "Last applied sync id.",
            "in": "query",
            "name": "after",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Delta batch."
          },
          "401": {
            "description": "Missing or invalid bearer credentials."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "read"
            ]
          },
          {
            "OAuth2": [
              "read"
            ]
          }
        ],
        "summary": "Read sync deltas",
        "tags": [
          "Sync"
        ]
      }
    },
    "/sync/mutate": {
      "post": {
        "description": "Apply a batch of client mutations (task create/update/delete and related models). Requires `write`.",
        "operationId": "syncMutate",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiVersion"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SyncMutateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Accepted mutations and the new last sync id."
          },
          "401": {
            "description": "Missing or invalid bearer credentials."
          }
        },
        "security": [
          {
            "BearerAuth": [
              "write"
            ]
          },
          {
            "OAuth2": [
              "write"
            ]
          }
        ],
        "summary": "Apply sync mutations",
        "tags": [
          "Sync"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "Done Bear API",
      "url": "https://api.donebear.com"
    },
    {
      "description": "Hosted MCP server (Streamable HTTP)",
      "url": "https://mcp.donebear.com"
    },
    {
      "description": "Public marketing origin for discovery files",
      "url": "https://donebear.com"
    }
  ],
  "tags": [
    {
      "description": "GraphQL reads and workspace administration.",
      "externalDocs": {
        "url": "https://donebear.com/docs/api/graphql"
      },
      "name": "GraphQL"
    },
    {
      "description": "Server-sequenced local-first sync protocol.",
      "name": "Sync"
    },
    {
      "description": "Health and machine-readable catalogs.",
      "name": "Meta"
    },
    {
      "description": "Self-serve signup: an agent opens a Free account for a human and receives an API key.",
      "externalDocs": {
        "url": "https://donebear.com/auth.md"
      },
      "name": "Onboarding"
    },
    {
      "description": "Outbound webhooks: signed POSTs for task, project and comment changes.",
      "externalDocs": {
        "url": "https://donebear.com/docs/api/webhooks"
      },
      "name": "Webhooks"
    }
  ],
  "x-versioning": {
    "currentVersion": "1",
    "deprecationHeaders": [
      "Deprecation",
      "Sunset",
      "Link"
    ],
    "minimumSunsetNoticeDays": 90,
    "policy": "https://donebear.com/docs/api/versioning",
    "strategy": "header",
    "supportedVersions": [
      "1"
    ],
    "versionHeader": "Api-Version"
  }
}