{
  "openapi": "3.1.0",
  "info": {
    "title": "Deemwar MCP control plane API",
    "version": "1.0.0",
    "description": "The API behind the Deemwar MCP console: create a project from your REST API, review its tools, connect your login, add docs, validate and publish a hosted MCP endpoint.\n\nAuthenticate with a console session (`dms_...`, from email sign-in) or your tenant API key (`dmt_...`) as a bearer token. Sign-up is invite-only. Errors are JSON: `{\"error\": \"<code>\", \"message\": \"...\"}`. Routes tagged **Internal** are used by the data plane and the billing platform, not by publishers.\n\nGuides: https://mcp.deemwar.com/docs.html",
    "contact": {
      "name": "Deemwar support",
      "email": "support@deemwar.com",
      "url": "https://mcp.deemwar.com/support.html"
    },
    "termsOfService": "https://mcp.deemwar.com/terms.html"
  },
  "servers": [
    {
      "url": "https://mcpconsoleapi.deemwar.com"
    }
  ],
  "tags": [
    {
      "name": "Account"
    },
    {
      "name": "Projects"
    },
    {
      "name": "Sign-in"
    },
    {
      "name": "Docs"
    },
    {
      "name": "Branding"
    },
    {
      "name": "Chat AI"
    },
    {
      "name": "Points"
    },
    {
      "name": "System"
    },
    {
      "name": "Internal"
    }
  ],
  "security": [
    {
      "tenantKey": []
    }
  ],
  "paths": {
    "/healthz": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "Health check",
        "operationId": "healthz",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "const": "ok"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/signup": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Sign-up mode",
        "operationId": "getSignup",
        "description": "What the console needs to render sign-up. `mode` is `invite` while sign-up is invite-only.",
        "security": [],
        "responses": {
          "200": {
            "description": "Sign-up settings.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mode": {
                      "type": "string",
                      "enum": [
                        "open",
                        "invite"
                      ]
                    },
                    "request_email": {
                      "type": "string",
                      "format": "email"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/access-requests": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Request access",
        "operationId": "createAccessRequest",
        "description": "Asks for an invite. Requires a work email: personal mailbox providers (Gmail, Outlook, Yahoo, iCloud, Proton, …) and disposable domains are rejected with `work_email_required`. Rate-limited per client IP and per email domain. Idempotent per email, and the answer is always the same 202 whether the address is new, already requested or already a customer. When Cloudflare Turnstile is on (see `GET /v1/console/config`), a browser request (one that sends an `Origin` header) must carry the widget's response in the `X-Turnstile-Token` header: 403 `turnstile_required` / `turnstile_failed`, 503 `turnstile_unavailable`. Requests without `Origin` (scripts, CLIs) are not challenged; rate limits and lockout apply.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "company",
                  "email"
                ],
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "company": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "api": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Which API they want to connect (optional)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Received.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "const": "received"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/access-requests/review": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Review page (owner)",
        "operationId": "getAccessReview",
        "description": "The owner's signed, expiring link from the notification email. Renders the request and an approve/reject form; never changes state.",
        "security": [],
        "parameters": [
          {
            "name": "t",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "HMAC-signed review token."
          }
        ],
        "responses": {
          "200": {
            "description": "Confirm page.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or expired link.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Approve or reject (owner)",
        "operationId": "postAccessReview",
        "description": "Approve creates the tenant and emails the requester their tenant API key (dmt_…), which is never shown on the page or in the owner's email. Reject optionally sends a polite note.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "t",
                  "action"
                ],
                "properties": {
                  "t": {
                    "type": "string"
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "approve",
                      "reject"
                    ]
                  },
                  "notify": {
                    "type": "string",
                    "enum": [
                      "1"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or expired link.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Already decided, or approval failed (still pending).",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/access-requests": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "List access requests (owner)",
        "operationId": "listAccessRequests",
        "description": "Bearer `ADMIN_KEY` (scripts; 404 when unset) or a super-admin console session.",
        "security": [],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "approved",
                "rejected",
                "all"
              ],
              "default": "pending"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Requests, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requests": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "company": {
                            "type": "string"
                          },
                          "api": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "tenant_id": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "decided_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Admin list disabled."
          }
        }
      }
    },
    "/v1/console/signin": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Email me a sign-in link",
        "operationId": "requestConsoleSignin",
        "description": "Console sign-in by email. If the address is a tenant's contact email or belongs to an approved access request, a one-time sign-in link and a 6-digit code are emailed from noreply@deemwar.com; both expire after 15 minutes and work once. The answer is always the same 202 whether or not the address has access (no account enumeration). Rate-limited per email (5/hour) and per client IP (20/hour). When Cloudflare Turnstile is on (see `GET /v1/console/config`), a browser request (one that sends an `Origin` header) must carry the widget's response in the `X-Turnstile-Token` header: 403 `turnstile_required` / `turnstile_failed`, 503 `turnstile_unavailable`. Requests without `Origin` (scripts, CLIs) are not challenged; rate limits and lockout apply.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "additionalProperties": false,
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted (same answer for every address).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "const": "sent"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Not an email address (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests (`rate_limited`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/console/signin/verify": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Finish email sign-in",
        "operationId": "verifyConsoleSignin",
        "description": "Consumes the emailed link token (`token`, `dml_...`) or the 6-digit `code` with its `email`, and returns a console session token (`dms_...`, valid 12 hours) to use as the bearer instead of the tenant API key. Single use; a code allows 5 guesses. Rate-limited per client IP.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "Link token from the email (dml_...)."
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[0-9]{6}$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Signed in.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "Console session (dms_...)."
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "email": {
                      "type": "string"
                    },
                    "tenant": {
                      "$ref": "#/components/schemas/Tenant"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid, expired or used link or code (`invalid_link`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts (`rate_limited`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/console/signout": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Sign out",
        "operationId": "consoleSignout",
        "description": "Ends the console session used as the bearer. A tenant API key is left as is.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "Signed out."
          },
          "401": {
            "description": "Missing or invalid credential (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tenants": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Create a tenant",
        "operationId": "createTenant",
        "description": "Creates a tenant and returns its API key once. Sign-up is invite-only: the email must be allowlisted or `invite_code` must be valid.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTenantRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created. Store `api_key`; it is not shown again.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenant": {
                      "$ref": "#/components/schemas/Tenant"
                    },
                    "api_key": {
                      "type": "string",
                      "description": "Tenant API key, prefix dmt_."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid slug or email (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not invited (`invite_required`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Slug taken (`slug_taken`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Who is signed in",
        "operationId": "getMe",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "The caller.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenant": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Tenant"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "email": {
                      "type": "string"
                    },
                    "super_admin": {
                      "type": "boolean"
                    },
                    "acting_as": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": "The caller's tenant (null for a super admin who has none and has not switched), email, and super-admin flag. A super admin may send `X-Act-As-Tenant: <tenant id>` on any tenant route to act inside that tenant (non-GET requests are audit-logged)."
      }
    },
    "/v1/projects": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "List projects",
        "operationId": "listProjects",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Projects.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projects": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Project"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Create a project",
        "operationId": "createProject",
        "description": "Returns the project with its data-plane API key (`api_key`, prefix dmp_) once.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProjectRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "`name` is required (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "Get a project",
        "operationId": "getProject",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "The project.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Projects"
        ],
        "summary": "Remove",
        "operationId": "removeProject",
        "description": "Removes the project: it is no longer listed, served or editable. Soft: its host label stays reserved and its history is kept.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "removed": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such project.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/discover": {
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Discover operations from a spec",
        "operationId": "discover",
        "description": "Send `{url}` (a base URL or spec URL; common spec paths are probed), `{spec}` (raw JSON/YAML), a multipart field `file`, or `{}` to probe the project's `upstream_url`. Replaces the draft's operations; when a version is approved, returns a diff and carries your edits over.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DiscoverRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Discovered.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiscoverResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad body or URL (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`no_spec` (with `tried` and `docs_pages`) or `invalid_spec`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/draft": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "Get the draft config",
        "operationId": "getDraft",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "The draft tool configuration.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectConfig"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Projects"
        ],
        "summary": "Edit the draft config",
        "operationId": "patchDraft",
        "description": "Every field is optional. Operations and groups are matched by id. Secrets (`hs256_secret`, `sso_secrets`) are sealed at rest and never returned.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchDraftRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated draft.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectConfig"
                }
              }
            }
          },
          "400": {
            "description": "Unknown operation or group, invalid auth or sign-in settings (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Group still has operations (`group_not_empty`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/validate": {
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Validate live as a test user",
        "operationId": "validate",
        "description": "Signs in with a token or test credentials and calls one operation per group. Credentials are used for this request only.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validation report.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationReport"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Login failed (`validation_failed`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/approve": {
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Approve and publish",
        "operationId": "approve",
        "description": "Publishes the draft as a new version. Needs at least one enabled operation, an upstream URL, at most 15 groups and a built docs wiki.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Published.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    },
                    "project": {
                      "$ref": "#/components/schemas/Project"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Another approval happened (`conflict`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`not_approvable`, with `problems`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "problems": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/api-key": {
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Rotate the project API key",
        "operationId": "rotateProjectKey",
        "description": "Returns the project with a new `api_key`; the old key stops working.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Rotated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/activity": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "Recent activity",
        "operationId": "getActivity",
        "description": "Last 10 published versions and points spent per day for the last 14 days.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Activity.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "publishes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "usage": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UsageDay"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/brand": {
      "get": {
        "tags": [
          "Branding"
        ],
        "summary": "Get the sign-in brand",
        "operationId": "getBrand",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Brand.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Brand"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Branding"
        ],
        "summary": "Set the sign-in brand",
        "operationId": "putBrand",
        "description": "Colours may be adjusted for readable contrast (WCAG AA); `adjusted` lists what changed.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Brand"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved brand.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Brand"
                }
              }
            }
          },
          "400": {
            "description": "Invalid brand (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/signin/test": {
      "post": {
        "tags": [
          "Sign-in"
        ],
        "summary": "Test a sign-in method",
        "operationId": "testSignin",
        "description": "Runs one sign-in method (`callback`, `capture`, `token`, `sso`) against the draft with a test user. Credentials are used for this request only.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SigninTestRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoginCheck"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/signin/exchange-secret": {
      "post": {
        "tags": [
          "Sign-in"
        ],
        "summary": "Rotate the token-exchange client secret",
        "operationId": "rotateExchangeSecret",
        "description": "Creates a client secret for RFC 8693 token exchange from your servers. Shown once; it takes effect when you approve.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "New secret.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_secret": {
                      "type": "string"
                    },
                    "note": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/end-users": {
      "get": {
        "tags": [
          "Sign-in"
        ],
        "summary": "Signed-in end users",
        "operationId": "listEndUsers",
        "description": "Sessions on the project's data plane, with the sign-in mode of each. `unavailable` explains an empty list.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Sessions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sessions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "unavailable": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/docs": {
      "get": {
        "tags": [
          "Docs"
        ],
        "summary": "Docs summary",
        "operationId": "getDocs",
        "description": "Sources and build status of the project's docs wiki (used by `ask_docs`).",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "Docs service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/docs/openapi": {
      "post": {
        "tags": [
          "Docs"
        ],
        "summary": "Rebuild docs from the OpenAPI operations",
        "operationId": "rebuildOpenAPIDocs",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "Docs service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/docs/urls": {
      "post": {
        "tags": [
          "Docs"
        ],
        "summary": "Add docs URLs",
        "operationId": "addDocURLs",
        "description": "Up to 20 http(s) URLs per call; each is fetched and added to the wiki.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "urls"
                ],
                "properties": {
                  "urls": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Queued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sources": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad URLs (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Docs service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/docs/files": {
      "post": {
        "tags": [
          "Docs"
        ],
        "summary": "Upload docs files",
        "operationId": "addDocFiles",
        "description": "Multipart field `file` (repeatable): .md, .txt, .html or .pdf, up to 15 MB each.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "binary"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Queued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sources": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad file (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Docs service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/docs/sources/{sid}/retry": {
      "post": {
        "tags": [
          "Docs"
        ],
        "summary": "Retry a docs source",
        "operationId": "retryDocSource",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          },
          {
            "name": "sid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Docs source id."
          }
        ],
        "responses": {
          "200": {
            "description": "Summary (OpenAPI source).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "202": {
            "description": "Requeued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "Docs service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/docs/sources/{sid}": {
      "delete": {
        "tags": [
          "Docs"
        ],
        "summary": "Remove a docs source",
        "operationId": "deleteDocSource",
        "description": "The OpenAPI source is required and cannot be removed.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          },
          {
            "name": "sid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Docs source id."
          }
        ],
        "responses": {
          "200": {
            "description": "Summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Cannot remove the OpenAPI source (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Docs service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/docs/wiki": {
      "get": {
        "tags": [
          "Docs"
        ],
        "summary": "Wiki page list",
        "operationId": "getDocsWiki",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Wiki index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "Docs service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/docs/wiki/pages/{pid}": {
      "get": {
        "tags": [
          "Docs"
        ],
        "summary": "Wiki page",
        "operationId": "getDocsPage",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          },
          {
            "name": "pid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Wiki page id."
          }
        ],
        "responses": {
          "200": {
            "description": "Page.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "Docs service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/docs/ask": {
      "post": {
        "tags": [
          "Docs"
        ],
        "summary": "Ask the docs",
        "operationId": "askDocs",
        "description": "Same retrieval as the `ask_docs` MCP tool: cited passages for a question.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "question"
                ],
                "properties": {
                  "question": {
                    "type": "string"
                  },
                  "k": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10,
                    "default": 5
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Passages.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`question` is required (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Docs service unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/ai/models": {
      "get": {
        "tags": [
          "Chat AI"
        ],
        "summary": "Model list",
        "operationId": "listAIModels",
        "description": "OpenRouter's model list (cached for an hour) and the platform points pricing.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Models.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "models": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "pricing": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "platform_configured": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Model list unavailable (`models_unavailable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/ai": {
      "get": {
        "tags": [
          "Chat AI"
        ],
        "summary": "Get chat AI settings",
        "operationId": "getAI",
        "description": "The key is never returned; only its last 4 characters.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Settings.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIView"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Chat AI"
        ],
        "summary": "Set chat AI settings",
        "operationId": "putAI",
        "description": "`byok` uses your own key (provider `openrouter`, or `openai_compatible` with `base_url`). `platform` uses our key and spends points. `api_key` may be omitted when one is already stored for the same provider.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutAIRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIView"
                }
              }
            }
          },
          "400": {
            "description": "Invalid settings (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Platform mode needs a positive points balance (`ai_mode_not_allowed`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/ai/test": {
      "post": {
        "tags": [
          "Chat AI"
        ],
        "summary": "Test chat AI settings",
        "operationId": "testAI",
        "description": "One small call with the saved settings.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "`{ok:true, provider, model, latency_ms}` or `{ok:false, error}`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "409": {
            "description": "AI is off (`ai_off`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/billing": {
      "get": {
        "tags": [
          "Points"
        ],
        "summary": "Points balance",
        "operationId": "getBilling",
        "description": "Fresh balance, signup bonus, packs on sale and pause status. A paused project resumes once its balance is positive.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Billing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Billing"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/checkout": {
      "post": {
        "tags": [
          "Points"
        ],
        "summary": "Start a points checkout",
        "operationId": "checkout",
        "description": "Returns a checkout URL to send the browser to.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "return_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "sku": {
                    "type": "string",
                    "description": "Credit pack code; empty = first pack."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout URL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid body or unknown pack (`bad_request`, `unknown_pack`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "424": {
            "description": "The billing platform refused (`billing_rejected`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Checkout not live or unavailable (`checkout_not_live`, `billing_unavailable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/usage": {
      "get": {
        "tags": [
          "Points"
        ],
        "summary": "Points used per day",
        "operationId": "getUsage",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 366,
              "default": 30
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "days": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UsageDay"
                      }
                    },
                    "totals": {
                      "$ref": "#/components/schemas/UsageDay"
                    },
                    "since": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/config": {
      "get": {
        "tags": [
          "Internal"
        ],
        "summary": "Approved config (data plane)",
        "operationId": "getConfig",
        "description": "For a self-hosted data plane. Supports `If-None-Match`.",
        "security": [
          {
            "projectKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Approved config.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectConfig"
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "304": {
            "description": "Not modified."
          },
          "401": {
            "description": "Project API key required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Out of points (`project_paused`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No approved config (`not_approved`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/dataplane/configs": {
      "get": {
        "tags": [
          "Internal"
        ],
        "summary": "Config feed (hosted data plane)",
        "operationId": "dataplaneConfigs",
        "security": [
          {
            "serviceKey": []
          }
        ],
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Unix seconds."
          }
        ],
        "responses": {
          "200": {
            "description": "Changed configs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Bad `since`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Service key required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/dataplane/ai-key": {
      "get": {
        "tags": [
          "Internal"
        ],
        "summary": "Resolve a sealed AI key",
        "operationId": "dataplaneAIKey",
        "security": [
          {
            "serviceKey": []
          },
          {
            "projectKey": []
          }
        ],
        "parameters": [
          {
            "name": "project_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "key_ref",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Key (no-store).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown key_ref.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/dataplane/auth-secret": {
      "get": {
        "tags": [
          "Internal"
        ],
        "summary": "Resolve a sealed auth secret",
        "operationId": "dataplaneAuthSecret",
        "security": [
          {
            "serviceKey": []
          },
          {
            "projectKey": []
          }
        ],
        "parameters": [
          {
            "name": "secret_ref",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Secret (no-store).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown secret_ref.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/dataplane/usage": {
      "post": {
        "tags": [
          "Internal"
        ],
        "summary": "Report usage (debit relay)",
        "operationId": "dataplaneUsage",
        "security": [
          {
            "serviceKey": []
          },
          {
            "projectKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Debit results.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Bad body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/webhook": {
      "post": {
        "tags": [
          "Internal"
        ],
        "summary": "Billing platform webhook",
        "operationId": "billingWebhook",
        "description": "Signed with `X-Deemwar-Signature: t=<unix>,v1=<hex>` (HMAC-SHA256).",
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`{status: ok | duplicate | ignored}`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Bad event.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Bad signature (`bad_signature`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/relay/token": {
      "post": {
        "tags": ["Account"],
        "summary": "Mint a terminal machine token",
        "description": "dmcp terminal serve --publish calls this to link the machine to the terminal relay (spec 006, docs/specs/in-progress/006-relay-contract.md). The machine then talks to /v1/relay/machine/{session,events,push} with the returned dmr_ token.",
        "operationId": "relayToken",
        "security": [{"tenantKey": []}],
        "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["machine"], "properties": {"machine": {"type": "string"}}}}}},
        "responses": {
          "200": {"description": "The machine token and the tenant's terminal URL.", "content": {"application/json": {"schema": {"type": "object", "properties": {
            "token": {"type": "string"}, "expires_at": {"type": "string"}, "tenant": {"type": "string"}, "title": {"type": "string"},
            "url": {"type": "string"}, "authorization_server": {"type": "string"}, "project_id": {"type": "string"}, "relay": {"type": "string"}}}}}},
          "409": {"description": "The tenant has no MCP project to sign people in with."},
          "503": {"description": "The relay is not configured."}
        }
      }
    },
    "/v1/terminal": {
      "get": {
        "tags": ["Account"],
        "summary": "The tenant's terminal",
        "description": "Tenant label, title, public MCP URL and whether the caller is the owner (owner-only: typing, expose/hide). The rest of /v1/terminal/... is passed to the relay; see docs/specs/in-progress/006-relay-contract.md.",
        "operationId": "terminalInfo",
        "security": [{"tenantKey": []}],
        "responses": {
          "200": {"description": "Terminal info.", "content": {"application/json": {"schema": {"type": "object", "properties": {
            "tenant": {"type": "string"}, "title": {"type": "string"}, "url": {"type": "string"}, "owner": {"type": "boolean"}}}}}}
        }
      }
    },
    "/v1/tunnels": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "The live herdr agent exposure",
        "operationId": "getTunnel",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Which agent is exposed now, if any. dmcp polls this and exits when another agent replaced it.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "active": {
                      "type": "boolean"
                    },
                    "agent": {
                      "type": "string"
                    },
                    "hostname": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Cloudflare failed (`cloudflare`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Publishing is not configured (`unavailable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Expose one herdr agent (dmcp serve --publish)",
        "operationId": "createTunnel",
        "description": "Exposes ONE herdr agent at the tenant's stable hostname `<tenant>-terminal.<domain>` through the tenant's single Cloudflare Tunnel, routed to `127.0.0.1:<port>` on the machine running `dmcp serve --publish`. Only one exposure is live per tenant: publishing agent B moves the hostname to B (the response and `GET` name the live agent). People sign in through the tenant's own MCP project (its authorization server, with dynamic client registration and PKCE); tokens are bound to `https://<tenant>-terminal.<domain>/mcp`. The tenant always gets the same URL. The exposure is removed when dmcp exits (DELETE) or after 10 minutes with no tunnel connection.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "agent"
                ],
                "properties": {
                  "agent": {
                    "type": "string",
                    "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
                    "description": "herdr agent name (lowercase letters, digits, hyphens); named in the DNS record and shown to callers"
                  },
                  "port": {
                    "type": "integer",
                    "minimum": 1024,
                    "maximum": 65535,
                    "default": 8765
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The published endpoint and the cloudflared run token (a secret: pass it to `cloudflared tunnel run` via TUNNEL_TOKEN, never log it).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "hostname": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "tunnel_token": {
                      "type": "string"
                    },
                    "project_id": {
                      "type": "string"
                    },
                    "authorization_server": {
                      "type": "string"
                    },
                    "agent": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad agent name or port (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "No MCP project to sign in through (`needs_project`), or the hostname collides with another host (`host_taken`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Cloudflare failed (`cloudflare`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Publishing is not configured (`unavailable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Account"
        ],
        "summary": "Stop the herdr agent exposure (dmcp unpublish)",
        "operationId": "deleteTunnel",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "responses": {
          "204": {
            "description": "Tunnel and DNS record removed (idempotent)."
          },
          "401": {
            "description": "Missing or invalid tenant API key (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Cloudflare failed (`cloudflare`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Publishing is not configured (`unavailable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Bad agent name (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "agent",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Only remove the exposure if this agent is the live one (a replaced dmcp exiting never removes its successor). Omit to remove whatever is live."
          }
        ]
      }
    },
    "/v1/terminals/plan": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Terminals plan: trial days left, plan, renew link",
        "operationId": "getTerminalPlan",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "description": "The 30-day trial starts on the first terminal publish. Day 30 without a licence: the terminal MCP answers every call with `message` (blocked). Day 37: the public URL is removed. Paying (license.deemwar.com) restores the same URL. `?fresh=1` re-reads the licence now.",
        "parameters": [
          {
            "name": "fresh",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The plan.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "none",
                        "trial",
                        "active",
                        "ended",
                        "removed"
                      ]
                    },
                    "plan": {
                      "type": "string",
                      "enum": [
                        "",
                        "trial",
                        "paid",
                        "lifetime"
                      ]
                    },
                    "trial_started_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "trial_ends_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "valid_until": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "days_left": {
                      "type": "integer"
                    },
                    "removes_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "blocked": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "renew_url": {
                      "type": "string"
                    },
                    "prices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "sku": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "usd_cents": {
                            "type": "integer"
                          },
                          "inr_paise": {
                            "type": "integer"
                          },
                          "days": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/terminals/checkout": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Checkout link for a Terminals licence",
        "operationId": "terminalCheckout",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sku": {
                    "type": "string",
                    "enum": [
                      "terminals_month",
                      "terminals_year",
                      "terminals_early"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A license.deemwar.com checkout session (expires in an hour).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "checkout_url": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unknown sku (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Checkout not open yet (`checkout_unavailable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/terminals/renew/{token}": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Emailed renew link",
        "operationId": "terminalRenew",
        "security": [],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sku",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to a fresh checkout session."
          },
          "404": {
            "description": "Unknown link."
          },
          "503": {
            "description": "Checkout not open yet."
          }
        }
      }
    },
    "/v1/terminals/keys": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "List terminal API keys",
        "operationId": "listTerminalKeys",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Keys (never the secret).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "scopes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "last_used_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "revoked_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Create a terminal API key (shown once)",
        "operationId": "createTerminalKey",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "description": "A named, scoped key the terminal MCP accepts as `Authorization: Bearer dtk_...` alongside OAuth. Scopes: terminal:ask, terminal:read (default both). Stored hashed; every use is logged with the key name as the caller.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The key, shown once.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad name or scope (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A live key has that name (`name_taken`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/terminals/keys/{name}": {
      "delete": {
        "tags": [
          "Account"
        ],
        "summary": "Revoke a terminal API key",
        "operationId": "revokeTerminalKey",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Revoked."
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No live key with that name (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/terminals/keys/verify": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Check a terminal API key (dmcp)",
        "operationId": "verifyTerminalKey",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The key's name and scopes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "caller": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unknown, revoked or another tenant's key (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/dataplane/terminal-check": {
      "post": {
        "tags": [
          "Internal"
        ],
        "summary": "Terminal plan + API key check (relay path)",
        "operationId": "dataplaneTerminalCheck",
        "security": [
          {
            "serviceKey": []
          }
        ],
        "description": "Data-plane service key. Is the tenant's Terminals plan ended (answer every call with `message`)? With `key`: is this dtk_ key live for the tenant, with which scopes (the caller is `key:<name>`)?",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tenant_id": {
                    "type": "string"
                  },
                  "key": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Plan state and key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "blocked": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "key": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "scopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "caller": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "tenant_id missing (`bad_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Service key missing (`unauthorized`) or key unknown/revoked (`invalid_key`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/console/signin/password": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Sign in with a password",
        "operationId": "passwordConsoleSignin",
        "description": "Optional per-email console password (bcrypt). Returns the same console session as email sign-in. Every failure (unknown email, no password set, wrong password, locked account, no tenant) gets the same 401. 5 failures lock the account for 15 minutes; 20 attempts per client IP per 10 minutes. When Cloudflare Turnstile is on (see `GET /v1/console/config`), a browser request (one that sends an `Origin` header) must carry the widget's response in the `X-Turnstile-Token` header: 403 `turnstile_required` / `turnstile_failed`, 503 `turnstile_unavailable`. Requests without `Origin` (scripts, CLIs) are not challenged; rate limits and lockout apply.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "email",
                  "password"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Signed in.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "Console session (dms_...)."
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "email": {
                      "type": "string"
                    },
                    "tenant": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Tenant"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "super_admin": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Any failure (`invalid_credentials`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts (`rate_limited`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/console/config": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Public console settings",
        "operationId": "consoleConfig",
        "description": "What the console's sign-in pages need before sign-in: whether Cloudflare Turnstile is on and, when it is, its public site key.",
        "security": [],
        "responses": {
          "200": {
            "description": "Settings.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "turnstile": {
                      "type": "object",
                      "properties": {
                        "enabled": {
                          "type": "boolean"
                        },
                        "site_key": {
                          "type": "string",
                          "description": "Present only when enabled."
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/console/cli/authorize": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Authorize dmcp (browser login)",
        "operationId": "cliAuthorize",
        "description": "Called by the console's /cli-login page when the signed-in person clicks Allow. Mints a single-use code that expires in 60 seconds and only works with the PKCE verifier behind `code_challenge`. Needs a console session (dms_), not a tenant key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "code_challenge",
                  "code_challenge_method"
                ],
                "properties": {
                  "code_challenge": {
                    "type": "string",
                    "description": "BASE64URL(SHA-256(verifier)), 43 chars."
                  },
                  "code_challenge_method": {
                    "type": "string",
                    "enum": [
                      "S256"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Code minted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "XXXX-XXXX"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad challenge.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Signed in with a tenant key, not a console session (`session_required`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/console/cli/token": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Exchange a dmcp login code",
        "operationId": "cliToken",
        "description": "dmcp exchanges the code (from its loopback callback or pasted by the person) plus its PKCE verifier for its own console session. The code is consumed by the first attempt, right or wrong. 30 attempts per client IP per 10 minutes.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "code",
                  "code_verifier"
                ],
                "properties": {
                  "code": {
                    "type": "string"
                  },
                  "code_verifier": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Signed in.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "Console session (dms_...)."
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "email": {
                      "type": "string"
                    },
                    "tenant": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Tenant"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "super_admin": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Wrong, used or expired code, or wrong verifier (`invalid_grant`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/console/password": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Set or change your console password",
        "operationId": "changeConsolePassword",
        "description": "Console session only (`dms_`). `current_password` is required when a password is already set. New password: 12 to 72 bytes.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "new_password"
                ],
                "properties": {
                  "current_password": {
                    "type": "string"
                  },
                  "new_password": {
                    "type": "string",
                    "minLength": 12
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Password saved."
          },
          "400": {
            "description": "Too weak (`weak_password`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Wrong current password, locked, or not a console session (`invalid_credentials`, `forbidden`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/tenants": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "List tenants (super admin)",
        "operationId": "adminListTenants",
        "description": "Super admins only: a console session (`dms_`) whose email is in `MCPSTORE_SUPER_ADMINS`. ",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Tenants, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenants": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Tenant"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not a super admin (`forbidden`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/tenants/{id}/switch": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Switch into a tenant (super admin)",
        "operationId": "adminSwitchTenant",
        "description": "Super admins only: a console session (`dms_`) whose email is in `MCPSTORE_SUPER_ADMINS`. Audit-logged; afterwards send `X-Act-As-Tenant: <id>`.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenant": {
                      "$ref": "#/components/schemas/Tenant"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not a super admin (`forbidden`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/access-requests/{id}/approve": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Approve an access request (super admin)",
        "operationId": "adminApproveAccess",
        "description": "Super admins only: a console session (`dms_`) whose email is in `MCPSTORE_SUPER_ADMINS`. Creates the tenant and emails the requester. Audit-logged.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "notify": {
                    "type": "boolean",
                    "description": "On reject, email a polite note."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Decided.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "tenant_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Already decided (`conflict`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not a super admin (`forbidden`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/access-requests/{id}/reject": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Reject an access request (super admin)",
        "operationId": "adminRejectAccess",
        "description": "Super admins only: a console session (`dms_`) whose email is in `MCPSTORE_SUPER_ADMINS`. Audit-logged.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "notify": {
                    "type": "boolean",
                    "description": "On reject, email a polite note."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Decided.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "tenant_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Already decided (`conflict`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not a super admin (`forbidden`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/audit": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Super-admin audit log",
        "operationId": "adminAudit",
        "description": "Super admins only: a console session (`dms_`) whose email is in `MCPSTORE_SUPER_ADMINS`. Latest 200 entries.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Entries, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "entries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "actor": {
                            "type": "string"
                          },
                          "action": {
                            "type": "string"
                          },
                          "tenant_id": {
                            "type": "string"
                          },
                          "target": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in (`unauthorized`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not a super admin (`forbidden`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/idp/token": {
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Deemwar account token (sign-in for your own MCP project)",
        "operationId": "idpToken",
        "description": "Identity provider for tenants without a login system: a project's capture sign-in posts here (served at https://mcpid.deemwar.com). Returns an ES256 JWT (iss `https://mcpid.deemwar.com`, aud `deemwar:<tenant>`, sub = email, role `admin`, 1 hour) only for the tenant's admin email or a super admin; every other case gets the same 401 as a wrong password. Same rate limits and lockout as password sign-in. 404 when the provider is not configured.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "email",
                  "password",
                  "tenant"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string"
                  },
                  "tenant": {
                    "type": "string",
                    "description": "Tenant slug."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token issued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "const": "Bearer"
                    },
                    "expires_in": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Wrong credentials, or not allowed for this tenant."
          },
          "404": {
            "description": "Provider not configured."
          },
          "429": {
            "description": "Rate limited."
          }
        }
      }
    },
    "/v1/idp/jwks.json": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Deemwar account public keys",
        "operationId": "idpJWKS",
        "security": [],
        "description": "JWKS for tokens from `POST /v1/idp/token`. 404 when the provider is not configured.",
        "responses": {
          "200": {
            "description": "JWK set.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Provider not configured."
          }
        }
      }
    },
    "/v1/projects/{id}/unpublish": {
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Unpublish",
        "operationId": "unpublish",
        "description": "Takes a published project offline (status `unpublished`). Every version is kept; approving again brings it back. The data plane stops serving its host on its next feed poll.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Unpublished.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "$ref": "#/components/schemas/Project"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`not_published`: never published.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such project.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/understand": {
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Cross-check the spec against docs and code",
        "operationId": "understand",
        "description": "One model pass over the draft's operations plus the product docs and/or code you send. Writes into the draft only: a server summary (also the purpose), what it is and is not, required order, side effects, per-operation descriptions and flags where the sources disagree. Annotations only move towards safety (marked destructive / not read-only, never the reverse). Uses the project's AI settings, else platform AI. Body up to 4 MB.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "docs": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "text": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "code": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "text": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The understanding and the operations it changed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "understanding": {
                      "type": "object"
                    },
                    "operations": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "No docs or code sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`no_operations` or `ai_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`model_failed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/skill-preview": {
      "get": {
        "tags": [
          "Projects"
        ],
        "summary": "Preview the skill",
        "operationId": "skillPreview",
        "description": "The SKILL.md the current draft would publish, including the is / is-not sections from understand.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "responses": {
          "200": {
            "description": "SKILL.md",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "`skill_failed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/database": {
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Add a Postgres database",
        "operationId": "addDatabase",
        "description": "Connects with the connection string (TLS required: sslmode=require, verify-ca or verify-full; public addresses only), introspects the chosen schemas (names, types, comments, keys, row estimates; never row values), reports whether the role can write, seals the connection string and puts the data model in the draft and the docs wiki. The data plane then serves list_tables, describe_table and a read-only query tool. The connection string is never returned or logged.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "dsn"
                ],
                "properties": {
                  "dsn": {
                    "type": "string",
                    "description": "Postgres connection string (secret)."
                  },
                  "schemas": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Default [\"public\"]."
                  },
                  "show_sensitive": {
                    "type": "boolean",
                    "description": "Return columns marked sensitive in query results (default false)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Introspected.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tables": {
                      "type": "integer"
                    },
                    "schemas": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "sensitive_columns": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "role_can_write": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "data_model": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "No dsn.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`bad_dsn`, `connect_failed`, `introspect_failed` or `no_tables`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{id}/data/s3": {
      "post": {
        "tags": [
          "Projects"
        ],
        "summary": "Add an S3 bucket",
        "operationId": "addS3",
        "description": "Inventories an S3 or S3-compatible bucket/prefix (file types, sizes, folders), reads the header of each CSV/TSV/JSON Lines/JSON file (column names only, never values), adds its documents (md/txt/html/pdf, up to 20) and a data overview to the docs wiki, and seals the access keys (none for a public bucket). The data plane then serves list_files, read_file and read_table, scoped to the prefix, without sensitive columns. Keys are never returned or logged.",
        "security": [
          {
            "tenantKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Project id (prj_...)."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "bucket"
                ],
                "properties": {
                  "bucket": {
                    "type": "string"
                  },
                  "prefix": {
                    "type": "string"
                  },
                  "endpoint": {
                    "type": "string",
                    "description": "https URL; empty = AWS"
                  },
                  "region": {
                    "type": "string"
                  },
                  "access_key": {
                    "type": "string"
                  },
                  "secret_key": {
                    "type": "string",
                    "description": "Secret."
                  },
                  "show_sensitive": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Inventoried.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    },
                    "documents": {
                      "type": "integer"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "overview": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad bucket, endpoint or key pair.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`s3_failed` or `empty`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "tenantKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Tenant API key (dmt_...) or a console session (dms_...) from email sign-in (POST /v1/console/signin/verify)."
      },
      "projectKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Project API key (dmp_...), for a self-hosted data plane."
      },
      "serviceKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Hosted data plane service key."
      },
      "webhookSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Deemwar-Signature"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable code."
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Tenant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateTenantRequest": {
        "type": "object",
        "required": [
          "slug",
          "email"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9]([a-z0-9-]{0,38}[a-z0-9])?$"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "invite_code": {
            "type": "string"
          }
        }
      },
      "CreateProjectRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "upstream_url": {
            "type": "string",
            "format": "uri"
          },
          "purpose": {
            "type": "string"
          }
        }
      },
      "Project": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "string"
          },
          "tenant_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "ready",
              "paused"
            ]
          },
          "paused_reason": {
            "type": "string"
          },
          "upstream_url": {
            "type": "string"
          },
          "spec_url": {
            "type": "string"
          },
          "approved_version": {
            "type": "integer"
          },
          "bonus_points": {
            "type": "integer"
          },
          "bonus_expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "pending_diff": {
            "type": "object",
            "additionalProperties": true
          },
          "last_validation": {
            "$ref": "#/components/schemas/ValidationReport"
          },
          "host_slug": {
            "type": "string"
          },
          "mcp_host": {
            "type": "string",
            "examples": [
              "acme-mcp.deemwar.com"
            ]
          },
          "mcp_url": {
            "type": "string",
            "examples": [
              "https://acme-mcp.deemwar.com/mcp"
            ]
          },
          "operation_count": {
            "type": "integer"
          },
          "group_count": {
            "type": "integer"
          },
          "api_key": {
            "type": "string",
            "description": "Data-plane key (dmp_...). Only on create and rotate."
          }
        }
      },
      "ProjectConfig": {
        "type": "object",
        "additionalProperties": true,
        "description": "The tool configuration: operations, groups, roles, auth, sign-in methods, workflows, widget origins.",
        "properties": {
          "name": {
            "type": "string"
          },
          "purpose": {
            "type": "string"
          },
          "upstream_url": {
            "type": "string"
          },
          "operations": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "roles": {
            "$ref": "#/components/schemas/RoleMap"
          },
          "auth": {
            "type": "object",
            "additionalProperties": true
          },
          "workflows": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "RoleMap": {
        "type": "object",
        "properties": {
          "claim_path": {
            "type": "string",
            "examples": [
              "role",
              "realm_access.roles"
            ]
          },
          "default_role": {
            "type": "string",
            "description": "Used when the claim is missing; empty denies."
          },
          "roles": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Role name to allowed operation ids; \"*\" allows all."
          }
        }
      },
      "DiscoverRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "spec": {
            "type": "string",
            "description": "Raw OpenAPI/Swagger JSON or YAML."
          }
        }
      },
      "DiscoverResponse": {
        "type": "object",
        "properties": {
          "project": {
            "$ref": "#/components/schemas/Project"
          },
          "draft": {
            "$ref": "#/components/schemas/ProjectConfig"
          },
          "spec_url": {
            "type": "string"
          },
          "tried": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "diff": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "OpPatch": {
        "type": "object",
        "required": [
          "id"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "summary": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "group_id": {
            "type": "string"
          },
          "confirm_required": {
            "type": "boolean"
          },
          "read_only": {
            "type": "boolean"
          },
          "destructive": {
            "type": "boolean"
          }
        }
      },
      "GroupPatch": {
        "type": "object",
        "required": [
          "id"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean",
            "description": "Toggles every operation in the group."
          },
          "delete": {
            "type": "boolean",
            "description": "Only when empty."
          }
        }
      },
      "PatchDraftRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "purpose": {
            "type": "string"
          },
          "upstream_url": {
            "type": "string"
          },
          "operations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpPatch"
            }
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GroupPatch"
            }
          },
          "roles": {
            "$ref": "#/components/schemas/RoleMap"
          },
          "auth": {
            "type": "object",
            "additionalProperties": true
          },
          "workflows": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "hs256_secret": {
            "type": "string",
            "minLength": 16,
            "maxLength": 1024,
            "writeOnly": true
          },
          "sso_secrets": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "writeOnly": true
          },
          "docs_only": {
            "type": "boolean",
            "description": "A knowledge server: documents only (ask_docs), no API operations or upstream URL."
          }
        }
      },
      "ValidateRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "token": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string",
            "writeOnly": true
          },
          "login_endpoint": {
            "type": "string",
            "description": "Absolute, or relative to upstream_url."
          },
          "username_field": {
            "type": "string",
            "default": "username"
          },
          "password_field": {
            "type": "string",
            "default": "password"
          },
          "form": {
            "type": "boolean"
          }
        }
      },
      "LoginCheck": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pass",
              "fail",
              "skipped"
            ]
          },
          "detail": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "operations": {
            "type": "integer"
          }
        }
      },
      "ValidationReport": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "token",
              "jwt",
              "bearer",
              "cookie"
            ]
          },
          "capture": {
            "type": "object",
            "additionalProperties": true
          },
          "login": {
            "$ref": "#/components/schemas/LoginCheck"
          },
          "advice": {
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "group_id": {
                  "type": "string"
                },
                "group_name": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "pass",
                    "fail",
                    "skipped"
                  ]
                },
                "operation_id": {
                  "type": "string"
                },
                "http_status": {
                  "type": "integer"
                },
                "detail": {
                  "type": "string"
                },
                "latency_ms": {
                  "type": "integer"
                }
              }
            }
          },
          "checked_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Brand": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "logo_url": {
            "type": "string",
            "format": "uri"
          },
          "primary": {
            "type": "string"
          },
          "accent": {
            "type": "string"
          },
          "radius": {
            "type": "integer",
            "minimum": 0,
            "maximum": 24
          },
          "dark": {
            "type": "boolean"
          },
          "adjusted": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "readOnly": true
          }
        }
      },
      "SigninTestRequest": {
        "type": "object",
        "required": [
          "method"
        ],
        "additionalProperties": false,
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "callback",
              "capture",
              "token",
              "sso"
            ]
          },
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string",
            "writeOnly": true
          },
          "token": {
            "type": "string"
          }
        }
      },
      "AIView": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "off",
              "byok",
              "platform"
            ]
          },
          "provider": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "base_url": {
            "type": "string"
          },
          "key_last4": {
            "type": "string"
          },
          "has_key": {
            "type": "boolean"
          },
          "depleted": {
            "type": "boolean"
          },
          "updated_at": {
            "type": "string"
          },
          "platform_available": {
            "type": "boolean"
          },
          "platform_configured": {
            "type": "boolean"
          }
        }
      },
      "PutAIRequest": {
        "type": "object",
        "required": [
          "mode"
        ],
        "additionalProperties": false,
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "off",
              "byok",
              "platform"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "openrouter",
              "openai_compatible"
            ]
          },
          "model": {
            "type": "string"
          },
          "base_url": {
            "type": "string",
            "format": "uri"
          },
          "api_key": {
            "type": "string",
            "writeOnly": true
          }
        }
      },
      "Billing": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "ready",
              "paused"
            ]
          },
          "paused": {
            "type": "boolean"
          },
          "paused_reason": {
            "type": "string"
          },
          "balance": {
            "type": "integer"
          },
          "next_expiry": {
            "type": "string",
            "format": "date-time"
          },
          "expiring_amount": {
            "type": "integer"
          },
          "bonus": {
            "type": "object",
            "properties": {
              "points": {
                "type": "integer"
              },
              "expires_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "balance_unavailable": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "stub",
              "test",
              "live"
            ]
          },
          "packs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "points": {
                  "type": "integer"
                },
                "price_inr_paise": {
                  "type": "integer"
                },
                "price_usd_cents": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "UsageDay": {
        "type": "object",
        "properties": {
          "day": {
            "type": "string"
          },
          "tools": {
            "type": "integer"
          },
          "model": {
            "type": "integer"
          },
          "docs": {
            "type": "integer"
          },
          "hosting": {
            "type": "integer"
          }
        }
      }
    }
  }
}
