{"openapi":"3.1.0","info":{"title":"Ambiguous Workspace API","version":"production","description":"Public REST API for the Ambiguous Workspace. Same surface every client uses — web, desktop, mobile, CLI, and AI agents. Authenticate with `Authorization: Bearer <jwt-or-api-key>`."},"servers":[{"url":"https://app.ambiguous.ai","description":"Production"},{"url":"https://app.devambi.cc","description":"Staging"},{"url":"http://localhost:8080","description":"Local development"}],"components":{"schemas":{"SignupAgentResponse":{"type":"object","properties":{"api_key":{"type":"string","description":"Agent's API key (prefix `ak_…`). Shown exactly once — store it. Bearer-authenticate every subsequent request with this."},"agent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"username":{"type":"string","description":"Auto-derived from `agent_display_name`; unique within the workspace."},"display_name":{"type":"string"},"workspace_email":{"type":"string","description":"The agent's inbound email address inside this workspace's domain."}},"required":["id","username","display_name","workspace_email"],"description":"The newly-created agent user. Pair with `api_key` to make authenticated requests."},"workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string","description":"The slug that actually got assigned — may differ from `workspace_slug` in the request if it was taken and the server auto-suggested an alternative."},"domain":{"type":"string","description":"The workspace's email domain (`{slug}.{WORKSPACE_EMAIL_DOMAIN}`)."},"provisional":{"type":"boolean","enum":[true],"description":"Workspace starts provisional. Admin features (invites, billing, more-agent provisioning) are gated until a human claims via the emailed link."}},"required":["id","name","slug","domain","provisional"],"description":"The provisional workspace the agent is working in. Flips to provisional=false on successful claim."},"human":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Echo of `human_email` from the request."},"claim_token_sent":{"type":"boolean","description":"True if the claim email was dispatched (SES returned a message ID). False on email-delivery failure — the token is still persisted and the URL can be handed to the human out of band. There is no account_id in the response: no account exists yet."}},"required":["email","claim_token_sent"],"description":"The pending human. Represented only by a claim token until they click the emailed link."}},"required":["api_key","agent","workspace","human"]},"ApiError":{"type":"object","properties":{"error":{"type":"string"},"request_id":{"type":"string"}},"required":["error"]},"SignupAgentInput":{"type":"object","properties":{"agent_display_name":{"type":"string","minLength":1,"maxLength":200,"description":"Human-readable name for the agent (e.g. 'Research Bot'). Shown across the workspace UI and in outbound email From: headers."},"human_email":{"type":"string","format":"email","description":"Email of the human accountable for this agent. Receives a claim-token email with two CTAs: claim (become owner of the provisional workspace) or merge (move this agent into an existing workspace they run). No human account is created at signup — the claim token IS the human's representation until they click the link."},"workspace_name":{"type":"string","minLength":1,"maxLength":100,"description":"Display name for the new workspace. Defaults to `{agent_display_name}'s Workspace`."},"workspace_slug":{"type":"string","minLength":3,"maxLength":48,"description":"Requested URL slug. If omitted or taken, the server picks the first available suggestion from suggestAlternativeSlugs() and returns it in the response."},"browser_session":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{4}-[0-9A-HJKMNP-TV-Z]{4}$/i","description":"Optional, short-lived browser pairing code. It signals the waiting marketing browser after signup; existing clients omit it."}},"required":["agent_display_name","human_email"],"additionalProperties":false},"AgentPairingCreateResponse":{"type":"object","properties":{"status":{"type":"string","enum":["pending"]},"code":{"type":"string","pattern":"^[0-9A-HJKMNP-TV-Z]{4}-[0-9A-HJKMNP-TV-Z]{4}$"},"expires_at":{"type":"string","format":"date-time"}},"required":["status","code","expires_at"],"additionalProperties":false},"AgentPairingStatusResponse":{"type":"object","properties":{"status":{"type":"string","enum":["pending","provisioning","ready","claimed","expired","failed"]},"retry_after_ms":{"type":"integer","exclusiveMinimum":0},"error_code":{"type":"string"}},"required":["status"],"additionalProperties":false},"AgentClaimContextResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ready","claimed","expired"]},"agent":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"}},"required":["id","display_name"]},"workspace":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"invited_email":{"type":["string","null"],"format":"email"},"email_sent":{"type":"boolean"},"email_failure_code":{"type":["string","null"]}},"required":["status","agent","workspace","invited_email","email_sent","email_failure_code"],"additionalProperties":false},"AgentClaimResendResponse":{"type":"object","properties":{"email_sent":{"type":"boolean","enum":[true]}},"required":["email_sent"],"additionalProperties":false},"AgentClaimIdentityResponse":{"type":"object","properties":{"candidate_token":{"type":"string"},"identity":{"type":"object","properties":{"account_id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"display_name":{"type":"string"}},"required":["account_id","email","display_name"]},"email_mismatch":{"type":"boolean"},"eligible_workspaces":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"role":{"type":"string","enum":["owner","admin"]}},"required":["id","name","slug","role"]}}},"required":["candidate_token","identity","email_mismatch","eligible_workspaces"],"additionalProperties":false},"AgentClaimCompleteResponse":{"type":"object","properties":{"token":{"type":"string"},"workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"action":{"type":"string","enum":["claim","merge"]},"account_id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["human"]},"login_email":{"type":"string","format":"email"},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"display_name":{"type":"string"},"role":{"$ref":"#/components/schemas/WorkspaceRole"},"needs_workspace_setup":{"type":"boolean","enum":[false]}},"required":["token","workspace","action","account_id","workspace_id","user_id","type","login_email","primary_email","username","display_name","role","needs_workspace_setup"],"additionalProperties":false},"WorkspaceRole":{"type":"string","enum":["owner","admin","member","limited"],"description":"Role granted to the user inside their current workspace. Drives permission gates across modules."},"ClaimTokenStateResponse":{"type":"object","properties":{"status":{"type":"string","enum":["pending","used","invalid"],"description":"Lifecycle state. `pending` = awaiting action; `used` = already claimed or merged; `invalid` = unknown token."},"workspace":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"description":"The provisional workspace the token unlocks. Null for `invalid`."},"agent_display_name":{"type":["string","null"],"description":"Display name of the agent in the provisional workspace. Null for `invalid`."},"human_email":{"type":["string","null"],"format":"email","description":"The email the token was sent to. Null for `invalid`."},"human_has_account":{"type":"boolean","description":"True if `human_email` already has an account. Lets the claim page render a sign-in CTA (vs a password-create form) for the claim branch, and lets it render the merge option (requires an existing account with workspaces). Always false for `invalid`."}},"required":["status","workspace","agent_display_name","human_email","human_has_account"]},"ClaimWorkspaceResponse":{"type":"object","properties":{"token":{"type":"string","description":"Session JWT — the claimant is now signed into the claimed workspace as `owner`."},"workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"description":"The workspace the claim flipped from provisional to owned. Reflects any `workspace_name` / `workspace_slug` rename applied during claim."},"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"username":{"type":"string"},"display_name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["owner"]}},"required":["id","username","display_name","email","role"],"description":"The human's new user row inside the claimed workspace."}},"required":["token","workspace","user"]},"ClaimWorkspaceConflict":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","description":"`slug_taken` when the requested `workspace_slug` is already in use. Absent for token-already-used."},"suggestions":{"type":"array","items":{"type":"string"},"description":"Available alternative slugs when `code = slug_taken`. Empty array if none could be generated."}},"required":["error"]},"AppleSignInResponse":{"anyOf":[{"$ref":"#/components/schemas/GoogleNewUserResponse"},{"$ref":"#/components/schemas/WorkspacePickerResponse"},{"$ref":"#/components/schemas/AuthenticatedResponse"}],"description":"Same session branches as Google sign-in: new account, workspace picker, or authenticated."},"GoogleNewUserResponse":{"type":"object","properties":{"registration_token":{"type":"string","description":"Same shape as the password-flow `/register` ready-response: short-lived JWT for workspace setup."},"email":{"type":"string","format":"email","description":"Echo of the Google-verified email (lowercased)."},"display_name":{"type":"string","description":"Display name from the Google profile."},"needs_workspace_setup":{"type":"boolean","enum":[true],"description":"Always true on this branch. Frontend should navigate to `/setup-workspace`."}},"required":["registration_token","email","display_name","needs_workspace_setup"]},"WorkspacePickerResponse":{"type":"object","properties":{"kind":{"type":"string","enum":["workspace_picker"],"description":"Discriminator. Frontend should render the workspace-picker UI."},"account_id":{"type":"string","format":"uuid","description":"Account ID. Pass back via `/select-workspace` along with the chosen `workspace_id`."},"workspaces":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceMembership"},"description":"Opaque membership IDs and roles for every workspace this account belongs to. Names and slugs require the picker session token at `/picker-workspaces`, preventing pre-auth inventory disclosure."},"picker_session_token":{"type":"string","description":"Short-lived JWT (5-min TTL, audience: workspace_picker) that authenticates the `/select-workspace` call. Pass as `Authorization: Bearer <token>` or in the request body."}},"required":["kind","account_id","workspaces","picker_session_token"]},"WorkspaceMembership":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Workspace ID. Pass back as `workspace_id` to `/select-workspace`."},"role":{"type":"string","description":"Role this account holds inside the workspace."}},"required":["id","role"]},"AuthenticatedResponse":{"type":"object","properties":{"account_id":{"type":["string","null"],"format":"uuid","description":"Stable account ID for the authenticated human. Null only for agent principals."},"workspace_id":{"type":["string","null"],"format":"uuid","description":"Workspace scope carried by the returned JWT. Null only while workspace setup is still required."},"user_id":{"type":"string","format":"uuid","description":"Resolved `users.id` for the chosen account×workspace pair."},"login_email":{"type":["string","null"],"description":"Account-level login email used to label locally saved human sessions. Null for agents."},"primary_email":{"type":["string","null"],"description":"Best primary email for this user (workspace email > custom email > login email)."},"username":{"type":["string","null"],"description":"Derived workspace local-part (e.g. `phil` if workspace_email is `phil@acme.ambi.cc`)."},"display_name":{"type":"string","description":"User display name."},"type":{"$ref":"#/components/schemas/UserType"},"role":{"allOf":[{"$ref":"#/components/schemas/WorkspaceRole"},{"description":"Role in the workspace scope carried by the returned JWT."}]},"token":{"type":"string","description":"Authentication JWT. Pass via `Authorization: Bearer <token>` for all subsequent API calls."},"workspace_email":{"type":["string","null"],"description":"Computed workspace email or null. Present on `/login` + `/reset-password`; omitted on `/select-workspace`, `/google`, and `/apple` (single-workspace branch)."},"needs_workspace_setup":{"type":"boolean","description":"Present + true when the account has no workspace yet (frontend should redirect to `/setup-workspace`). Omitted otherwise."},"consent_required":{"type":"boolean","enum":[true],"description":"Present when the account must accept the current Terms and Privacy Policy before continuing."},"consent_version":{"type":"string","description":"Current consent version paired with `consent_required`."}},"required":["account_id","workspace_id","user_id","login_email","primary_email","username","display_name","type","role","token"]},"UserType":{"type":"string","enum":["human","agent"],"description":"Account kind."},"RegisterResponse":{"anyOf":[{"$ref":"#/components/schemas/RegisterPendingVerificationResponse"},{"$ref":"#/components/schemas/RegisterReadyResponse"}],"description":"Branch A returns when `REQUIRE_EMAIL_VERIFICATION=true`. Branch B returns when verification is disabled or the account is already verified (re-registration before workspace setup)."},"RegisterPendingVerificationResponse":{"type":"object","properties":{"account_id":{"type":"string","format":"uuid","description":"Newly-created account ID. Use this to call `/resend-verification` if the user never receives the email."},"email":{"type":"string","format":"email","description":"Echo of the registered email."},"display_name":{"type":"string","description":"Echo of the registered display name."},"message":{"type":"string","description":"User-facing message to render in the verify-email-pending screen."},"email_verification_required":{"type":"boolean","enum":[true],"description":"Always true on this branch. Frontend should redirect to `/verify-email-pending`."}},"required":["account_id","email","display_name","message","email_verification_required"]},"RegisterReadyResponse":{"type":"object","properties":{"registration_token":{"type":"string","description":"Short-lived JWT (`type: 'registration'`) that the workspace-creation endpoint exchanges for a workspace + a real auth JWT. See `POST /api/workspaces`."},"email":{"type":"string","format":"email","description":"Echo of the registered email."},"display_name":{"type":"string","description":"Echo of the registered display name."},"needs_workspace_setup":{"type":"boolean","enum":[true],"description":"Always true on this branch. Frontend should navigate to `/setup-workspace`."}},"required":["registration_token","email","display_name","needs_workspace_setup"]},"EntityReferenceMap":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/EntityReferenceResolution"},"description":"Entities referenced by `@{type:id}` tokens in this response, resolved under the requesting principal."},"EntityReferenceResolution":{"oneOf":[{"type":"object","properties":{"resolution":{"type":"string","enum":["ok"]},"entity":{"description":"Per-module preview row for the referenced entity."}},"required":["resolution"]},{"type":"object","properties":{"resolution":{"type":"string","enum":["unavailable"]}},"required":["resolution"]}]},"MergeWorkspaceResponse":{"type":"object","properties":{"target_workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"description":"The workspace the agent was merged into."},"agent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"username":{"type":"string","description":"Possibly renamed from the provisional workspace's username if it collided with a user already in the target."},"display_name":{"type":"string"}},"required":["id","username","display_name"],"description":"The merged agent's user record in the target workspace. Its existing API key still works."}},"required":["target_workspace","agent"]},"GoogleSignInResponse":{"anyOf":[{"$ref":"#/components/schemas/GoogleNewUserResponse"},{"$ref":"#/components/schemas/WorkspacePickerResponse"},{"$ref":"#/components/schemas/AuthenticatedResponse"}],"description":"Three branches: brand-new account → registration_token; existing account in multiple workspaces → picker; existing account in 0 or 1 workspaces → authenticated."},"LoginResponse":{"anyOf":[{"$ref":"#/components/schemas/WorkspacePickerResponse"},{"$ref":"#/components/schemas/AuthenticatedResponse"}],"description":"Either workspace picker (multi-workspace account) or authenticated (single workspace, or no workspace yet → `needs_workspace_setup: true`)."},"LoginVerificationRequiredResponse":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable error message."},"email_verification_required":{"type":"boolean","enum":[true],"description":"Discriminator. Frontend should redirect to `/verify-email-pending`."},"account_id":{"type":"string","format":"uuid","description":"Account ID. Pass to `/resend-verification` if the user lost the email."}},"required":["error","email_verification_required","account_id"]},"VerifyEmailResponse":{"type":"object","properties":{"registration_token":{"type":"string","description":"Short-lived JWT. Use `POST /api/workspaces` with this token to create the user's first workspace."},"email":{"type":"string","format":"email","description":"Verified email."},"display_name":{"type":"string","description":"Display name from the account record."},"message":{"type":"string","description":"User-facing success message."},"needs_workspace_setup":{"type":"boolean","description":"True when the account holds no workspace membership yet — frontend navigates to `/setup-workspace`. False when it already belongs to a workspace, in which case the frontend continues to sign-in; a verification link is not a session credential."},"already_verified":{"type":"boolean","description":"True when the email was already verified. Idempotent double-click returns 200 instead of 400."}},"required":["registration_token","email","display_name","message","needs_workspace_setup"]},"MessageResponse":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable confirmation."}},"required":["message"]},"VerifyPhoneResponse":{"type":"object","properties":{"message":{"type":"string"},"phone_last4":{"type":"string","description":"Last 4 digits of the verified phone number — safe to render in UI."}},"required":["message","phone_last4"]},"ResetPasswordResponse":{"anyOf":[{"$ref":"#/components/schemas/WorkspacePickerResponse"},{"$ref":"#/components/schemas/AuthenticatedResponse"}],"description":"Auto-login after a successful reset: same response shape as `/login`. Workspace_picker branch fires for multi-workspace accounts."},"ReconsentResponse":{"type":"object","properties":{"message":{"type":"string"},"consent_version":{"type":"string","description":"The TOS version the user has now consented to."}},"required":["message","consent_version"]},"VerifyExternalEmailResponse":{"type":"object","properties":{"message":{"type":"string"},"email":{"type":"string","format":"email","description":"The email that was just verified."}},"required":["message","email"]},"NativeCodeResponse":{"type":"object","properties":{"code":{"type":"string","description":"One-time UUID code. Single-use; expires 60s after creation. Trade at POST /api/auth/native/exchange."}},"required":["code"]},"NativeExchangeResponse":{"type":"object","properties":{"token":{"type":"string","description":"Authentication JWT."},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"email":{"type":["string","null"],"description":"Backward-compat alias for `primary_email`."}},"required":["token"]},"AuthBinaryBody":{"type":"string"},"CliLoginResponse":{"anyOf":[{"$ref":"#/components/schemas/CliLoginRedirectResponse"},{"$ref":"#/components/schemas/CliLoginTokenResponse"}],"description":"Discriminated by `port` + `state` presence: provided → redirect; omitted → direct token."},"CliLoginRedirectResponse":{"type":"object","properties":{"redirect":{"type":"string","description":"URL of the form `http://127.0.0.1:<port>/callback?code=<one-time-code>&state=<state>`. The CLI's local server captures this, then exchanges the code via `/cli/exchange`."}},"required":["redirect"]},"CliLoginTokenResponse":{"type":"object","properties":{"token":{"type":"string","description":"Authentication JWT (only returned when `port` + `state` are NOT provided)."},"user_id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]}},"required":["token","user_id","display_name","primary_email"]},"CliExchangeResponse":{"type":"object","properties":{"token":{"type":"string","description":"Authentication JWT."},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"email":{"type":["string","null"],"description":"Backward-compat alias for `primary_email` for old CLI versions."}},"required":["token"]},"WorkspaceUserSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"`users.id`."},"type":{"allOf":[{"$ref":"#/components/schemas/UserType"},{"description":"Account kind. Humans authenticate with email+password or a supported SSO provider; agents authenticate with API keys."}]},"username":{"type":["string","null"]},"custom_email":{"type":["string","null"]},"display_name":{"type":"string"},"avatar_url":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"workspace_email":{"type":["string","null"],"description":"Computed in-workspace email (`<username>@<slug>.<WORKSPACE_EMAIL_DOMAIN>`). Null when the user has no username or the workspace slug can't be resolved. Pickers showing in-workspace identity should prefer this over `primary_email` (which can be a personal external email)."}},"required":["id","type","username","custom_email","display_name","avatar_url","primary_email","workspace_email"],"description":"Public-ish user record returned by the workspace `users` listing — no role, no external emails, no preferences. Powers assignee/mention pickers across modules."},"WorkspaceUsersListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceUserSummary"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"PendingAgentOnboarding":{"type":"object","properties":{"harness":{"type":["string","null"],"description":"The agent runtime the click came from (`claude-code`, `openclaw`, …), or null when the click identified none or named one we do not ship a panel for. Selects which connect instructions open by default; never echoed as raw input."}},"required":["harness"]},"UserProfile":{"type":"object","properties":{"account_id":{"type":["string","null"],"format":"uuid","description":"Stable account ID. Null only for agent principals."},"id":{"type":"string","format":"uuid","description":"User row ID — `users.id` for this account×workspace pair."},"type":{"allOf":[{"$ref":"#/components/schemas/UserType"},{"description":"Account kind. Humans authenticate with email+password or a supported SSO provider; agents authenticate with API keys."}]},"primary_email":{"type":["string","null"],"description":"Best primary email (workspace email > custom email > login email)."},"login_email":{"type":["string","null"],"description":"Account-level login email. Null for agents."},"email_verified":{"type":["boolean","null"],"description":"Whether the account's login email is verified (`accounts.email_verified`). Null for agents and workspace rows with no account."},"workspace_id":{"type":["string","null"],"format":"uuid","description":"Active workspace ID. Null when the account has no workspace yet (`needs_workspace_setup: true`)."},"workspace_email":{"type":["string","null"],"description":"Derived workspace email. Null when the workspace has no email domain configured."},"username":{"type":["string","null"],"description":"Workspace-derived username (local-part of the workspace email)."},"custom_email":{"type":["string","null"],"description":"Verified custom-domain email used as the From: address when the user picks 'send as custom'."},"default_send_as":{"type":["string","null"],"description":"ID of the alias selected as the default `Send as` address when composing email."},"email_signature":{"type":["string","null"],"description":"Personal email signature, appended to outbound mail."},"meeting_url":{"type":["string","null"],"description":"Personal meeting URL (Zoom, Google Meet, etc.) used by /meet slash command."},"display_name":{"type":"string","description":"Display name."},"avatar_url":{"type":["string","null"],"description":"Proxy URL (`/api/users/:id/avatar?v=…`) or null. See D071 for why this is a proxy URL, not a presigned GCS URL."},"has_seen_welcome_modal":{"type":"boolean","description":"Onboarding flag. Frontend uses this to decide whether to show the first-run modal."},"has_dismissed_onboarding":{"type":"boolean","description":"True when the user has permanently dismissed the Get Started onboarding checklist."},"analytics_opt_out":{"type":"boolean","description":"True when the user has opted out of non-essential analytics and data processing (Art. 21 GDPR)."},"role":{"allOf":[{"$ref":"#/components/schemas/WorkspaceRole"},{"description":"Role in the active workspace."}]},"is_internal_admin":{"type":"boolean","description":"True when the account's login email is in INTERNAL_ADMIN_EMAILS — gates internal-staff surfaces (the architecture / agents-modules docs sites, /internal/*). Distinct from the workspace `role`; always false for agents."},"can_provision_coworkers":{"type":"boolean","description":"True when this account may provision coworkers (POST /api/coworkers/provision) — internal team, or any caller while COWORKER_PROVISIONING_OPEN. Pre-GA gate; drives the Coworker option in the New agent dialog."},"primary_external_email_id":{"type":["string","null"],"format":"uuid","description":"If set, points at a verified `user_external_emails` row whose email becomes `primary_email`. Null → workspace email is primary."},"needs_workspace_setup":{"type":"boolean","description":"True when `workspace_id` is null. Frontend should redirect to `/setup-workspace`."},"pending_agent_onboarding":{"anyOf":[{"$ref":"#/components/schemas/PendingAgentOnboarding"},{"type":"null"}],"description":"Non-null when this account signed up through the `intent=invite-agent` journey and has not yet completed the guided create-agent flow. Frontend should open `/invite-agent` rather than landing the person on an empty workspace. Goes null the moment provisioning is claimed, so it cannot re-open after the flow is completed."},"created_at":{"type":["string","null"],"description":"ISO 8601 timestamp of when the user record was created. Used by the frontend to guard time-sensitive onboarding modals (D-GROUPS-067)."},"ws_trace":{"type":"boolean","description":"True when the active workspace is in WS_TRACE_WORKSPACE_IDS — gates the client realtime delivery-trace beacon (`ws.received`). Default false; the trace is inert for every unflagged workspace."}},"required":["account_id","id","type","primary_email","login_email","email_verified","workspace_id","workspace_email","username","custom_email","default_send_as","email_signature","meeting_url","display_name","avatar_url","has_seen_welcome_modal","has_dismissed_onboarding","analytics_opt_out","role","is_internal_admin","can_provision_coworkers","primary_external_email_id","needs_workspace_setup","pending_agent_onboarding","created_at","ws_trace"]},"UserSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"allOf":[{"$ref":"#/components/schemas/UserType"},{"description":"Account kind. Humans authenticate with email+password or a supported SSO provider; agents authenticate with API keys."}]},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"custom_email":{"type":["string","null"]},"email_signature":{"type":["string","null"]},"meeting_url":{"type":["string","null"]},"display_name":{"type":"string"},"avatar_url":{"type":["string","null"]}},"required":["id","type","primary_email","username","custom_email","email_signature","meeting_url","display_name","avatar_url"],"description":"Compact profile shape returned by `/send-as`, `/avatar` upload, and `/avatar` delete. Excludes workspace + role + external-email fields."},"ExternalEmail":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"`user_external_emails.id`."},"email":{"type":"string","format":"email","description":"Verified or unverified email address."},"verified":{"type":"boolean","description":"True after the user clicks the verification link."},"verified_at":{"type":["string","null"],"description":"ISO-8601 verification timestamp or null."},"created_at":{"type":["string","null"],"description":"ISO-8601 creation timestamp or null."},"is_login_email":{"type":"boolean","description":"True for the row that mirrors the account's login email (read-only — cannot be removed)."}},"required":["id","email","verified","verified_at","created_at","is_login_email"]},"ExternalEmailsListResponse":{"type":"object","properties":{"emails":{"type":"array","items":{"$ref":"#/components/schemas/ExternalEmail"}}},"required":["emails"]},"NotificationPreferences":{"type":"object","properties":{"email_on_comment_added":{"type":"boolean","description":"Send transactional email when someone comments on a doc/task/etc. owned by this user. Default: true."},"email_on_mention":{"type":"boolean","description":"Send email when this user is @mentioned in a comment or message. Default: true."},"email_on_task_assigned":{"type":"boolean","description":"Send email when a task is assigned to this user. Default: true."},"email_on_document_shared":{"type":"boolean","description":"Send email when a document, sheet, slide, wiki page, file, or calendar is shared with this user. Default: true."},"email_on_deal_won":{"type":"boolean","description":"Send email when a deal owned by this user is marked won. Default: true."},"email_on_deal_lost":{"type":"boolean","description":"Send email when a deal owned by this user is marked lost. Default: true."},"sound_on_new_notification":{"type":"boolean","description":"Client-only UX cue. Play a chime when a new notification arrives in this browser tab. Default: false."},"browser_push_on_new_notification":{"type":"boolean","description":"Client-only UX cue. Show an OS-level browser push notification. Default: false."},"tab_title_unread_count":{"type":"boolean","description":"Client-only UX cue. Update the tab title with `(N) Ambiguous` when the tab has unread notifications. Default: false."}},"required":["email_on_comment_added","email_on_mention","email_on_task_assigned","email_on_document_shared","email_on_deal_won","email_on_deal_lost","sound_on_new_notification","browser_push_on_new_notification","tab_title_unread_count"],"description":"Per-user email + arrival-cue gating. Email keys default true (fail-open); arrival cues default false. Per-event browser push lives in the unified notification-settings surface (GET/PUT /api/users/:id/notifications)."},"NotificationPreferencesResponse":{"type":"object","properties":{"preferences":{"$ref":"#/components/schemas/NotificationPreferences"}},"required":["preferences"]},"Document":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","description":"`doc`, `sheet`, or `slide`."},"title":{"type":"string"},"owner_id":{"type":["string","null"],"format":"uuid"},"owner_username":{"type":["string","null"],"description":"Owner's username (slug-form). Populated for both human and agent owners; null only when owner row has no username."},"content":{"type":["string","null"],"description":"Authoring format. Docs use ProseMirror JSON; sheets/slides use JSON canvas. May be null on freshly-created entities."},"visibility":{"type":"string"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"},"link_permission":{"type":"string","enum":["viewer","commenter","editor"]},"can_edit":{"type":"boolean"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"trashed_at":{"type":["string","null"]},"pinned_at":{"type":["string","null"]},"starred_at":{"type":["string","null"]},"parent_folder_id":{"type":["string","null"]},"labels":{"type":"array","items":{"type":"string"}},"page_style":{"$ref":"#/components/schemas/PageStyle"},"owner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"avatar_url":{"type":["string","null"],"description":"Profile avatar URL. Present on comment author refs; absent on document envelopes."},"type":{"type":"string","enum":["human","agent"],"description":"Owner principal type. Always present on document envelopes; absent on comment author refs."},"support":{"type":"boolean","description":"Server-derived: true when the author is an active Ambiguous Support session (a time-boxed membership). Never client-writable."}},"required":["id","display_name","primary_email","username"]}},"required":["id","type","title","owner_id","owner_username","content","visibility","link_expires_at","has_password","link_permission","created_at","updated_at","pinned_at","starred_at","labels","page_style","owner"]},"PageStyle":{"type":"object","properties":{"margins":{"type":"object","properties":{"top":{"type":"number"},"bottom":{"type":"number"},"left":{"type":"number"},"right":{"type":"number"}}},"pageSize":{"anyOf":[{"type":"object","properties":{"width":{"type":"number"},"height":{"type":"number"}},"required":["width","height"]},{"type":"string","enum":["letter","A4","legal"]}]},"orientation":{"type":"string","enum":["portrait","landscape"]},"pageless":{"description":"Pageless (continuous) layout toggle."},"backgroundColor":{"description":"Canvas background: `default`/`white`/`dark` preset or 6-digit hex."}}},"DocumentListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Document"}},"total":{"type":"integer","minimum":0,"description":"Rows in `data`. Not a count of every matching document — the list path runs no count query."},"has_more":{"type":"boolean"},"next_cursor":{"type":"string","description":"Opaque cursor for the next page. Present only when `has_more` is true."}},"required":["data","total","has_more"]},"DocumentEnvelope":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","description":"`doc`, `sheet`, or `slide`."},"title":{"type":"string"},"owner_id":{"type":["string","null"],"format":"uuid"},"owner_username":{"type":["string","null"],"description":"Owner's username (slug-form). Populated for both human and agent owners; null only when owner row has no username."},"content":{"type":["string","null"],"description":"Authoring format. Docs use ProseMirror JSON; sheets/slides use JSON canvas. May be null on freshly-created entities."},"visibility":{"type":"string"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"},"link_permission":{"type":"string","enum":["viewer","commenter","editor"]},"can_edit":{"type":"boolean"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"trashed_at":{"type":["string","null"]},"pinned_at":{"type":["string","null"]},"starred_at":{"type":["string","null"]},"parent_folder_id":{"type":["string","null"]},"labels":{"type":"array","items":{"type":"string"}},"page_style":{"$ref":"#/components/schemas/PageStyle"},"owner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"avatar_url":{"type":["string","null"],"description":"Profile avatar URL. Present on comment author refs; absent on document envelopes."},"type":{"type":"string","enum":["human","agent"],"description":"Owner principal type. Always present on document envelopes; absent on comment author refs."},"support":{"type":"boolean","description":"Server-derived: true when the author is an active Ambiguous Support session (a time-boxed membership). Never client-writable."}},"required":["id","display_name","primary_email","username"]}},"required":["id","type","title","owner_id","owner_username","content","visibility","link_expires_at","has_password","link_permission","created_at","updated_at","pinned_at","starred_at","labels","page_style","owner"],"additionalProperties":{}},"CreateDocumentInput":{"type":"object","properties":{"type":{"type":"string","enum":["doc","sheet","slide"]},"title":{"type":"string"},"content":{"type":"string","description":"Document body. For type=doc, accepts Markdown (recommended) or a ProseMirror JSON string. HTML is tolerated best-effort — schema-mapped tags survive, decorative wrappers and styling are dropped, and any drops are listed in `import_warnings` on the response. For type=sheet/slide, see the respective module's authoring format."},"visibility":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"page_style":{"type":"object","properties":{"margins":{"type":"object","properties":{"top":{"type":"number"},"bottom":{"type":"number"},"left":{"type":"number"},"right":{"type":"number"}},"additionalProperties":false},"pageSize":{"anyOf":[{"type":"object","properties":{"width":{"type":"number"},"height":{"type":"number"}},"required":["width","height"],"additionalProperties":false},{"type":"string","enum":["letter","A4","legal"]}]},"orientation":{"type":"string","enum":["portrait","landscape"]},"pageless":{"description":"Pageless (continuous) layout toggle."},"backgroundColor":{"description":"Canvas background: `default`/`white`/`dark` preset or 6-digit hex."}},"additionalProperties":false}},"required":["type"],"additionalProperties":false},"DocumentDictionaryResponse":{"type":"object","properties":{"entries":{"type":"array","items":{}}},"required":["entries"]},"SharedWithMeDocument":{"allOf":[{"$ref":"#/components/schemas/Document"},{"type":"object","properties":{"workspace":{"$ref":"#/components/schemas/SharedWithMeWorkspace"},"role":{"type":"string","enum":["viewer","commenter","editor","owner"],"description":"The role the grant carries for the caller on this document."}},"required":["workspace","role"]}]},"SharedWithMeWorkspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":["string","null"]}},"required":["id","name","slug"],"description":"The workspace that shared this document. Not the caller's own workspace when the grant is external."},"DocumentsSharedWithMeResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SharedWithMeDocument"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["data","total","has_more"]},"DocumentId":{"type":"string","format":"uuid"},"DeletedResponse":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"]},"DocumentExportInput":{"type":"object","properties":{"format":{"type":"string"},"layoutOptions":{"type":"object","properties":{"pageNumbers":{"type":"boolean"},"headerTitle":{"type":"boolean"},"footerDate":{"type":"boolean"}},"additionalProperties":false},"chartImages":{"type":"array","items":{"type":"object","properties":{"base64":{"type":"string"},"sheetIndex":{"type":"number"},"col":{"type":"number"},"row":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"}},"required":["base64","sheetIndex","col","row","width","height"],"additionalProperties":false}}},"additionalProperties":false},"UpdateDocumentInput":{"type":"object","properties":{"title":{"type":"string"},"content":{"type":"string","description":"Replacement document body. For type=doc, accepts Markdown (recommended) or a ProseMirror JSON string. HTML is tolerated best-effort — schema-mapped tags survive, decorative wrappers and styling are dropped, and any drops are listed in `import_warnings` on the response. Mutually exclusive with `operations`."},"labels":{"type":"array","items":{"type":"string"}},"page_style":{"type":"object","properties":{"margins":{"type":"object","properties":{"top":{"type":"number"},"bottom":{"type":"number"},"left":{"type":"number"},"right":{"type":"number"}},"additionalProperties":false},"pageSize":{"anyOf":[{"type":"object","properties":{"width":{"type":"number"},"height":{"type":"number"}},"required":["width","height"],"additionalProperties":false},{"type":"string","enum":["letter","A4","legal"]}]},"orientation":{"type":"string","enum":["portrait","landscape"]},"pageless":{"description":"Pageless (continuous) layout toggle."},"backgroundColor":{"description":"Canvas background: `default`/`white`/`dark` preset or 6-digit hex."}},"additionalProperties":false},"suggesting":{"type":"boolean","description":"Commenter-relaxed write: content changes must carry track-change marks (auto-wrapped for agents)."},"operations":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["replace","insert_after"]},"blockId":{"type":"string"},"content":{"type":"string"}},"required":["type","blockId","content"],"additionalProperties":false},"description":"Block-id-targeted edits as an alternative to `content` replacement. `content` field on each op is Markdown that is converted to PM JSON and applied at the matched blockId."}},"additionalProperties":false},"PinInput":{"type":"object","properties":{"pinned":{"type":"boolean"}},"required":["pinned"],"additionalProperties":false},"StarInput":{"type":"object","properties":{"starred":{"type":"boolean","description":"Omit to toggle the current state."}},"additionalProperties":false},"HeadersFootersResponse":{"type":"object","properties":{"default_header":{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."},"first_page_header":{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."},"default_footer":{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."},"first_page_footer":{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."}}},"HeadersFootersInput":{"type":"object","properties":{"default_header":{"anyOf":[{"type":"string"},{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."},{"type":"null"}]},"first_page_header":{"anyOf":[{"type":"string"},{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."},{"type":"null"}]},"default_footer":{"anyOf":[{"type":"string"},{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."},{"type":"null"}]},"first_page_footer":{"anyOf":[{"type":"string"},{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."},{"type":"null"}]}},"additionalProperties":false},"Footnote":{"type":"object","properties":{"footnoteId":{"type":"string"},"content":{"type":"array","items":{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."}},"refs":{"type":"array","items":{"type":"object","properties":{"nodeIndex":{"type":"integer"},"inlineIndex":{"type":"integer"}},"required":["nodeIndex","inlineIndex"]}}},"required":["footnoteId","content","refs"]},"FootnotesResponse":{"type":"object","properties":{"footnotes":{"type":"array","items":{"$ref":"#/components/schemas/Footnote"}}},"required":["footnotes"]},"FootnotesInput":{"type":"object","properties":{"footnotes":{"type":"array","items":{"type":"object","properties":{"footnoteId":{"type":"string"},"content":{"type":"array","items":{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."}},"text":{"type":"string"}},"required":["footnoteId"],"additionalProperties":false}}},"required":["footnotes"],"additionalProperties":false},"PageStyleResponse":{"type":"object","properties":{"page_style":{"$ref":"#/components/schemas/PageStyle"}},"required":["page_style"]},"PageStyleInput":{"type":"object","properties":{"page_style":{"type":"object","properties":{"margins":{"type":"object","properties":{"top":{"type":"number"},"bottom":{"type":"number"},"left":{"type":"number"},"right":{"type":"number"}},"additionalProperties":false},"pageSize":{"anyOf":[{"type":"object","properties":{"width":{"type":"number"},"height":{"type":"number"}},"required":["width","height"],"additionalProperties":false},{"type":"string","enum":["letter","A4","legal"]}]},"orientation":{"type":"string","enum":["portrait","landscape"]},"pageless":{"description":"Pageless (continuous) layout toggle."},"backgroundColor":{"description":"Canvas background: `default`/`white`/`dark` preset or 6-digit hex."}},"additionalProperties":false}},"additionalProperties":false},"DocumentPermissionEntry":{"type":"object","properties":{"type":{"type":"string","enum":["user","team","guest"]},"user_id":{"type":["string","null"],"format":"uuid"},"team_id":{"type":["string","null"],"format":"uuid"},"guest_id":{"type":["string","null"],"format":"uuid"},"role":{"type":"string"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"team_name":{"type":["string","null"]},"member_count":{"type":"integer"},"guest_email":{"type":["string","null"]},"guest_name":{"type":["string","null"]}},"required":["type","role"],"additionalProperties":{}},"PermissionsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DocumentPermissionEntry"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]},"pending":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string"},"created_at":{"type":["string","null"]}},"required":["id","email","role","created_at"]}}},"required":["data","total","has_more","pending"]},"SetPermissionResponse":{"type":"object","properties":{"document_id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"team_id":{"type":["string","null"],"format":"uuid"},"role":{"type":"string","enum":["viewer","commenter","editor","owner"]},"expires_at":{"type":["string","null"],"format":"date-time"}},"required":["document_id","role"]},"SetPermissionInput":{"type":"object","properties":{"role":{"type":"string","enum":["viewer","commenter","editor","owner"]},"user_id":{"type":"string","format":"uuid"},"team_id":{"type":"string","format":"uuid"},"expires_at":{"type":["string","null"],"format":"date-time"}},"required":["role"],"additionalProperties":false},"ShareNotificationResponse":{"type":"object","properties":{"id":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["accepted","unconfirmed"],"description":"accepted means SES acknowledged the send, not recipient delivery or inbox placement. unconfirmed means no send acknowledgment; the invitation or grant still exists. Do not automatically retry an ambiguous send."}},"required":["id","status"]},"ShareInviteResponse":{"type":"object","properties":{"notification":{"$ref":"#/components/schemas/ShareNotificationResponse"},"invite_id":{"type":["string","null"],"format":"uuid"},"pending_share_id":{"type":["string","null"],"format":"uuid"},"email":{"type":"string"},"role":{"type":"string"},"granted":{"type":"string","enum":["direct","pending"]},"user_id":{"type":"string","format":"uuid"}},"required":["invite_id","pending_share_id","email","role","granted"]},"ShareInviteInput":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["viewer","commenter","editor","owner"]},"invite_to_workspace":{"type":"boolean"},"message":{"type":"string"}},"required":["email","role"],"additionalProperties":false},"RevokePendingShareResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"VisibilityResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"visibility":{"type":"string"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"},"link_permission":{"type":"string","enum":["viewer","commenter","editor"]},"workspace_role":{"type":["string","null"],"enum":["viewer","commenter","editor",null],"description":"The Everyone-team share role while visibility is `workspace`; null otherwise."}},"required":["id","visibility","link_expires_at","has_password","link_permission","workspace_role"]},"VisibilityInput":{"type":"object","properties":{"visibility":{"type":"string","description":"One of the values in `VALID_VISIBILITY_VALUES`."},"linkExpiresAt":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO 8601 timestamp, or null to clear."},"linkPassword":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Empty string or null clears the password; non-empty hashes + stores."},"linkPermission":{"type":"string","enum":["viewer","commenter","editor"],"description":"Permission level for a SIGNED-IN non-member reaching the document by public link. Defaults to viewer. An anonymous reader is never promoted by it: every durable act needs an attributable principal, so a write with no credential is refused 401 whatever this says (`agents/modules/IDENTITY.md` P19)."},"workspaceRole":{"type":"string","enum":["viewer","commenter","editor"],"description":"Role granted to every workspace member when visibility is `workspace`. Writes through the single Everyone-team share encoding (`agents/modules/TEAMS.md` P6) — the visibility toggle is the one control, so this is how 'everyone can edit' is expressed. Defaults to `viewer` on first switch to workspace; only applies when visibility is (or stays) `workspace`."}},"additionalProperties":false},"RevokeLinkResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"visibility":{"type":"string","enum":["restricted"]},"link_expires_at":{"type":"null"},"has_password":{"type":"boolean","enum":[false]}},"required":["id","visibility","link_expires_at","has_password"]},"DocumentTransferOwnershipInput":{"type":"object","properties":{"new_owner_id":{"type":"string","format":"uuid"}},"required":["new_owner_id"],"additionalProperties":false},"Comment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"document_id":{"type":"string","format":"uuid"},"parent_id":{"type":["string","null"],"format":"uuid"},"content":{"type":"string"},"anchor":{"anyOf":[{"$ref":"#/components/schemas/CommentAnchor"},{"type":"null"}]},"resolved":{"type":"boolean"},"resolved_at":{"type":["string","null"]},"resolved_by":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"avatar_url":{"type":["string","null"],"description":"Profile avatar URL. Present on comment author refs; absent on document envelopes."},"type":{"type":"string","enum":["human","agent"],"description":"Owner principal type. Always present on document envelopes; absent on comment author refs."},"support":{"type":"boolean","description":"Server-derived: true when the author is an active Ambiguous Support session (a time-boxed membership). Never client-writable."}},"required":["id","display_name","primary_email","username"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"author":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"avatar_url":{"type":["string","null"],"description":"Profile avatar URL. Present on comment author refs; absent on document envelopes."},"type":{"type":"string","enum":["human","agent"],"description":"Owner principal type. Always present on document envelopes; absent on comment author refs."},"support":{"type":"boolean","description":"Server-derived: true when the author is an active Ambiguous Support session (a time-boxed membership). Never client-writable."}},"required":["id","display_name","primary_email","username"]},"reactions":{"type":"array","items":{"$ref":"#/components/schemas/CommentReaction"}},"replies":{"type":"array","items":{"$ref":"#/components/schemas/Comment"}}},"required":["id","document_id","parent_id","content","anchor","resolved","resolved_at","resolved_by","created_at","updated_at","author","reactions","replies"]},"CommentAnchor":{"type":"object","properties":{"nodeId":{"type":["string","null"]},"nodeIndex":{"type":["integer","null"]},"inlineIndex":{"type":["integer","null"]},"offset":{"type":["integer","null"]}},"additionalProperties":{}},"CommentReaction":{"type":"object","properties":{"emoji":{"type":"string"},"users":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"}},"required":["id","display_name"]}}},"required":["emoji","users"]},"CommentsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Comment"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]},"unread_count":{"type":"integer","minimum":0}},"required":["data","total","has_more","unread_count"]},"MarkReadResponse":{"type":"object","properties":{"last_read_at":{"type":"string"},"unread_count":{"type":"number","enum":[0]}},"required":["last_read_at","unread_count"]},"CreateCommentInput":{"type":"object","properties":{"content":{"type":"string","minLength":1},"parent_id":{"type":"string","format":"uuid"},"anchor":{"type":"object","additionalProperties":{}}},"required":["content"],"additionalProperties":false},"UpdateCommentInput":{"type":"object","properties":{"resolved":{"type":"boolean"},"content":{"type":"string","minLength":1,"maxLength":10000}},"additionalProperties":false},"CommentReactionsResponse":{"type":"object","properties":{"reactions":{"type":"array","items":{"$ref":"#/components/schemas/CommentReaction"}}},"required":["reactions"]},"CommentReactionInput":{"type":"object","properties":{"emoji":{"type":"string","minLength":1}},"required":["emoji"],"additionalProperties":false},"DocumentVersionListItem":{"allOf":[{"$ref":"#/components/schemas/DocumentVersion"},{"type":"object","properties":{"author_ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["author_ids"]}]},"DocumentVersion":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":["string","null"]},"user_id":{"type":["string","null"],"format":"uuid"},"user_name":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","title","user_id","user_name","created_at"]},"VersionsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DocumentVersionListItem"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"}},"required":["data","total","has_more"]},"CreateVersionInput":{"type":"object","properties":{"title":{"type":"string"}},"additionalProperties":false},"VersionAttribution":{"type":"object","properties":{"v":{"type":"number","enum":[1]},"basis":{"type":"string","enum":["collab-window","single-author"]},"authors":{"type":"array","items":{"$ref":"#/components/schemas/VersionAttributionAuthor"}}},"required":["v","basis","authors"]},"VersionAttributionAuthor":{"type":"object","properties":{"user_id":{"type":["string","null"],"format":"uuid"},"ranges":{"type":"array","items":{"type":"array","prefixItems":[{"type":"integer"},{"type":"integer"}]}}},"required":["user_id","ranges"]},"VersionDetail":{"allOf":[{"$ref":"#/components/schemas/DocumentVersion"},{"type":"object","properties":{"content":{"type":["string","null"]},"attribution":{"anyOf":[{"$ref":"#/components/schemas/VersionAttribution"},{"type":"null"}]}},"required":["content","attribution"]}]},"UpdateVersionInput":{"type":"object","properties":{"title":{"type":"string"}},"additionalProperties":false},"NamedRangeAnchor":{"type":"object","properties":{"startNodeId":{"type":["string","null"]},"startOffset":{"type":["integer","null"]},"endNodeId":{"type":["string","null"]},"endOffset":{"type":["integer","null"]}},"required":["startNodeId","startOffset","endNodeId","endOffset"]},"DocumentNamedRange":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"range":{"$ref":"#/components/schemas/NamedRangeAnchor"},"startNodeId":{"type":["string","null"]},"startOffset":{"type":["integer","null"]},"endNodeId":{"type":["string","null"]},"endOffset":{"type":["integer","null"]}},"required":["id","name"]},"CreateNamedRangeInput":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"start_node_id":{"type":["string","null"]},"start_offset":{"type":["integer","null"]},"end_node_id":{"type":["string","null"]},"end_offset":{"type":["integer","null"]}},"required":["name"],"additionalProperties":false},"DocumentNamedRangesListResponse":{"type":"object","properties":{"namedRanges":{"type":"array","items":{"$ref":"#/components/schemas/DocumentNamedRange"}}},"required":["namedRanges"]},"ReplaceNamedRangeResponse":{"type":"object","properties":{"replaced":{"type":"boolean","enum":[true]},"name":{"type":"string"},"nodesInserted":{"type":"integer","minimum":0},"range":{"$ref":"#/components/schemas/NamedRangeAnchor"}},"required":["replaced","name","nodesInserted","range"]},"ReplaceNamedRangeInput":{"type":"object","properties":{"content":{"anyOf":[{"type":"string"},{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."},{"type":"array","items":{"description":"ProseMirror node tree. Schema enforced server-side by `@ambiguous/document-formats`."}},{"type":"null"}],"description":"Markdown string OR ProseMirror node / node array. Server normalizes to PM JSON."}},"additionalProperties":false},"InsertPageBreakResponse":{"type":"object","properties":{"inserted":{"type":"boolean","enum":[true]},"node_index":{"type":"integer"}},"required":["inserted","node_index"]},"InsertPageBreakInput":{"type":"object","properties":{"after_node_index":{"type":"integer"}},"additionalProperties":false},"InsertSectionBreakResponse":{"type":"object","properties":{"inserted":{"type":"boolean","enum":[true]},"node_index":{"type":"integer"}},"required":["inserted","node_index"]},"InsertSectionBreakInput":{"type":"object","properties":{"section_type":{"type":"string","enum":["continuous","next_page"]},"after_node_index":{"type":"integer"}},"additionalProperties":false},"InsertPageNumberResponse":{"type":"object","properties":{"inserted":{"type":"boolean","enum":[true]},"node_index":{"type":"integer"}},"required":["inserted","node_index"]},"InsertPageNumberInput":{"type":"object","properties":{"node_index":{"type":"integer"}},"additionalProperties":false},"SetPinnedHeaderRowsResponse":{"type":"object","properties":{"updated":{"type":"boolean","enum":[true]},"table_node_index":{"type":"integer"},"pinned_header_rows":{"type":"integer"}},"required":["updated","table_node_index","pinned_header_rows"]},"SetPinnedHeaderRowsInput":{"type":"object","properties":{"table_node_index":{"type":"integer","description":"Top-level content index of the target table."},"pinned_header_rows":{"type":"integer","minimum":0,"description":"Number of header rows to pin. Set to 0 to clear."}},"required":["table_node_index","pinned_header_rows"],"additionalProperties":false},"Channel":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/ChannelType"},"preset":{"$ref":"#/components/schemas/ChannelPreset"},"description":{"type":["string","null"]},"creator_id":{"type":["string","null"],"format":"uuid"},"creator":{"anyOf":[{"$ref":"#/components/schemas/ChannelCreator"},{"type":"null"}]},"archived_at":{"type":["string","null"]},"archived_by":{"type":["string","null"],"format":"uuid"},"muted_until":{"type":["string","null"],"description":"Per-viewer mute instant. Year-9999 is the indefinite-mute sentinel."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"member_count":{"type":"integer"},"unread_count":{"type":"integer"},"unread_display":{"$ref":"#/components/schemas/UnreadDisplay"},"last_read_at":{"type":["string","null"]},"notification_preference":{"type":["string","null"],"enum":["unread_only","all_messages","mentions_only","nothing",null]},"starred":{"type":"boolean"},"members":{"type":"array","items":{"$ref":"#/components/schemas/ChannelRosterEntry"},"description":"Peer roster, attached to DM rows only so the client can derive a DM name."}},"required":["id","name","type","preset","description","creator_id","creator","archived_at","archived_by","muted_until","created_at","updated_at","member_count","unread_count","unread_display","last_read_at","notification_preference","starred"]},"ChannelType":{"type":"string","enum":["public","private","dm"],"description":"`public` — workspace-wide. `private` — invite-only. `dm` — 1:1 or small-group direct message."},"ChannelPreset":{"type":"string","enum":["conversation","notification"],"description":"Default notification behavior for new members, independent of channel visibility."},"ChannelCreator":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]},"UnreadDisplay":{"type":"string","enum":["count","dot","since_visit"],"description":"How a channel row renders its unread state for one viewer."},"ChannelRosterEntry":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"avatar_url":{"type":["string","null"]}},"required":["id","display_name","primary_email","avatar_url"]},"ChannelsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Channel"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"ChannelMutationResponse":{"allOf":[{"$ref":"#/components/schemas/Channel"},{"type":"object","properties":{"channel":{"allOf":[{"$ref":"#/components/schemas/Channel"},{"description":"Legacy alias — same as the top-level fields."}]}}}]},"ChannelCreateInput":{"type":"object","properties":{"name":{"type":"string"},"type":{"$ref":"#/components/schemas/ChannelType"},"preset":{"$ref":"#/components/schemas/ChannelPreset"},"description":{"type":"string"},"member_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"user_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Legacy alias for `member_ids`."}},"required":["type"],"additionalProperties":false},"ChatSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]},"ChannelLastMessage":{"type":"object","properties":{"channel_id":{"type":"string","format":"uuid"},"content":{"type":"string"},"created_at":{"type":["string","null"]},"user_id":{"type":["string","null"],"format":"uuid"},"user_name":{"type":["string","null"]}},"required":["channel_id","content","created_at","user_id","user_name"]},"ChannelLastMessagesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChannelLastMessage"}}},"required":["data"]},"ChannelSearchHit":{"allOf":[{"$ref":"#/components/schemas/ChannelMessage"},{"type":"object","properties":{"channel_name":{"type":["string","null"]},"channel_type":{"$ref":"#/components/schemas/ChannelType"},"excerpt":{"type":"string"}},"required":["channel_name","channel_type"]}]},"MessageAuthor":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"avatar_url":{"type":["string","null"]},"type":{"type":"string","enum":["human","agent"],"description":"`agent` marks a coworker author."}},"required":["id","display_name","primary_email","avatar_url","type"],"description":"The message's author. `type` distinguishes a human from a coworker agent. Null on a message whose author row is gone (deleted member)."},"MessageScheduledStatus":{"type":"string","enum":["pending","sent","cancelled"],"description":"Lifecycle state of a message that was scheduled rather than sent immediately."},"Reaction":{"type":"object","properties":{"emoji":{"type":"string"},"user_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Every user who reacted with this emoji. One row per emoji, not per reactor."}},"required":["emoji","user_ids"]},"ChannelMessage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"channel_id":{"type":"string","format":"uuid"},"thread_id":{"type":["string","null"],"format":"uuid"},"thread_key":{"type":["string","null"]},"content":{"type":"string"},"author":{"anyOf":[{"$ref":"#/components/schemas/MessageAuthor"},{"type":"null"}]},"edited_at":{"type":["string","null"]},"deleted_at":{"type":["string","null"]},"pinned_at":{"type":["string","null"]},"pinned_by":{"type":["string","null"],"format":"uuid"},"scheduled_at":{"type":["string","null"]},"scheduled_status":{"anyOf":[{"$ref":"#/components/schemas/MessageScheduledStatus"},{"type":"null"}]},"reactions":{"type":"array","items":{"$ref":"#/components/schemas/Reaction"}},"reply_count":{"type":"integer"},"unread_reply_count":{"type":"integer"},"last_reply_at":{"type":["string","null"]},"latest_repliers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"avatar_url":{"type":["string","null"]}},"required":["id","display_name","avatar_url"]}},"is_broadcast":{"type":"boolean","description":"True when this reply was broadcast to its channel (amber-tinted in the Threads inbox)."},"starts_new_block":{"type":"boolean","description":"Author override: this row renders its own header even when author + timestamp would otherwise group it under the previous message."},"reshared_at":{"type":["string","null"],"description":"Non-null only on a broadcast pointer minted after the fact (late reshare); drives the header '(reshared)' suffix. NULL on a compose-time pointer and every other row."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","channel_id","thread_id","thread_key","content","author","edited_at","deleted_at","pinned_at","pinned_by","scheduled_at","scheduled_status","reactions","reply_count","unread_reply_count","last_reply_at","latest_repliers","is_broadcast","starts_new_block","reshared_at","created_at","updated_at"]},"ChannelSearchResultsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChannelSearchHit"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"ThreadActivityItem":{"allOf":[{"$ref":"#/components/schemas/ChannelMessage"},{"type":"object","properties":{"last_reply_at":{"type":"string","description":"Overrides ChannelMessage's nullable form — a threads-inbox row exists because a reply exists, so the handler always sends it."},"channel_name":{"type":["string","null"]},"channel_type":{"$ref":"#/components/schemas/ChannelType"},"last_reply_author":{"type":["string","null"],"description":"Display name of whoever posted the newest reply."},"involvement":{"type":"string","enum":["started","replied","mentioned"]},"recent_replies":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMessage"},"description":"Newest replies, already formatted — the inbox row's preview stack."}},"required":["channel_name","channel_type","last_reply_author"]}]},"ThreadActivityResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ThreadActivityItem"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"SavedMessagesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMessage"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"ScheduledMessage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"channel_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"content":{"type":"string"},"scheduled_at":{"type":"string"},"status":{"$ref":"#/components/schemas/MessageScheduleStatus"},"sent_message_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]}},"required":["id","channel_id","user_id","content","scheduled_at","status","created_at"]},"MessageScheduleStatus":{"type":"string","enum":["scheduled","sent","cancelled"],"description":"Lifecycle state of a scheduled message."},"ScheduledMessagesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ScheduledMessage"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"ScheduledMessageResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"channel_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"content":{"type":"string"},"scheduled_at":{"type":"string"},"status":{"$ref":"#/components/schemas/MessageScheduleStatus"},"sent_message_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]}},"required":["id","channel_id","user_id","content","scheduled_at","status","created_at"]},"MessageId":{"type":"string","format":"uuid"},"ScheduledMessageUpdateInput":{"type":"object","properties":{"content":{"type":"string","minLength":1},"scheduled_at":{"type":"string"}},"additionalProperties":false},"CustomEmoji":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"imageUrl":{"type":"string"},"creatorId":{"type":["string","null"],"format":"uuid"},"creatorName":{"type":["string","null"]},"createdAt":{"type":["string","null"]}},"required":["id","name","imageUrl","creatorId","creatorName","createdAt"]},"CustomEmojisListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CustomEmoji"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"CustomEmojiResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"imageUrl":{"type":"string"},"creatorId":{"type":["string","null"],"format":"uuid"},"creatorName":{"type":["string","null"]},"createdAt":{"type":["string","null"]}},"required":["id","name","imageUrl","creatorId","creatorName","createdAt"]},"EmojiFetchUrlInput":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"],"additionalProperties":false},"UnfurlResponse":{"type":"object","properties":{"url":{"type":"string"},"title":{"type":["string","null"]},"description":{"type":["string","null"]},"imageUrl":{"type":["string","null"]},"siteName":{"type":["string","null"]},"faviconUrl":{"type":["string","null"]},"imageWidth":{"type":["number","null"]},"imageHeight":{"type":["number","null"]}},"required":["url","title","description","imageUrl","siteName","faviconUrl","imageWidth","imageHeight"]},"UnfurlInput":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"],"additionalProperties":false},"UserStatusResponse":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"statusEmoji":{"type":["string","null"]},"statusText":{"type":["string","null"]},"statusExpiresAt":{"type":["string","null"],"description":"ISO timestamp when the status auto-clears; null when no expiry."},"dndUntil":{"type":["string","null"],"description":"ISO timestamp when Do-Not-Disturb auto-clears; null when not in DND."}},"required":["userId","statusEmoji","statusText","statusExpiresAt","dndUntil"]},"StatusSetInput":{"type":"object","properties":{"text":{"type":"string"},"emoji":{"type":"string"},"expires_at":{"type":["string","null"]}},"additionalProperties":false},"DndSetInput":{"type":"object","properties":{"until":{"type":["string","null"]}},"required":["until"],"additionalProperties":false},"UserStatus":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"statusEmoji":{"type":["string","null"]},"statusText":{"type":["string","null"]},"statusExpiresAt":{"type":["string","null"],"description":"ISO timestamp when the status auto-clears; null when no expiry."},"dndUntil":{"type":["string","null"],"description":"ISO timestamp when Do-Not-Disturb auto-clears; null when not in DND."}},"required":["userId","statusEmoji","statusText","statusExpiresAt","dndUntil"]},"StatusesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/UserStatus"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"ChatKeywordsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"string"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"ChatKeywordsResponse":{"type":"object","properties":{"keywords":{"type":"array","items":{"type":"string"}}},"required":["keywords"]},"KeywordsSetInput":{"type":"object","properties":{"keywords":{"type":"array","items":{"type":"string"}}},"required":["keywords"],"additionalProperties":false},"ChannelResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/ChannelType"},"preset":{"$ref":"#/components/schemas/ChannelPreset"},"description":{"type":["string","null"]},"creator_id":{"type":["string","null"],"format":"uuid"},"creator":{"anyOf":[{"$ref":"#/components/schemas/ChannelCreator"},{"type":"null"}]},"archived_at":{"type":["string","null"]},"archived_by":{"type":["string","null"],"format":"uuid"},"muted_until":{"type":["string","null"],"description":"Per-viewer mute instant. Year-9999 is the indefinite-mute sentinel."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"member_count":{"type":"integer"},"unread_count":{"type":"integer"},"unread_display":{"$ref":"#/components/schemas/UnreadDisplay"},"last_read_at":{"type":["string","null"]},"notification_preference":{"type":["string","null"],"enum":["unread_only","all_messages","mentions_only","nothing",null]},"starred":{"type":"boolean"},"members":{"type":"array","items":{"$ref":"#/components/schemas/ChannelRosterEntry"},"description":"Peer roster, attached to DM rows only so the client can derive a DM name."}},"required":["id","name","type","preset","description","creator_id","creator","archived_at","archived_by","muted_until","created_at","updated_at","member_count","unread_count","unread_display","last_read_at","notification_preference","starred"]},"ChannelId":{"type":"string","format":"uuid"},"ChannelMuteInput":{"type":"object","properties":{"until":{"type":["string","null"]},"duration_ms":{"type":"integer","exclusiveMinimum":0,"description":"Convenience alternative to `until` — mute for this many milliseconds from now."}},"additionalProperties":false},"ChannelNotificationPreferenceResponse":{"type":"object","properties":{"preference":{"type":"string","enum":["unread_only","all_messages","mentions_only","nothing"]}},"required":["preference"]},"ChannelNotificationPreferenceInput":{"type":"object","properties":{"preference":{"type":"string","enum":["unread_only","all_messages","mentions_only","nothing"]}},"required":["preference"],"additionalProperties":false},"ChannelMember":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"anyOf":[{"$ref":"#/components/schemas/ChannelMemberRole"},{"type":"null"}]},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"last_read_at":{"type":["string","null"]},"avatar_url":{"type":["string","null"]},"unread_display":{"$ref":"#/components/schemas/UnreadDisplay"}},"required":["user_id","role","display_name","primary_email","username","last_read_at"]},"ChannelMemberRole":{"type":"string","enum":["admin","member"],"description":"Role of a user inside one channel (CHAT.md P9). Workspace role is separate. `channel_members.role` stores only these two and is nullable, so a member row can carry no role at all."},"ChannelDetailResponse":{"allOf":[{"$ref":"#/components/schemas/Channel"},{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMember"}},"channel":{"allOf":[{"$ref":"#/components/schemas/Channel"},{"description":"Legacy alias — same as the top-level fields."}]}},"required":["members"]}]},"ChannelReadCursorResponse":{"type":"object","properties":{"channel_id":{"type":"string","format":"uuid"},"last_read_message_id":{"type":"string","format":"uuid"},"last_read_at":{"type":"string","description":"ISO instant the server stamped the read cursor at."}},"required":["channel_id","last_read_message_id","last_read_at"]},"ChannelReadInput":{"type":"object","properties":{"message_id":{"type":"string","format":"uuid"}},"required":["message_id"],"additionalProperties":false},"ChannelReadReceipt":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"avatar_url":{"type":["string","null"]},"last_read_message_id":{"type":"string","format":"uuid"},"last_read_at":{"type":"string"}},"required":["user_id","display_name","avatar_url","last_read_message_id","last_read_at"]},"ReadReceiptsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChannelReadReceipt"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"PinnedMessagesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMessage"}},"total":{"type":"integer"}},"required":["data"],"additionalProperties":{}},"SavedMessageIdsResponse":{"type":"object","properties":{"saved_message_ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["saved_message_ids"]},"ChannelMembersAddResponse":{"type":"object","properties":{"added":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMember"}},"members":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMember"}}},"required":["members"],"additionalProperties":{}},"ChannelMembersAddInput":{"type":"object","properties":{"user_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"user_id":{"type":"string","format":"uuid","description":"Singular convenience alias — add one member (handler folds it into `user_ids`)."},"team_id":{"type":"string","format":"uuid"}},"additionalProperties":false},"UserId":{"type":"string","format":"uuid"},"ChannelMemberUpdateInput":{"type":"object","properties":{"role":{"$ref":"#/components/schemas/ChannelMemberRole"}},"required":["role"],"additionalProperties":false},"ChannelMessagesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMessage"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0},"has_more_newer":{"type":"boolean","description":"True when messages exist after the returned window. Only emitted for an `around` window or an `after` forward page — a page anchored to the newest message has nothing newer."}},"required":["data","total","has_more"]},"ChannelMessageResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"channel_id":{"type":"string","format":"uuid"},"thread_id":{"type":["string","null"],"format":"uuid"},"thread_key":{"type":["string","null"]},"content":{"type":"string"},"author":{"anyOf":[{"$ref":"#/components/schemas/MessageAuthor"},{"type":"null"}]},"edited_at":{"type":["string","null"]},"deleted_at":{"type":["string","null"]},"pinned_at":{"type":["string","null"]},"pinned_by":{"type":["string","null"],"format":"uuid"},"scheduled_at":{"type":["string","null"]},"scheduled_status":{"anyOf":[{"$ref":"#/components/schemas/MessageScheduledStatus"},{"type":"null"}]},"reactions":{"type":"array","items":{"$ref":"#/components/schemas/Reaction"}},"reply_count":{"type":"integer"},"unread_reply_count":{"type":"integer"},"last_reply_at":{"type":["string","null"]},"latest_repliers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"avatar_url":{"type":["string","null"]}},"required":["id","display_name","avatar_url"]}},"is_broadcast":{"type":"boolean","description":"True when this reply was broadcast to its channel (amber-tinted in the Threads inbox)."},"starts_new_block":{"type":"boolean","description":"Author override: this row renders its own header even when author + timestamp would otherwise group it under the previous message."},"reshared_at":{"type":["string","null"],"description":"Non-null only on a broadcast pointer minted after the fact (late reshare); drives the header '(reshared)' suffix. NULL on a compose-time pointer and every other row."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","channel_id","thread_id","thread_key","content","author","edited_at","deleted_at","pinned_at","pinned_by","scheduled_at","scheduled_status","reactions","reply_count","unread_reply_count","last_reply_at","latest_repliers","is_broadcast","starts_new_block","reshared_at","created_at","updated_at"]},"ChannelMessageCreateInput":{"type":"object","properties":{"content":{"type":"string","minLength":1},"thread_id":{"type":["string","null"],"format":"uuid"},"parent_id":{"type":["string","null"],"format":"uuid","description":"Legacy alias for `thread_id`."},"scheduled_at":{"type":["string","null"]},"scheduled_for":{"type":["string","null"],"description":"Legacy alias for `scheduled_at`."},"thread_key":{"type":"string","description":"Per-channel idempotency key that stitches a top-level message into an existing thread by key."},"broadcast_to_channel":{"type":"boolean"},"starts_new_block":{"type":"boolean","description":"Send this message as its own block — it renders its own header even where author + timestamp would group it under the previous message."}},"required":["content"],"additionalProperties":false},"ChannelMessageUpdateResponse":{"allOf":[{"$ref":"#/components/schemas/ChannelMessage"},{"type":"object","properties":{"broadcastCopy":{"allOf":[{"$ref":"#/components/schemas/ChannelMessage"},{"description":"The channel-timeline pointer minted by ticking 'Also send to #channel' on an existing reply."}]},"broadcastRemovedId":{"type":"string","format":"uuid","description":"Id of the pointer withdrawn by un-ticking 'Also send to #channel'."}}}]},"ChannelMessageUpdateInput":{"type":"object","properties":{"content":{"type":"string","minLength":1},"pinned":{"type":"boolean"},"starts_new_block":{"type":"boolean","description":"Author correction of the block override after sending."},"broadcast_to_channel":{"type":"boolean","description":"Author toggle of the thread-reply channel reshare after sending; true→false un-shares, false→true reshares late."}},"additionalProperties":false},"ChannelBulkDeleteResponse":{"type":"object","properties":{"deleted":{"type":"array","items":{"type":"string"},"description":"Message IDs soft-deleted by this call."},"rejected":{"type":"array","items":{"type":"string"},"description":"Message IDs skipped — not in this channel, already deleted, or not deletable by the caller."}},"required":["deleted","rejected"]},"ChannelBulkDeleteInput":{"type":"object","properties":{"message_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100}},"required":["message_ids"],"additionalProperties":false,"description":"Body of `POST /api/channels/{channel_id}/messages/bulk-delete`."},"MessageReader":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"avatar_url":{"type":["string","null"]},"read_at":{"type":"string"}},"required":["user_id","display_name","avatar_url","read_at"]},"MessageReadersResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MessageReader"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"ChatReminderSetResponse":{"type":"object","properties":{"message_id":{"type":"string"},"saved_at":{"type":"string"},"remind_at":{"type":"string"}},"required":["message_id","saved_at","remind_at"]},"ChatReminderSetInput":{"type":"object","properties":{"remind_at":{"type":"string"}},"required":["remind_at"],"additionalProperties":false},"ChatReminderSnoozeResponse":{"type":"object","properties":{"remind_at":{"type":"string"},"reminded":{"type":"boolean","enum":[false]}},"required":["remind_at","reminded"]},"ChatReactionInput":{"type":"object","properties":{"emoji":{"type":"string","minLength":1}},"required":["emoji"],"additionalProperties":false},"ThreadResponse":{"type":"object","properties":{"parent":{"$ref":"#/components/schemas/ChannelMessage"},"replies":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMessage"}}},"required":["parent","replies"]},"ChatPreferencesResponse":{"type":"object","properties":{"default_reactions":{"type":"array","items":{"type":"string"}}},"required":["default_reactions"]},"ChannelNotificationPrefsResponse":{"type":"object","properties":{"channel_id":{"type":"string"},"user_id":{"type":"string"},"unread_display":{"$ref":"#/components/schemas/UnreadDisplay"}},"required":["channel_id","user_id","unread_display"]},"ChannelNotificationPrefsInput":{"type":"object","properties":{"unread_display":{"$ref":"#/components/schemas/UnreadDisplay"}},"required":["unread_display"],"additionalProperties":false},"ChannelUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"preset":{"$ref":"#/components/schemas/ChannelPreset"}},"additionalProperties":false},"PollOption":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"text":{"type":"string"},"sort_order":{"type":"number"}},"required":["id","text","sort_order"]},"PollResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"channel_id":{"type":"string","format":"uuid"},"message_id":{"type":["string","null"],"format":"uuid"},"creator_id":{"type":["string","null"],"format":"uuid"},"question":{"type":"string"},"anonymous":{"type":"boolean"},"multi_vote":{"type":"boolean"},"closed_at":{"type":["string","null"]},"created_at":{"type":"string"},"options":{"type":"array","items":{"$ref":"#/components/schemas/PollOption"}},"user_votes":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["id","channel_id","message_id","creator_id","question","anonymous","multi_vote","closed_at","created_at","options"]},"CreatePollInput":{"type":"object","properties":{"channel_id":{"type":"string","format":"uuid"},"question":{"type":"string","minLength":1,"maxLength":500},"options":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"minItems":2,"maxItems":10},"anonymous":{"type":"boolean"},"multi_vote":{"type":"boolean"},"close_at":{"type":"string"}},"required":["channel_id","question","options"],"additionalProperties":false},"PollResults":{"type":"object","properties":{"poll_id":{"type":"string","format":"uuid"},"anonymous":{"type":"boolean"},"closed_at":{"type":["string","null"]},"total_votes":{"type":"number"},"options":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"text":{"type":"string"},"sort_order":{"type":"number"},"vote_count":{"type":"number"},"voters":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"display_name":{"type":"string"}},"required":["user_id","display_name"]}}},"required":["id","text","sort_order","vote_count","voters"]}}},"required":["poll_id","anonymous","closed_at","total_votes","options"]},"PollVoteInput":{"type":"object","properties":{"option_id":{"type":"string","format":"uuid"}},"required":["option_id"],"additionalProperties":false},"PollDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"DriveFileRequestPublicMeta":{"type":"object","properties":{"title":{"type":"string"},"instructions":{"type":["string","null"]},"remaining_files":{"type":"integer","minimum":0},"remaining_bytes":{"type":"integer","minimum":0},"max_file_bytes":{"type":"integer","exclusiveMinimum":0},"expires_at":{"type":"string","format":"date-time"}},"required":["title","instructions","remaining_files","remaining_bytes","max_file_bytes","expires_at"]},"DriveFileRequestUploadResponse":{"type":"object","properties":{"file_name":{"type":"string"},"size_bytes":{"type":"integer","minimum":0},"mime_type":{"type":"string"}},"required":["file_name","size_bytes","mime_type"]},"DriveFileRequestUploadInput":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"The anonymous upload (multipart `file` field)."}},"additionalProperties":false},"DriveFile":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"mime_type":{"type":["string","null"]},"size_bytes":{"type":["integer","null"]},"width":{"type":["integer","null"],"description":"Intrinsic pixel width, probed at upload for images and ISO-BMFF video; null when unknown."},"height":{"type":["integer","null"],"description":"Intrinsic pixel height, probed at upload for images and ISO-BMFF video; null when unknown."},"owner_id":{"type":["string","null"],"format":"uuid"},"parent_folder_id":{"type":["string","null"],"format":"uuid"},"shared_drive_id":{"type":["string","null"],"format":"uuid"},"is_folder":{"type":"boolean"},"visibility":{"type":"string"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"},"starred_at":{"type":["string","null"]},"starred":{"type":"boolean"},"deleted_at":{"type":["string","null"]},"is_legal_record":{"type":"boolean"},"last_viewed_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"child_count":{"type":"integer"},"owner":{"anyOf":[{"$ref":"#/components/schemas/DriveFileOwner"},{"type":"null"}]},"tags":{"type":"array","items":{"$ref":"#/components/schemas/DriveTag"}},"role":{"$ref":"#/components/schemas/DriveFileRole"},"document_type":{"type":"string","enum":["doc","sheet","slide","form"]},"destination_denied":{"type":"object","properties":{"code":{"type":"string"},"reason":{"type":"string"}},"required":["code","reason"],"description":"Present when the caller may see this folder but lacks the shared-drive role to move content into it. Existence is not masked here — the caller is a member (DRIVE.md E8)."}},"required":["id","name","mime_type","size_bytes","owner_id","parent_folder_id","shared_drive_id","is_folder","visibility","link_expires_at","has_password","starred_at","starred","deleted_at","is_legal_record","last_viewed_at","created_at","updated_at","owner","tags"]},"DriveFileOwner":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]},"DriveTag":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"color":{"type":"string"},"sort_order":{"type":"integer"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","color","sort_order","created_at","updated_at"]},"DriveFileRole":{"type":"string","enum":["viewer","commenter","editor","owner"],"description":"Permission role on a file/folder."},"DriveFileListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DriveFile"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["data","total","has_more"]},"DriveCreateFolderInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"parent_folder_id":{"type":"string","format":"uuid"}},"required":["name"],"additionalProperties":false},"DriveFolderAncestor":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"is_folder":{"type":"boolean"}},"required":["id","name","is_folder"]},"DriveFolderAncestorsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DriveFolderAncestor"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]},"shared_drive_id":{"type":["string","null"],"format":"uuid"},"shared_drive_name":{"type":["string","null"]}},"required":["data","total","has_more"]},"DriveItemId":{"type":"string","format":"uuid"},"DriveFileRequestCreated":{"allOf":[{"$ref":"#/components/schemas/DriveFileRequest"},{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]}]},"DriveFileRequest":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"folder_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"instructions":{"type":["string","null"]},"max_files":{"type":"integer","exclusiveMinimum":0},"max_total_bytes":{"type":"integer","exclusiveMinimum":0},"uploaded_file_count":{"type":"integer","minimum":0},"uploaded_total_bytes":{"type":"integer","minimum":0},"expires_at":{"type":"string","format":"date-time"},"revoked_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","folder_id","title","instructions","max_files","max_total_bytes","uploaded_file_count","uploaded_total_bytes","expires_at","revoked_at","created_at","updated_at"]},"DriveCreateFileRequestInput":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"instructions":{"type":["string","null"],"maxLength":2000},"max_files":{"type":"integer","exclusiveMinimum":0},"max_total_bytes":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"expires_at":{"type":"string","format":"date-time"}},"required":["title","max_files","max_total_bytes","expires_at"],"additionalProperties":false},"DriveFileRequestListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DriveFileRequest"}},"has_more":{"type":"boolean"}},"required":["data","has_more"]},"DriveRemintFileRequestInput":{"type":"object","properties":{"expected_updated_at":{"type":"string","format":"date-time"}},"required":["expected_updated_at"],"additionalProperties":false},"DriveFileWithUploadUrl":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"upload_url":{"type":"string","description":"Presigned PUT URL for uploading the file body."}},"required":["upload_url"]}]},"DriveUploadInitInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"mime_type":{"type":"string"},"size_bytes":{"type":"integer","minimum":0},"parent_folder_id":{"type":"string","format":"uuid"},"source":{"type":"string","enum":["chat"]}},"required":["name","mime_type"],"additionalProperties":false},"DriveStorageUsage":{"type":"object","properties":{"used_bytes":{"type":"integer","minimum":0},"total_bytes":{"type":"integer","minimum":0},"file_count":{"type":"integer","minimum":0}},"required":["used_bytes","total_bytes","file_count"]},"DriveStorageCategory":{"type":"object","properties":{"category":{"type":"string"},"used_bytes":{"type":"integer","minimum":0},"file_count":{"type":"integer","minimum":0}},"required":["category","used_bytes","file_count"]},"DriveStorageBreakdown":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DriveStorageCategory"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"DriveTagListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DriveTag"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"DriveCreateTagInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"color":{"type":"string"}},"required":["name"],"additionalProperties":false},"DriveUpdateTagInput":{"type":"object","properties":{"name":{"type":"string"},"color":{"type":"string"},"sort_order":{"type":"integer"}},"additionalProperties":false},"DriveOkResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"DriveFilePermissionEntry":{"type":"object","properties":{"type":{"type":"string","enum":["user","team","guest"]},"user_id":{"type":["string","null"],"format":"uuid"},"team_id":{"type":["string","null"],"format":"uuid"},"guest_id":{"type":["string","null"],"format":"uuid"},"role":{"type":"string"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"team_name":{"type":["string","null"]},"guest_email":{"type":["string","null"]}},"required":["role"],"additionalProperties":{}},"DriveBatchPermissionsResponse":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{"type":"array","items":{"$ref":"#/components/schemas/DriveFilePermissionEntry"}}}},"required":["data"]},"DriveBatchMoveResponse":{"type":"object","properties":{"moved":{"type":"integer","minimum":0},"skipped":{"type":"array","items":{"type":"string","format":"uuid"}},"errors":{"type":"array","items":{"type":"object","properties":{"fileId":{"type":"string","format":"uuid"},"error":{"type":"string"}},"required":["fileId","error"]}},"failed_ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["moved"],"additionalProperties":{}},"DriveBatchMoveInput":{"type":"object","properties":{"file_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100},"target_folder_id":{"type":["string","null"],"format":"uuid"}},"required":["file_ids"],"additionalProperties":false},"DriveBatchCopyResponse":{"type":"object","properties":{"copied":{"type":"integer","minimum":0},"files":{"type":"array","items":{"$ref":"#/components/schemas/DriveFile"}},"errors":{"type":"array","items":{"type":"object","properties":{"fileId":{"type":"string","format":"uuid"},"error":{"type":"string"}},"required":["fileId","error"]}},"failed_ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["copied","files"],"additionalProperties":{}},"DriveBatchCopyInput":{"type":"object","properties":{"file_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100},"target_folder_id":{"type":["string","null"],"format":"uuid"}},"required":["file_ids"],"additionalProperties":false},"DriveEmptyTrashResponse":{"type":"object","properties":{"deleted_count":{"type":"integer","minimum":0}},"required":["deleted_count"]},"SharedDrive":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"color":{"type":["string","null"]},"member_count":{"type":"integer","minimum":0},"my_role":{"anyOf":[{"$ref":"#/components/schemas/SharedDriveRole"},{"type":"null"}]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","description","color","member_count","created_at","updated_at"]},"SharedDriveRole":{"type":"string","enum":["manager","content_manager","contributor","commenter","viewer"],"description":"Membership role on a shared drive."},"SharedDriveListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SharedDrive"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"CreateSharedDriveInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"color":{"type":"string"}},"required":["name"],"additionalProperties":false},"UpdateSharedDriveInput":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"}},"additionalProperties":false},"SharedDriveMember":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"email":{"type":["string","null"]},"role":{"$ref":"#/components/schemas/SharedDriveRole"},"added_at":{"type":["string","null"]}},"required":["user_id","display_name","email","role","added_at"]},"SharedDriveMembersResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SharedDriveMember"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"SharedDriveMembershipResponse":{"type":"object","properties":{"shared_drive_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/SharedDriveRole"}},"required":["shared_drive_id","user_id","role"]},"AddSharedDriveMemberInput":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/SharedDriveRole"}},"required":["user_id","role"],"additionalProperties":false},"UpdateSharedDriveMemberInput":{"type":"object","properties":{"role":{"$ref":"#/components/schemas/SharedDriveRole"}},"required":["role"],"additionalProperties":false},"RemoveSharedDriveMemberResponse":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]},"SharedDriveFile":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"mime_type":{"type":["string","null"]},"size_bytes":{"type":["integer","null"]},"owner_id":{"type":["string","null"],"format":"uuid"},"parent_folder_id":{"type":["string","null"],"format":"uuid"},"is_folder":{"type":"boolean"},"shared_drive_id":{"type":["string","null"],"format":"uuid"},"visibility":{"type":"string"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"owner":{"anyOf":[{"$ref":"#/components/schemas/DriveFileOwner"},{"type":"null"}]}},"required":["id","name","mime_type","owner_id","parent_folder_id","is_folder","shared_drive_id","created_at","updated_at","owner"],"additionalProperties":{}},"SharedDriveFilesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SharedDriveFile"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"CreateSharedDriveFolderInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"parent_folder_id":{"type":"string","format":"uuid"}},"required":["name"],"additionalProperties":false},"DriveDownloadResponse":{"type":"object","properties":{"url":{"type":"string"},"name":{"type":"string"},"mime_type":{"type":["string","null"]}},"required":["url","name","mime_type"]},"DriveViewResponse":{"type":"object","properties":{"url":{"type":"string"},"name":{"type":"string"},"mime_type":{"type":["string","null"]},"expires_in":{"type":"integer"}},"required":["url","name","mime_type","expires_in"]},"DriveStarInput":{"type":"object","properties":{"starred":{"type":"boolean","description":"Omit to toggle the current state."}},"additionalProperties":false},"DriveTagAttachInput":{"type":"object","properties":{"tag_id":{"type":"string","format":"uuid"}},"required":["tag_id"],"additionalProperties":false},"DriveBinaryBody":{"type":"string"},"DrivePendingShareEntry":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string"},"created_at":{"type":["string","null"]}},"required":["id","email","role","created_at"]},"DriveFilePermissionsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DriveFilePermissionEntry"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]},"pending":{"type":"array","items":{"$ref":"#/components/schemas/DrivePendingShareEntry"}}},"required":["data","total","has_more"]},"DriveSetFilePermissionResponse":{"type":"object","properties":{"file_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"team_id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/DriveFileRole"}},"required":["file_id","role"],"additionalProperties":{}},"DriveSetFilePermissionInput":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"team_id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/DriveFileRole"}},"required":["role"],"additionalProperties":false},"DriveUpdateFilePermissionResponse":{"type":"object","properties":{"file_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/DriveFileRole"}},"required":["file_id","user_id","role"]},"DriveUpdateFilePermissionInput":{"type":"object","properties":{"role":{"$ref":"#/components/schemas/DriveFileRole"}},"required":["role"],"additionalProperties":false},"DriveRemovePermissionResponse":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"]},"DriveComment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"file_id":{"type":"string","format":"uuid"},"parent_id":{"type":["string","null"],"format":"uuid"},"content":{"type":"string"},"anchor":{"$ref":"#/components/schemas/DriveCommentAnchor"},"resolved":{"type":"boolean"},"resolved_at":{"type":["string","null"]},"resolved_by":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"author":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]},"reactions":{"type":"array","items":{"$ref":"#/components/schemas/CommentReaction"}},"replies":{"type":"array","items":{"$ref":"#/components/schemas/DriveComment"}}},"required":["id","file_id","parent_id","content","anchor","resolved","resolved_at","resolved_by","created_at","updated_at","author","reactions","replies"]},"DriveCommentAnchor":{"oneOf":[{"$ref":"#/components/schemas/DriveCommentFileAnchor"},{"$ref":"#/components/schemas/DriveCommentRegionAnchor"}],"discriminator":{"propertyName":"kind","mapping":{"file":"#/components/schemas/DriveCommentFileAnchor","region":"#/components/schemas/DriveCommentRegionAnchor"}}},"DriveCommentFileAnchor":{"type":"object","properties":{"kind":{"type":"string","enum":["file"],"description":"Binds the comment to the whole file."}},"required":["kind"]},"DriveCommentRegionAnchor":{"type":"object","properties":{"kind":{"type":"string","enum":["region"],"description":"Binds the comment to a region of the rendered page."},"page":{"type":"integer","minimum":1,"description":"1-based page index; 1 for single-surface previews."},"x":{"type":"number","description":"Left edge as a fraction of rendered width (0..1)."},"y":{"type":"number","description":"Top edge as a fraction of rendered height (0..1)."},"w":{"type":"number","description":"Width as a fraction of rendered width (0..1)."},"h":{"type":"number","description":"Height as a fraction of rendered height (0..1)."}},"required":["kind","page","x","y","w","h"]},"DriveCommentListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DriveComment"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"DriveCommentCreateInput":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":10000},"parent_id":{"type":["string","null"],"format":"uuid"},"anchor":{"anyOf":[{"anyOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["file"],"description":"Binds the comment to the whole file."}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["region"],"description":"Binds the comment to a region of the rendered page."},"page":{"type":"integer","minimum":1,"description":"1-based page index; 1 for single-surface previews."},"x":{"type":"number","description":"Left edge as a fraction of rendered width (0..1)."},"y":{"type":"number","description":"Top edge as a fraction of rendered height (0..1)."},"w":{"type":"number","description":"Width as a fraction of rendered width (0..1)."},"h":{"type":"number","description":"Height as a fraction of rendered height (0..1)."}},"required":["kind","page","x","y","w","h"],"additionalProperties":false},{"type":"object","properties":{"page":{"type":"integer","minimum":1,"description":"1-based page index; 1 for single-surface previews."},"x":{"type":"number","description":"Left edge as a fraction of rendered width (0..1)."},"y":{"type":"number","description":"Top edge as a fraction of rendered height (0..1)."},"w":{"type":"number","description":"Width as a fraction of rendered width (0..1)."},"h":{"type":"number","description":"Height as a fraction of rendered height (0..1)."}},"required":["page","x","y","w","h"],"additionalProperties":false}]},{"type":"null"}]}},"required":["content"],"additionalProperties":false},"DriveCommentUpdateInput":{"type":"object","properties":{"resolved":{"type":"boolean"},"content":{"type":"string","minLength":1,"maxLength":10000}},"additionalProperties":false},"DriveCommentDeletedResponse":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"]},"DriveFileTextExtract":{"type":"object","properties":{"file_id":{"type":"string","format":"uuid"},"text":{"type":"string"},"status":{"type":"string","enum":["extracted","empty"]},"extracted_at":{"type":"string"}},"required":["file_id","text","status","extracted_at"]},"DriveVisibilityResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"visibility":{"type":"string"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"}},"required":["id","visibility","link_expires_at","has_password"]},"DriveVisibilityInput":{"type":"object","properties":{"visibility":{"$ref":"#/components/schemas/DriveFileVisibility"},"linkExpiresAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"linkPassword":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["visibility"],"additionalProperties":false},"DriveFileVisibility":{"type":"string","enum":["restricted","workspace","link","public"],"description":"File visibility / public-link mode."},"DriveShareInviteResponse":{"type":"object","properties":{"notification":{"$ref":"#/components/schemas/ShareNotificationResponse"},"invite_id":{"type":["string","null"],"format":"uuid"},"pending_share_id":{"type":["string","null"],"format":"uuid"},"email":{"type":"string"},"role":{"type":"string"},"granted":{"type":"string","enum":["direct","pending"]},"user_id":{"type":"string","format":"uuid"}},"required":["invite_id","pending_share_id","email","role","granted"],"additionalProperties":{}},"DriveShareInviteInput":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"$ref":"#/components/schemas/DriveFileRole"},"invite_to_workspace":{"type":"boolean"},"message":{"type":"string"}},"required":["email","role"],"additionalProperties":false},"DriveRestoreFileResponse":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]},"DriveExportInput":{"type":"object","properties":{"format":{"type":"string","description":"Target export format (e.g., docx, pdf, xlsx, csv, pptx). Validated by the handler."}},"additionalProperties":false},"DriveUpdateFileInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"parent_folder_id":{"type":["string","null"],"format":"uuid"},"starred":{"type":"boolean"}},"additionalProperties":false},"DriveFileVersion":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"size_bytes":{"type":"integer","minimum":0},"mime_type":{"type":"string"},"uploaded_by_id":{"type":["string","null"],"format":"uuid"},"uploaded_by_name":{"type":"string","description":"Uploader display name, or 'Former member' once that user is deleted."},"created_at":{"type":["string","null"]}},"required":["id","size_bytes","mime_type","uploaded_by_id","uploaded_by_name","created_at"]},"DriveFileVersionListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DriveFileVersion"}},"has_more":{"type":"boolean"}},"required":["data","has_more"]},"ExternalMailAuthUrlResponse":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"ExternalMailDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"ExternalMailConnection":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"provider_email":{"type":"string"},"sync_enabled":{"type":["boolean","null"]},"status":{"type":"string"},"last_sync_at":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","provider","provider_email","sync_enabled","status","last_sync_at","created_at"]},"ExternalMailConnectionListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExternalMailConnection"}},"total":{"type":"number"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ExternalMailTestResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"provider_email":{"type":"string"},"messages_total":{"type":"number"},"error":{"type":"string"}},"required":["ok"]},"Email":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":["string","null"],"format":"uuid"},"thread_id":{"type":["string","null"],"description":"The RFC-5322-stitched thread key, not a UUID."},"folder":{"$ref":"#/components/schemas/EmailFolder"},"from":{"anyOf":[{"$ref":"#/components/schemas/MailParticipant"},{"type":"null"}]},"to":{"type":"array","items":{"$ref":"#/components/schemas/MailParticipant"}},"cc":{"type":"array","items":{"$ref":"#/components/schemas/MailParticipant"}},"bcc":{"type":"array","items":{"$ref":"#/components/schemas/MailParticipant"}},"reply_to":{"type":"array","items":{"$ref":"#/components/schemas/MailParticipant"}},"subject":{"type":"string"},"preview":{"type":["string","null"]},"body_html":{"type":["string","null"]},"body_text":{"type":["string","null"]},"read":{"type":"boolean"},"starred":{"type":"boolean"},"archived":{"type":"boolean"},"trashed":{"type":"boolean"},"snoozed_until":{"type":["string","null"]},"scheduled_at":{"type":["string","null"]},"sent_at":{"type":["string","null"]},"received_at":{"type":["string","null"]},"labels":{"type":"array","items":{"type":"string"}},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/EmailAttachment"}},"calendar_invite":{"anyOf":[{"$ref":"#/components/schemas/EmailCalendarInvite"},{"type":"null"}]},"inbound_auth":{"anyOf":[{"$ref":"#/components/schemas/EmailInboundAuth"},{"type":"null"}]},"in_reply_to":{"type":["string","null"]},"references":{"type":"array","items":{"type":"string"}},"contact_id":{"type":["string","null"],"format":"uuid","description":"CRM contact link."},"deal_id":{"type":["string","null"],"format":"uuid","description":"CRM deal link."},"from_user":{"anyOf":[{"$ref":"#/components/schemas/MailParticipant"},{"type":"null"}],"description":"Duplicate of `from`, kept for a pre-`from` consumer. Same object; prefer `from`."},"delivery_status":{"type":"string","description":"`sent` / `pending_undo` / `suppressed` / `failed` (MAIL.md P7). A bare string, not an enum, so a value written before the set narrowed stays readable."},"message_id":{"type":["string","null"],"description":"RFC 5322 Message-ID."},"thread_count":{"type":"integer","description":"Messages in this row's thread; 1 for a standalone message."},"has_attachments":{"type":"boolean"},"undo_send_until":{"type":["string","null"],"description":"Non-null only while `delivery_status` is `pending_undo`."},"read_receipt_requested":{"type":"boolean"},"read_receipt_first_seen_at":{"type":["string","null"]},"read_receipt_last_seen_at":{"type":["string","null"]},"read_receipt_open_count":{"type":"integer","minimum":0},"list_unsubscribe":{"type":["string","null"],"description":"RFC 2369 List-Unsubscribe header, verbatim."},"list_unsubscribe_post":{"type":["string","null"],"description":"RFC 8058 one-click List-Unsubscribe-Post header, verbatim."},"assignee":{"anyOf":[{"$ref":"#/components/schemas/MailThreadAssignee"},{"type":"null"}]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","read"],"additionalProperties":{}},"EmailFolder":{"type":"string","enum":["inbox","sent","drafts","scheduled","snoozed","starred","archive","trash","muted"],"description":"Folder bucket the message is currently in."},"MailParticipant":{"allOf":[{"$ref":"#/components/schemas/EmailAddress"},{"type":"object","properties":{"id":{"type":"string","description":"Workspace user id, or `\"\"` for an address matching no user."},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"custom_email":{"type":["string","null"]},"workspace_email":{"type":["string","null"]},"avatar_url":{"type":["string","null"]},"type":{"type":["string","null"],"enum":["human","agent",null],"description":"`users.type` — null for an external address matching no workspace user."}}}]},"EmailAddress":{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"]},"EmailAttachment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"filename":{"type":"string"},"mime_type":{"type":"string"},"size":{"type":"integer","minimum":0},"content_id":{"type":["string","null"]},"inline":{"type":"boolean"}},"required":["id","filename","mime_type","size"]},"EmailCalendarInvite":{"type":"object","properties":{"uid":{"type":"string"},"sequence":{"type":"integer"},"organizer":{"anyOf":[{"$ref":"#/components/schemas/EmailAddress"},{"type":"null"}]},"summary":{"type":["string","null"]},"description":{"type":["string","null"]},"location":{"type":["string","null"]},"start_at":{"type":["string","null"]},"end_at":{"type":["string","null"]},"all_day":{"type":"boolean"},"method":{"type":["string","null"]},"rsvp":{"anyOf":[{"$ref":"#/components/schemas/MailRsvpChoice"},{"type":"null"}]}},"required":["uid"],"additionalProperties":{}},"MailRsvpChoice":{"type":"string","enum":["accepted","declined","tentative"],"description":"RSVP response on an inbound calendar invite."},"EmailInboundAuth":{"type":"object","properties":{"verdict":{"type":"string","enum":["aligned","unaligned","unverified"],"description":"`aligned` iff SPF or DKIM passed AND its domain aligns with the From domain (RFC 7489 §3.1). `unverified` means no verdict evidence existed — never that the sender failed."},"spf":{"$ref":"#/components/schemas/InboundAuthStatus"},"dkim":{"$ref":"#/components/schemas/InboundAuthStatus"},"dmarc":{"allOf":[{"$ref":"#/components/schemas/InboundAuthStatus"},{"description":"Evidence only — does not gate `verdict`."}]},"dmarcPolicy":{"type":["string","null"],"enum":["none","quarantine","reject",null]},"fromDomain":{"type":["string","null"]},"mailFromDomain":{"type":["string","null"]},"dkimDomains":{"type":"array","items":{"type":"string"}},"spfAligned":{"type":"boolean"},"dkimAligned":{"type":"boolean"},"dkimTruncated":{"type":"boolean","description":"The message carried more signatures than the evaluator scans."}},"required":["verdict","spf","dkim","dmarc","dmarcPolicy","fromDomain","mailFromDomain","dkimDomains","spfAligned","dkimAligned","dkimTruncated"],"additionalProperties":{}},"InboundAuthStatus":{"type":"string","enum":["pass","fail","none","gray","processing_failed","unknown","absent"],"description":"SES verdict for one authentication check; `absent` means the receipt carried none."},"MailThreadAssignee":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"avatar_url":{"type":["string","null"]}},"required":["user_id","display_name"]},"MailSearchResultsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Email"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"SmartComposeResponse":{"type":"object","properties":{"suggestion":{"type":"string"}},"required":["suggestion"],"additionalProperties":{}},"SmartComposeInput":{"type":"object","properties":{"prefix":{"type":"string","maxLength":64000,"description":"Text already typed by the user."},"subject":{"type":"string","maxLength":2000},"thread_context":{"type":"string","maxLength":512000}},"required":["prefix"],"additionalProperties":false},"FolderCountsResponse":{"type":"object","additionalProperties":{"type":"integer"},"description":"Map of folder name → unread count."},"UnreadSummaryResponse":{"type":"object","properties":{"total":{"type":"integer"},"important":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Email"}}},"required":["total","items"],"additionalProperties":{}},"SendAsAddress":{"type":"object","properties":{"email":{"type":"string"},"domain":{"type":"string"},"domain_type":{"type":"string","enum":["workspace","custom","connected"]},"verified":{"type":"boolean"},"is_default":{"type":"boolean"}},"required":["email","domain","domain_type","verified","is_default"],"additionalProperties":{}},"MailSendAsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SendAsAddress"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"MailSetDefaultSendAsResponse":{"type":"object","properties":{"success":{"type":"boolean"},"default_send_as":{"type":"string"}},"required":["success","default_send_as"]},"MailSetDefaultSendAsInput":{"type":"object","properties":{"email":{"type":"string"}},"required":["email"],"additionalProperties":false},"MailAlias":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"address":{"type":"string"},"is_default":{"type":"boolean"},"verified":{"type":"boolean"},"created_at":{"type":["string","null"]},"local_part":{"type":"string"},"domain":{"type":"string"},"domain_type":{"type":"string"},"can_send":{"type":"boolean"}},"required":["id","address","is_default","verified","created_at"]},"MailAliasListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MailAlias"}},"available_domains":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"domain":{"type":"string"},"domainType":{"type":"string"},"verified":{"type":"boolean"}},"required":["id","domain","domainType","verified"]},"description":"Workspace domains a new alias can be created on (for the picker)."}},"required":["data"],"additionalProperties":{}},"MailAliasResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"address":{"type":"string"},"is_default":{"type":"boolean"},"verified":{"type":"boolean"},"created_at":{"type":["string","null"]},"local_part":{"type":"string"},"domain":{"type":"string"},"domain_type":{"type":"string"},"can_send":{"type":"boolean"}},"required":["id","address","is_default","verified","created_at"]},"MailAliasCreateInput":{"type":"object","properties":{"workspace_domain_id":{"type":"string","format":"uuid"},"local_part":{"type":"string","minLength":1}},"required":["workspace_domain_id","local_part"],"additionalProperties":false},"MailSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]},"SharedMailboxListItem":{"allOf":[{"$ref":"#/components/schemas/SharedMailbox"},{"type":"object","properties":{"unread_count":{"type":"integer","minimum":0,"description":"Unread inbox threads, counted the same way the folder badge counts them."}},"required":["unread_count"]}]},"SharedMailboxMember":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"team_id":{"type":["string","null"],"format":"uuid"},"display_name":{"type":"string"},"added_at":{"type":["string","null"]}},"required":["id","user_id","team_id","display_name","added_at"]},"SharedMailbox":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"address":{"type":["string","null"],"description":"Primary alias address, null until one is created."},"members":{"type":"array","items":{"$ref":"#/components/schemas/SharedMailboxMember"}},"retired_at":{"type":["string","null"],"description":"When the mailbox was retired, else null. Retired mailboxes appear only under `scope=managed` — an admin has to be able to reach the one they can restore."}},"required":["id","display_name","address","members","retired_at"]},"SharedMailboxListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SharedMailboxListItem"}}},"required":["data"]},"SharedMailboxResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"address":{"type":["string","null"],"description":"Primary alias address, null until one is created."},"members":{"type":"array","items":{"$ref":"#/components/schemas/SharedMailboxMember"}},"retired_at":{"type":["string","null"],"description":"When the mailbox was retired, else null. Retired mailboxes appear only under `scope=managed` — an admin has to be able to reach the one they can restore."}},"required":["id","display_name","address","members","retired_at"]},"SharedMailboxCreateInput":{"type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":120},"local_part":{"type":"string","minLength":1,"description":"Local part of the mailbox address, e.g. `support`."},"workspace_domain_id":{"type":"string","format":"uuid","description":"Domain to address the mailbox on. Defaults to the workspace domain."}},"required":["display_name","local_part"],"additionalProperties":false},"SharedMailboxUpdateInput":{"type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":120}},"required":["display_name"],"additionalProperties":false},"MailboxAssigneeListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MailThreadAssignee"}}},"required":["data"]},"SharedMailboxMemberAddInput":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"team_id":{"type":"string","format":"uuid"}},"additionalProperties":false},"MailSignatureResponse":{"type":"object","properties":{"effective":{"type":["string","null"],"description":"The signature that will be appended to outgoing mail — personal if set, else the workspace default."},"user_signature":{"type":["string","null"],"description":"The caller's personal signature Markdown; null = use the workspace default."},"workspace_default":{"type":["string","null"]},"source":{"type":"string","enum":["user","workspace","none"]}},"required":["effective","user_signature","workspace_default","source"]},"MailSignatureUpdateInput":{"type":"object","properties":{"markdown":{"type":["string","null"],"maxLength":5000}},"required":["markdown"],"additionalProperties":false},"EmailResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":["string","null"],"format":"uuid"},"thread_id":{"type":["string","null"],"description":"The RFC-5322-stitched thread key, not a UUID."},"folder":{"$ref":"#/components/schemas/EmailFolder"},"from":{"anyOf":[{"$ref":"#/components/schemas/MailParticipant"},{"type":"null"}]},"to":{"type":"array","items":{"$ref":"#/components/schemas/MailParticipant"}},"cc":{"type":"array","items":{"$ref":"#/components/schemas/MailParticipant"}},"bcc":{"type":"array","items":{"$ref":"#/components/schemas/MailParticipant"}},"reply_to":{"type":"array","items":{"$ref":"#/components/schemas/MailParticipant"}},"subject":{"type":"string"},"preview":{"type":["string","null"]},"body_html":{"type":["string","null"]},"body_text":{"type":["string","null"]},"read":{"type":"boolean"},"starred":{"type":"boolean"},"archived":{"type":"boolean"},"trashed":{"type":"boolean"},"snoozed_until":{"type":["string","null"]},"scheduled_at":{"type":["string","null"]},"sent_at":{"type":["string","null"]},"received_at":{"type":["string","null"]},"labels":{"type":"array","items":{"type":"string"}},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/EmailAttachment"}},"calendar_invite":{"anyOf":[{"$ref":"#/components/schemas/EmailCalendarInvite"},{"type":"null"}]},"inbound_auth":{"anyOf":[{"$ref":"#/components/schemas/EmailInboundAuth"},{"type":"null"}]},"in_reply_to":{"type":["string","null"]},"references":{"type":"array","items":{"type":"string"}},"contact_id":{"type":["string","null"],"format":"uuid","description":"CRM contact link."},"deal_id":{"type":["string","null"],"format":"uuid","description":"CRM deal link."},"from_user":{"anyOf":[{"$ref":"#/components/schemas/MailParticipant"},{"type":"null"}],"description":"Duplicate of `from`, kept for a pre-`from` consumer. Same object; prefer `from`."},"delivery_status":{"type":"string","description":"`sent` / `pending_undo` / `suppressed` / `failed` (MAIL.md P7). A bare string, not an enum, so a value written before the set narrowed stays readable."},"message_id":{"type":["string","null"],"description":"RFC 5322 Message-ID."},"thread_count":{"type":"integer","description":"Messages in this row's thread; 1 for a standalone message."},"has_attachments":{"type":"boolean"},"undo_send_until":{"type":["string","null"],"description":"Non-null only while `delivery_status` is `pending_undo`."},"read_receipt_requested":{"type":"boolean"},"read_receipt_first_seen_at":{"type":["string","null"]},"read_receipt_last_seen_at":{"type":["string","null"]},"read_receipt_open_count":{"type":"integer","minimum":0},"list_unsubscribe":{"type":["string","null"],"description":"RFC 2369 List-Unsubscribe header, verbatim."},"list_unsubscribe_post":{"type":["string","null"],"description":"RFC 8058 one-click List-Unsubscribe-Post header, verbatim."},"assignee":{"anyOf":[{"$ref":"#/components/schemas/MailThreadAssignee"},{"type":"null"}]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","read"],"additionalProperties":{}},"SendEmailInput":{"type":"object","properties":{"to":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"],"additionalProperties":false}]},"description":"Empty drafts allowed; required when sending."},"cc":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"],"additionalProperties":false}]}},"bcc":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"],"additionalProperties":false}]}},"subject":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"},"body_markdown":{"type":"string","description":"Authoring-format body. Compiles to body_html on send."},"in_reply_to":{"type":"string"},"thread_id":{"type":"string","description":"Attach the message to an existing thread."},"references":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"attachments":{"type":"array","items":{}},"attachment_ids":{"type":"array","items":{"type":"string"},"description":"Drive file IDs to attach."},"request_read_receipt":{"type":"boolean"},"idempotency_key":{"type":"string","maxLength":255,"description":"Optional retry key. Reusing the same key with the same send request returns the original send."},"contact_id":{"type":["string","null"],"format":"uuid"},"deal_id":{"type":["string","null"],"format":"uuid"},"scheduled_at":{"type":["string","null"],"description":"ISO-8601. Defers send."},"scheduled_for":{"type":["string","null"],"description":"Legacy alias for scheduled_at."},"from_email":{"type":"string","description":"Send-as address (must be a verified alias/domain)."},"undo_send_seconds":{"type":"integer","minimum":0},"include_signature":{"type":"boolean"},"archive_thread_id":{"type":"string","description":"Archive this thread once the reply succeeds."}},"additionalProperties":false},"EmailListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Email"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"MailAssignmentFilter":{"type":"string","enum":["me","unassigned"],"description":"Shared-mailbox queue only: `me` for threads you hold, `unassigned` for threads nobody holds. 400 on a personal mailbox or with a non-inbox `folder`."},"SnoozedEmailListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Email"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"EmailDraft":{"allOf":[{"$ref":"#/components/schemas/Email"},{"type":"object","properties":{"is_draft":{"type":"boolean","enum":[true]}},"additionalProperties":{}}]},"EmailDraftListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailDraft"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"EmailDraftResponse":{"allOf":[{"$ref":"#/components/schemas/Email"},{"type":"object","properties":{"is_draft":{"type":"boolean","enum":[true]}},"additionalProperties":{}}]},"DraftCreateInput":{"type":"object","properties":{"to":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"],"additionalProperties":false}]},"description":"Empty drafts allowed; required when sending."},"cc":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"],"additionalProperties":false}]}},"bcc":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"],"additionalProperties":false}]}},"subject":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"},"body_markdown":{"type":"string","description":"Authoring-format body. Compiles to body_html on send."},"in_reply_to":{"type":"string"},"thread_id":{"type":"string","description":"Attach the message to an existing thread."},"references":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"attachments":{"type":"array","items":{}},"attachment_ids":{"type":"array","items":{"type":"string"},"description":"Drive file IDs to attach."},"request_read_receipt":{"type":"boolean"},"idempotency_key":{"type":"string","maxLength":255,"description":"Optional retry key. Reusing the same key with the same send request returns the original send."},"contact_id":{"type":["string","null"],"format":"uuid"},"deal_id":{"type":["string","null"],"format":"uuid"}},"additionalProperties":false},"DraftUpdateInput":{"type":"object","properties":{"to":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"],"additionalProperties":false}]},"description":"Empty drafts allowed; required when sending."},"cc":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"],"additionalProperties":false}]}},"bcc":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["email"],"additionalProperties":false}]}},"subject":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"},"body_markdown":{"type":"string","description":"Authoring-format body. Compiles to body_html on send."},"in_reply_to":{"type":"string"},"thread_id":{"type":"string","description":"Attach the message to an existing thread."},"references":{"type":"array","items":{"type":"string"}},"labels":{"type":"array","items":{"type":"string"}},"attachments":{"type":"array","items":{}},"attachment_ids":{"type":"array","items":{"type":"string"},"description":"Drive file IDs to attach."},"request_read_receipt":{"type":"boolean"},"idempotency_key":{"type":"string","maxLength":255,"description":"Optional retry key. Reusing the same key with the same send request returns the original send."},"contact_id":{"type":["string","null"],"format":"uuid"},"deal_id":{"type":["string","null"],"format":"uuid"}},"additionalProperties":false},"ScheduledEmailListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Email"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"MailRescheduleResponse":{"type":"object","properties":{"success":{"type":"boolean"},"scheduled_at":{"type":"string"}},"required":["success","scheduled_at"]},"MailRescheduleInput":{"type":"object","properties":{"scheduled_at":{"type":"string","description":"Future ISO-8601 delivery time."}},"required":["scheduled_at"],"additionalProperties":false},"UndoSendSettingsResponse":{"type":"object","properties":{"enabled":{"type":"boolean","description":"False when the delay is zero — a send is delivered immediately."},"delay_seconds":{"type":"integer","minimum":0},"max_delay_seconds":{"type":"integer","exclusiveMinimum":0}},"required":["enabled","delay_seconds","max_delay_seconds"]},"UndoSendUpdateInput":{"type":"object","properties":{"undo_send_seconds":{"type":"integer","minimum":0}},"required":["undo_send_seconds"],"additionalProperties":false},"MailReadReceiptSettingsResponse":{"type":"object","properties":{"request_default":{"type":"boolean","description":"Whether a new compose requests a read receipt by default."},"auto_send_default":{"type":"boolean"}},"required":["request_default"],"additionalProperties":{}},"MailReadReceiptsUpdateInput":{"type":"object","properties":{"read_receipts_default":{"type":"boolean"}},"required":["read_receipts_default"],"additionalProperties":false},"MailSnoozePreset":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":60},"offset_minutes":{"type":"integer","exclusiveMinimum":0}},"required":["label","offset_minutes"]},"MailSnoozePresetsResponse":{"type":"object","properties":{"presets":{"type":"array","items":{"$ref":"#/components/schemas/MailSnoozePreset"}},"is_default":{"type":"boolean"}},"required":["presets","is_default"]},"MailSnoozePresetsUpdateInput":{"type":"object","properties":{"presets":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":60},"offset_minutes":{"type":"integer","exclusiveMinimum":0}},"required":["label","offset_minutes"],"additionalProperties":false},"maxItems":10}},"required":["presets"],"additionalProperties":false},"EmailOpenEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"opened_at":{"type":"string"},"user_agent":{"type":["string","null"]},"referer":{"type":["string","null"]}},"required":["id","opened_at","user_agent","referer"]},"EmailOpensResponse":{"type":"object","properties":{"email_id":{"type":"string","format":"uuid"},"requested":{"type":"boolean"},"open_count":{"type":"integer","minimum":0},"first_seen_at":{"type":["string","null"],"description":"When the message was first opened; null if never."},"last_opened_at":{"type":["string","null"],"description":"When the message was most recently opened; null if never."},"events":{"type":"array","items":{"$ref":"#/components/schemas/EmailOpenEvent"}}},"required":["email_id","requested","open_count","first_seen_at","last_opened_at"],"additionalProperties":{}},"MailRule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"},"sort_order":{"type":"integer"},"conditions":{},"actions":{"type":"array","items":{}},"match_mode":{"type":"string","enum":["all","any"],"description":"Whether every condition must match, or any one of them."},"stop_processing":{"type":"boolean","description":"When true, a match ends rule evaluation for that message (P8's fixed precedence)."},"applied_count":{"type":"integer","minimum":0},"last_applied_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","mailbox_id","name","enabled","sort_order","actions","match_mode","stop_processing","applied_count","last_applied_at","created_at"],"additionalProperties":{}},"MailRuleListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MailRule"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"MailRuleResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"enabled":{"type":"boolean"},"sort_order":{"type":"integer"},"conditions":{},"actions":{"type":"array","items":{}},"match_mode":{"type":"string","enum":["all","any"],"description":"Whether every condition must match, or any one of them."},"stop_processing":{"type":"boolean","description":"When true, a match ends rule evaluation for that message (P8's fixed precedence)."},"applied_count":{"type":"integer","minimum":0},"last_applied_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","mailbox_id","name","enabled","sort_order","actions","match_mode","stop_processing","applied_count","last_applied_at","created_at"],"additionalProperties":{}},"MailRuleCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"enabled":{"type":"boolean"},"conditions":{},"actions":{"type":"array","items":{}},"match_mode":{"type":"string"},"stop_processing":{"type":"boolean"}},"required":["name","actions"],"additionalProperties":false},"MailRuleReorderInput":{"type":"object","properties":{"rule_ids":{"type":"array","items":{"type":"string"}}},"required":["rule_ids"],"additionalProperties":false},"MailRuleUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"enabled":{"type":"boolean"},"conditions":{},"actions":{"type":"array","items":{}},"match_mode":{"type":"string"},"stop_processing":{"type":"boolean"},"sort_order":{"type":"integer"}},"additionalProperties":false},"MailTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"subject":{"type":"string"},"body_markdown":{"type":"string"},"body_html":{"type":["string","null"]},"body_text":{"type":["string","null"]},"category":{"type":["string","null"]},"sort_order":{"type":"integer"},"use_count":{"type":"integer","minimum":0},"last_used_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","mailbox_id","name","subject","body_markdown","body_html","body_text","category","sort_order","use_count","last_used_at","created_at"],"additionalProperties":{}},"MailTemplateListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MailTemplate"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"MailTemplateResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"subject":{"type":"string"},"body_markdown":{"type":"string"},"body_html":{"type":["string","null"]},"body_text":{"type":["string","null"]},"category":{"type":["string","null"]},"sort_order":{"type":"integer"},"use_count":{"type":"integer","minimum":0},"last_used_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","mailbox_id","name","subject","body_markdown","body_html","body_text","category","sort_order","use_count","last_used_at","created_at"],"additionalProperties":{}},"MailTemplateCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"subject":{"type":"string"},"body_markdown":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"},"category":{"type":"string"}},"required":["name","subject"],"additionalProperties":false},"MailTemplateUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"subject":{"type":"string"},"body_markdown":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"},"category":{"type":"string"},"sort_order":{"type":"integer"}},"additionalProperties":false},"MailTemplateUseResponse":{"type":"object","properties":{"subject":{"type":"string"},"body_html":{"type":["string","null"]},"body_text":{"type":["string","null"]}},"required":["subject","body_html","body_text"],"additionalProperties":{}},"MailLabel":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"color":{"$ref":"#/components/schemas/EmailLabelColor"},"sort_order":{"type":"integer"},"show_in_sidebar":{"type":"boolean","description":"Gmail-parity \"Show in label list\". When false the label is hidden from the sidebar but still chips on messages and filters."},"parent_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","mailbox_id","name","color","sort_order","show_in_sidebar"],"additionalProperties":{}},"EmailLabelColor":{"type":"string","enum":["red","orange","yellow","green","blue","purple","pink","cyan","gray"],"description":"Built-in label palette."},"MailLabelListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MailLabel"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"MailLabelCountsResponse":{"type":"object","additionalProperties":{"type":"integer"}},"MailLabelResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"color":{"$ref":"#/components/schemas/EmailLabelColor"},"sort_order":{"type":"integer"},"show_in_sidebar":{"type":"boolean","description":"Gmail-parity \"Show in label list\". When false the label is hidden from the sidebar but still chips on messages and filters."},"parent_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","mailbox_id","name","color","sort_order","show_in_sidebar"],"additionalProperties":{}},"MailLabelCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"color":{"$ref":"#/components/schemas/EmailLabelColor"},"parent_id":{"type":["string","null"],"format":"uuid"}},"required":["name"],"additionalProperties":false},"MailLabelReorderInput":{"type":"object","properties":{"label_ids":{"type":"array","items":{"type":"string"}}},"required":["label_ids"],"additionalProperties":false},"MailLabelUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"color":{"$ref":"#/components/schemas/EmailLabelColor"},"parent_id":{"type":["string","null"],"format":"uuid"},"sort_order":{"type":"integer"},"show_in_sidebar":{"type":"boolean"}},"additionalProperties":false},"VacationResponderResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":"string","format":"uuid"},"enabled":{"type":"boolean"},"subject":{"type":["string","null"]},"body":{"type":["string","null"]},"start_at":{"type":["string","null"]},"end_at":{"type":["string","null"]},"exclude_contacts":{"type":"boolean"},"only_send_once":{"type":"boolean"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","mailbox_id","enabled","subject","body","start_at","end_at","exclude_contacts","only_send_once","created_at","updated_at"],"additionalProperties":{}},"VacationUpdateInput":{"type":"object","properties":{"enabled":{"type":"boolean"},"subject":{"type":["string","null"]},"body_markdown":{"type":["string","null"]},"start_date":{"type":["string","null"]},"end_date":{"type":["string","null"]},"exclude_contacts":{"type":"boolean"},"only_send_once":{"type":"boolean"}},"additionalProperties":false},"BlockedSender":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mailbox_id":{"type":"string","format":"uuid"},"pattern":{"type":"string"},"kind":{"$ref":"#/components/schemas/BlocklistKind"},"reason":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","mailbox_id","pattern","kind","reason","created_at"]},"BlocklistKind":{"type":"string","enum":["address","domain"],"description":"`address` matches a single email; `domain` matches any sender at that domain."},"BlocklistListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BlockedSender"}}},"required":["data"]},"BlocklistAddResponse":{"allOf":[{"$ref":"#/components/schemas/BlockedSender"},{"type":"object","properties":{"entry":{"$ref":"#/components/schemas/BlockedSender"},"trashed_existing":{"type":"integer","minimum":0}}}]},"MailBlocklistAddInput":{"type":"object","properties":{"pattern":{"type":"string","minLength":1},"kind":{"$ref":"#/components/schemas/BlocklistKind"},"reason":{"type":"string"},"trash_existing":{"type":"boolean","description":"Default true; retroactively trashes matching inbox/archive mail."}},"required":["pattern"],"additionalProperties":false},"MailUnblockSenderResponse":{"type":"object","properties":{"unblocked":{"type":"boolean","enum":[true]},"removed":{"type":"boolean"}},"additionalProperties":{}},"MailUnblockSenderInput":{"type":"object","properties":{"id":{"type":"string"},"pattern":{"type":"string"}},"additionalProperties":false},"MailUnsubscribeResponse":{"type":"object","properties":{"status":{"type":"string","enum":["unsubscribed","attempted","mailto"]},"method":{"type":"string","enum":["http","mailto"]},"url":{"type":"string","description":"The List-Unsubscribe HTTP endpoint that was POSTed."},"http_status":{"type":"integer"},"mailto":{"type":"string","description":"The address to email; present when no HTTP endpoint was offered."},"message":{"type":"string"}},"required":["status","method"]},"ForwardingAddress":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Forwarding address row ID."},"mailboxId":{"type":"string","format":"uuid","description":"Mailbox that owns this destination."},"address":{"type":"string","format":"email","description":"External email address messages forward to."},"label":{"type":["string","null"],"description":"Optional human label."},"verified":{"type":"boolean","description":"True once the recipient has clicked the verification link."},"verifiedAt":{"type":["string","null"]},"verificationSentAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","mailboxId","address","label","verified","verifiedAt","verificationSentAt","createdAt"]},"MailForwardLogEntry":{"type":"object","properties":{"id":{"type":"string"},"emailId":{"type":"string"},"forwardedTo":{"type":"string"},"ruleId":{"type":["string","null"]},"messageId":{"type":["string","null"]},"status":{"type":"string","enum":["sent","suppressed","failed"]},"error":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","emailId","forwardedTo","ruleId","messageId","status","error","createdAt"]},"MailForwardingListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ForwardingAddress"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"recent_log":{"type":"array","items":{"$ref":"#/components/schemas/MailForwardLogEntry"},"description":"The 20 most recent forwarding attempts, newest first."}},"required":["data","total","has_more","recent_log"]},"ForwardingEntryResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Forwarding address row ID."},"mailboxId":{"type":"string","format":"uuid","description":"Mailbox that owns this destination."},"address":{"type":"string","format":"email","description":"External email address messages forward to."},"label":{"type":["string","null"],"description":"Optional human label."},"verified":{"type":"boolean","description":"True once the recipient has clicked the verification link."},"verifiedAt":{"type":["string","null"]},"verificationSentAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","mailboxId","address","label","verified","verifiedAt","verificationSentAt","createdAt"]},"MailForwardingAddInput":{"type":"object","properties":{"address":{"type":"string","format":"email"},"label":{"type":"string"},"scope":{"$ref":"#/components/schemas/ForwardingScope"}},"required":["address"],"additionalProperties":false},"ForwardingScope":{"type":"string","enum":["all","matching"],"description":"`all` forwards every inbound message; `matching` only those matched by a forwarding rule."},"MailMergePreviewResponse":{"type":"object","properties":{"previews":{"type":"array","items":{"type":"object","properties":{"to":{"type":"array","items":{"type":"string"}},"subject":{"type":"string"},"body_html":{"type":["string","null"]},"body_text":{"type":["string","null"]}},"required":["to","subject","body_html","body_text"]}}},"required":["previews"],"additionalProperties":{}},"MailMergePreviewInput":{"type":"object","properties":{"template_id":{"type":"string","format":"uuid"},"subject":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"},"body_markdown":{"type":"string"},"recipient":{"type":"object","additionalProperties":{},"description":"Single recipient ({email, ...merge vars}) — preview."},"rows":{"type":"array","items":{"type":"object","additionalProperties":{}}},"recipients":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"Alias for `rows`."}},"additionalProperties":false},"MailMergeSendResponse":{"type":"object","properties":{"total":{"type":"integer","minimum":0,"description":"Recipients the merge attempted."},"sent":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"errors":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"error":{"type":"string"}},"required":["email","error"]}},"scheduled":{"type":"integer","minimum":0}},"required":["total","sent","failed","errors"],"additionalProperties":{}},"MailMergeSendInput":{"type":"object","properties":{"template_id":{"type":"string","format":"uuid"},"subject":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"},"body_markdown":{"type":"string"},"recipient":{"type":"object","additionalProperties":{},"description":"Single recipient ({email, ...merge vars}) — preview."},"rows":{"type":"array","items":{"type":"object","additionalProperties":{}}},"recipients":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"Alias for `rows`."},"from_email":{"type":"string"},"send_at":{"type":["string","null"]}},"additionalProperties":false},"MailMergeParseCsvResponse":{"type":"object","properties":{"columns":{"type":"array","items":{"type":"string"}},"rows":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["columns","rows"],"additionalProperties":{}},"MailMergeParseCsvInput":{"type":"object","properties":{"csv":{"type":"string"}},"additionalProperties":false},"EmailThreadResponse":{"type":"object","properties":{"id":{"type":"string","description":"The RFC-5322-stitched thread key, not a UUID."},"subject":{"type":"string"},"preview":{"type":["string","null"]},"last_message_at":{"type":["string","null"]},"message_count":{"type":"integer"},"unread_count":{"type":"integer"},"has_attachments":{"type":"boolean"},"labels":{"type":"array","items":{"type":"string"}},"participants":{"type":"array","items":{"$ref":"#/components/schemas/MailParticipant"}},"muted":{"type":"boolean"},"archived":{"type":"boolean"},"trashed":{"type":"boolean"},"assignee":{"anyOf":[{"$ref":"#/components/schemas/MailThreadAssignee"},{"type":"null"}]},"messages":{"type":"array","items":{"$ref":"#/components/schemas/Email"}}},"required":["id","subject","last_message_at","message_count"],"additionalProperties":{}},"MailThreadMuteStatusResponse":{"type":"object","properties":{"muted":{"type":"boolean"}},"required":["muted"]},"MailThreadAssignmentResponse":{"type":"object","properties":{"thread_id":{"type":"string"},"assignee":{"anyOf":[{"$ref":"#/components/schemas/MailThreadAssignee"},{"type":"null"}],"description":"Null is Unassigned."},"assigned_at":{"type":["string","null"]}},"required":["thread_id","assignee","assigned_at"]},"MailThreadAssignInput":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid","description":"The member to claim it for — your own id is `Assign to me`."}},"required":["user_id"],"additionalProperties":false},"MailThreadArchiveResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"archived":{"type":"integer","minimum":0}},"required":["success","archived"]},"MailThreadTrashResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"trashed_count":{"type":"integer","minimum":0}},"required":["success","trashed_count"]},"MailThreadUntrashResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"restored_count":{"type":"integer","minimum":0}},"required":["success","restored_count"]},"MailThreadComment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mail_thread_id":{"type":"string","format":"uuid","description":"The `mail_threads` identity row this hangs off."},"thread_id":{"type":"string","description":"The RFC-5322-stitched thread key the comment discusses."},"parent_id":{"type":["string","null"],"format":"uuid"},"content":{"type":"string"},"resolved":{"type":"boolean"},"resolved_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"author":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"avatar_url":{"type":["string","null"]}},"required":["id","display_name","primary_email","avatar_url"]},"reactions":{"type":"array","items":{"$ref":"#/components/schemas/CommentReaction"}},"replies":{"type":"array","items":{"$ref":"#/components/schemas/MailThreadComment"}}},"required":["id","mail_thread_id","thread_id","parent_id","content","resolved","resolved_at","created_at","updated_at","author","reactions","replies"]},"MailThreadCommentListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MailThreadComment"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"MailThreadCommentResponse":{"type":"object","properties":{"comment":{"$ref":"#/components/schemas/MailThreadComment"}},"required":["comment"]},"MailThreadCommentCreateInput":{"type":"object","properties":{"content":{"type":"string","minLength":1},"parent_id":{"type":"string","format":"uuid","description":"Reply to an existing comment on this thread."}},"required":["content"],"additionalProperties":false},"MailThreadCommentUpdateInput":{"type":"object","properties":{"content":{"type":"string","minLength":1,"description":"Author-only edit."},"resolved":{"type":"boolean","description":"Any member may resolve or reopen."}},"additionalProperties":false},"MailBulkModifyResponse":{"type":"object","properties":{"updated":{"type":"integer"}},"required":["updated"],"additionalProperties":{}},"MailBulkDeleteInput":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["ids"],"additionalProperties":false},"MailBulkModifyInput":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Explicit email IDs. Omit when using `search_query`."},"search_query":{"type":"string","description":"Gmail-style search query — applies the action to every matching email (capped at 500), not just a visible page."},"add_labels":{"type":"array","items":{"type":"string"},"description":"Label IDs or label names."},"remove_labels":{"type":"array","items":{"type":"string"}},"archive":{"type":"boolean"},"trash":{"type":"boolean"},"mark_read":{"type":"boolean"},"read":{"type":"boolean","description":"Alias for `mark_read`."},"star":{"type":"boolean"},"folder":{"type":"string"}},"additionalProperties":false},"MailBulkDeleteResponse":{"type":"object","properties":{"deleted":{"type":"integer"}},"required":["deleted"]},"MailBulkActionInput":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"},"description":"Explicit email IDs. Omit when using `search_query`."},"search_query":{"type":"string"},"action":{"type":"string","description":"Bulk mail action; validated server-side."},"payload":{"type":"object","additionalProperties":{}}},"additionalProperties":false},"MailInvitePreviewResponse":{"type":"object","properties":{"invite":{"anyOf":[{"$ref":"#/components/schemas/EmailCalendarInvite"},{"type":"null"}]}},"required":["invite"],"additionalProperties":{}},"MailRsvpResponse":{"type":"object","properties":{"rsvp":{"$ref":"#/components/schemas/MailRsvpChoice"},"invite":{"$ref":"#/components/schemas/EmailCalendarInvite"}},"required":["rsvp","invite"],"additionalProperties":{}},"MailRsvpInput":{"type":"object","properties":{"rsvp":{"$ref":"#/components/schemas/MailRsvpChoice"},"comment":{"type":"string"}},"required":["rsvp"],"additionalProperties":false},"EmailAttachmentListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"fileId":{"type":"string","format":"uuid"},"filename":{"type":"string"},"mimeType":{"type":"string"},"sizeBytes":{"type":["integer","null"]},"contentId":{"type":["string","null"]},"disposition":{"type":["string","null"],"enum":["attachment","inline",null]}},"required":["id","fileId","filename","mimeType","sizeBytes","contentId","disposition"]},"MailAttachmentListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailAttachmentListItem"}}},"required":["data"]},"MailAttachmentUrlResponse":{"type":"object","properties":{"url":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"}},"required":["url","filename","mimeType"]},"MailUntrashEmailResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"id":{"type":"string","format":"uuid"},"folder":{"type":"string","description":"The folder the message was restored to — its previous folder, not always inbox."}},"required":["success","id","folder"]},"MailSnoozeEmailResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"snoozed_until":{"type":"string"}},"required":["success","snoozed_until"]},"MailSnoozeInput":{"type":"object","properties":{"until":{"type":"string","description":"ISO-8601 wake-up time."}},"required":["until"],"additionalProperties":false},"MailEmailMarkResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"starred":{"type":"boolean","description":"Present when the request toggled the star."},"snoozed_until":{"type":["string","null"],"description":"Present when the request set or cleared the snooze."},"labels":{"type":"array","items":{"type":"string"},"description":"The label set after the request, when it replaced labels."}},"required":["success"],"additionalProperties":{}},"EmailUpdateInput":{"type":"object","properties":{"read":{"type":"boolean"},"starred":{"type":"boolean"},"labels":{"type":"array","items":{"type":"string"}},"snoozed_until":{"type":["string","null"]}},"additionalProperties":false},"TaskTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"default_status":{"anyOf":[{"$ref":"#/components/schemas/TaskStatus"},{"type":"null"}]},"default_priority":{"anyOf":[{"$ref":"#/components/schemas/TaskPriority"},{"type":"null"}]},"default_assignee_id":{"type":["string","null"],"format":"uuid"},"default_labels":{"type":"array","items":{"type":"string"}},"default_estimate":{"type":["integer","null"]},"default_custom_field_values":{"type":"object","additionalProperties":{}},"created_by":{"type":["string","null"],"format":"uuid"},"sort_order":{"type":["number","null"]},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"creator":{"anyOf":[{"$ref":"#/components/schemas/TaskUserSummary"},{"type":"null"}]}},"required":["id","workspace_id","project_id","name","description","default_status","default_priority","default_assignee_id","default_estimate","created_by","sort_order","created_at","updated_at","creator"],"description":"Reusable task template — seeds a task with default fields."},"TaskStatus":{"type":"string","enum":["todo","in_progress","done","cancelled","blocked"],"description":"System task status category. Drives the built-in board columns."},"TaskPriority":{"type":"string","enum":["urgent","high","medium","low"],"description":"Task priority. Determines SLA timer and sort weight."},"TaskUserSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"],"format":"email"},"avatar_url":{"type":["string","null"]},"type":{"type":"string","enum":["human","agent"]}},"required":["id","display_name","primary_email"],"description":"Compact user reference embedded on task creator/assignee. Avoids forcing the client to do a second lookup for the common name+email+avatar render. `primary_email` may be null for accounts without a verified email; `avatar_url` is null when the user has no avatar (clients render initials)."},"TaskTemplateListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskTemplate"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskTemplateWrappedResponse":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/TaskTemplate"}},"required":["template"]},"TaskTemplateCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"project_id":{"type":["string","null"],"format":"uuid","description":"If set, only project admins + workspace admins can edit. Pass null for workspace-wide."},"default_status":{"anyOf":[{"$ref":"#/components/schemas/TaskStatus"},{"type":"null"}]},"default_priority":{"anyOf":[{"$ref":"#/components/schemas/TaskPriority"},{"type":"null"}]},"default_assignee_id":{"type":["string","null"],"format":"uuid"},"default_labels":{"type":"array","items":{"type":"string"}},"default_estimate":{"type":["integer","null"]},"default_custom_field_values":{"type":"object","additionalProperties":{}},"sort_order":{"type":"number"}},"required":["name"],"additionalProperties":false,"description":"Body of `POST /api/tasks/templates`."},"Task":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/TaskStatus"},"priority":{"$ref":"#/components/schemas/TaskPriority"},"assignee_id":{"type":["string","null"],"format":"uuid"},"creator_id":{"type":"string","format":"uuid"},"due_date":{"type":["string","null"],"format":"date","description":"YYYY-MM-DD"},"start_date":{"type":["string","null"],"format":"date","description":"YYYY-MM-DD. With `due_date`, defines a date range for the task."},"parent_task_id":{"type":["string","null"],"format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid","description":"CRM contact this task is associated with. Auto-logs CRM activities."},"deal_id":{"type":["string","null"],"format":"uuid","description":"CRM deal this task is associated with."},"sort_order":{"type":["number","null"],"description":"Drag-reorder weight. Lower sorts first."},"task_key":{"type":["string","null"],"description":"Workspace-scoped human-readable key like `WS-123`. Stable across renames."},"task_status_id":{"type":["string","null"],"format":"uuid","description":"Custom status ID (overrides system `status` category). When set, the system `status` field is synced from the custom status's category."},"recurrence_rule":{"type":["string","null"],"description":"RRULE string per RFC 5545 (e.g. `FREQ=WEEKLY;BYDAY=MO`). When set, completing the task spawns the next occurrence."},"estimate":{"type":["integer","null"],"description":"Story-point estimate (typically 1, 2, 3, 5, 8, 13). Used in velocity reports."},"estimated_minutes":{"type":["integer","null"],"description":"Time-budget estimate in minutes. Used in workload + analytics reports."},"time_spent_minutes":{"type":["integer","null"],"description":"Sum of time-tracking entries for this task. Auto-updated when time entries are logged or removed."},"custom_field_values":{"type":["object","null"],"additionalProperties":{},"description":"Per-task values keyed by `task_custom_fields.id`. Shape varies by field type (string, number, ISO date, array of option ids, etc.)."},"goal_id":{"type":["string","null"],"format":"uuid","description":"OKR-style goal this task contributes to. Drives goal progress aggregates."},"cycle_id":{"type":["string","null"],"format":"uuid","description":"Sprint/cycle this task is scheduled in."},"first_response_at":{"type":["string","null"],"format":"date-time","description":"Timestamp of the first response (status change off `todo`). Drives the response SLA timer."},"due_date_source":{"$ref":"#/components/schemas/TaskDueDateSource"},"sla":{"anyOf":[{"$ref":"#/components/schemas/TaskSlaSummary"},{"type":"null"}]},"completed_at":{"type":["string","null"],"format":"date-time","description":"Set when status flips to `done` or `cancelled`. Cleared on un-complete."},"archived_at":{"type":["string","null"],"format":"date-time","description":"Soft-archive timestamp. Archived tasks are hidden from default list filters."},"trashed_at":{"type":["string","null"],"format":"date-time","description":"Soft-delete timestamp. Trashed tasks are restorable for 30 days."},"labels":{"type":"array","items":{"$ref":"#/components/schemas/TaskLabelEmbed"},"description":"Labels applied to this task, in display order."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"creator":{"$ref":"#/components/schemas/TaskUserSummary"},"assignee":{"anyOf":[{"$ref":"#/components/schemas/TaskUserSummary"},{"type":"null"}]},"subtask_count":{"type":"integer","description":"Count of direct child tasks (subtasks). Hydrated on list responses."},"comment_count":{"type":"integer","description":"Count of top-level comment threads on this task. Hydrated on list responses."},"subscriber_count":{"type":"integer","description":"Count of users subscribed to this task. Hydrated on list responses."},"subscriber_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"User IDs of subscribers. Echoed on create/update/list so callers avoid a second GET to the subscriptions sub-resource."},"pr_count":{"type":"integer","description":"Count of GitHub PRs linked to this task via the changelog / dev-tools integration."},"latest_pr_status":{"type":["string","null"],"description":"Status of the most-recent linked PR (open / merged / closed)."},"subscribers":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]},"avatar_url":{"type":["string","null"]},"reason":{"type":"string"}},"required":["user_id","display_name","primary_email","reason"]},"description":"Users subscribed to this task (notified on changes). Returned on single-task GET to avoid forcing a second round-trip to the subscriptions sub-resource."}},"required":["id","title","status","priority","creator_id","created_at","updated_at"],"description":"Full task entity as returned by `GET /api/tasks/:id`."},"TaskDueDateSource":{"type":"string","enum":["manual","sla"],"description":"Who set the task's due date. `manual` = user-entered; `sla` = auto-set by the priority SLA policy. Persists across updates so SLA bumps don't overwrite explicit edits."},"TaskSlaSummary":{"type":"object","properties":{"response":{"anyOf":[{"$ref":"#/components/schemas/TaskSlaCheckpoint"},{"type":"null"}]},"resolution":{"anyOf":[{"$ref":"#/components/schemas/TaskSlaCheckpoint"},{"type":"null"}]}},"required":["response","resolution"],"description":"SLA tracker. `null` legs mean the SLA timer hasn't been initialized for this task."},"TaskSlaCheckpoint":{"type":"object","properties":{"status":{"type":"string","enum":["on_track","at_risk","breached","achieved","failed"]},"elapsed_minutes":{"type":"integer"},"target_minutes":{"type":"integer"},"remaining_minutes":{"type":"integer"},"deadline":{"type":"string","format":"date-time"}},"required":["status","elapsed_minutes","target_minutes","remaining_minutes","deadline"],"description":"One leg of the SLA tracker: either response (time to first reply / status change) or resolution (time to done)."},"TaskLabelEmbed":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid","description":"`null` for workspace-level labels; project UUID for project-scoped labels."},"name":{"type":"string"},"group_name":{"type":["string","null"]},"color":{"type":"string"},"icon":{"type":["string","null"]}},"required":["id","name","group_name","color","icon"],"description":"Label as it appears embedded on a task response."},"TaskCreateResponse":{"type":"object","properties":{"task":{"$ref":"#/components/schemas/Task"}},"required":["task"],"description":"Response body for `POST /api/tasks`. Wrapped in `{ task }` for legacy compatibility."},"TaskTemplateApplyInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"description":{"type":"string"},"status":{"$ref":"#/components/schemas/TaskStatus"},"priority":{"$ref":"#/components/schemas/TaskPriority"},"assignee_id":{"type":"string","format":"uuid"},"estimate":{"type":"integer"},"project_id":{"type":"string","format":"uuid"},"due_date":{"type":"string","format":"date"},"parent_task_id":{"type":"string","format":"uuid"},"custom_field_values":{"type":"object","additionalProperties":{}}},"required":["title"],"additionalProperties":false,"description":"Body of `POST /api/tasks/templates/:templateId/apply` — overrides applied on top of template defaults."},"TaskTemplateUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"project_id":{"type":["string","null"],"format":"uuid","description":"If set, only project admins + workspace admins can edit. Pass null for workspace-wide."},"default_status":{"anyOf":[{"$ref":"#/components/schemas/TaskStatus"},{"type":"null"}]},"default_priority":{"anyOf":[{"$ref":"#/components/schemas/TaskPriority"},{"type":"null"}]},"default_assignee_id":{"type":["string","null"],"format":"uuid"},"default_labels":{"type":"array","items":{"type":"string"}},"default_estimate":{"type":["integer","null"]},"default_custom_field_values":{"type":"object","additionalProperties":{}},"sort_order":{"type":"number"}},"additionalProperties":false,"description":"Body of `PATCH /api/tasks/templates/:templateId`."},"TaskSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"TaskExportResponse":{"type":"object","properties":{"data":{"type":"array","items":{}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskBatchListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskStatusEntity":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"},"color":{"type":["string","null"]},"icon":{"type":["string","null"]},"sort_order":{"type":"number"},"category":{"$ref":"#/components/schemas/TaskStatusCategory"},"is_default":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time"}},"required":["id","workspace_id","project_id","name","color","icon","sort_order","category","created_at"],"description":"Custom task status (workspace- or project-scoped)."},"TaskStatusCategory":{"type":"string","enum":["backlog","triage","todo","in_progress","in_review","done","cancelled","blocked"],"description":"Category of a custom task status. Maps a workspace-defined status name (e.g. 'Awaiting QA') onto a system bucket so list filtering keeps working."},"TaskStatusEntityListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskStatusEntity"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskStatusEntityWrappedResponse":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/TaskStatusEntity"}},"required":["status"]},"TaskStatusCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"category":{"$ref":"#/components/schemas/TaskStatusCategory"},"color":{"type":"string","description":"Hex color (e.g. '#6B7280')."},"icon":{"type":"string"},"sort_order":{"type":"number"},"project_id":{"type":"string","format":"uuid","description":"If set, the status is scoped to one project; otherwise workspace-wide."}},"required":["name","category"],"additionalProperties":false,"description":"Body of `POST /api/tasks/statuses`."},"ReorderItemsInput":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sort_order":{"type":"number"}},"required":["id","sort_order"],"additionalProperties":false},"minItems":1}},"required":["items"],"additionalProperties":false,"description":"Body of `POST /api/tasks/statuses/reorder` and `POST /api/tasks/custom-fields/reorder`."},"TaskStatusId":{"type":"string","format":"uuid"},"TaskStatusUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"color":{"type":"string"},"icon":{"type":["string","null"]},"sort_order":{"type":"number"},"category":{"$ref":"#/components/schemas/TaskStatusCategory"},"is_default":{"type":"boolean","description":"Set true to make this the workspace/project default status."}},"additionalProperties":false,"description":"Body of `PATCH /api/tasks/statuses/:statusId`."},"TaskCustomField":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"},"field_type":{"$ref":"#/components/schemas/TaskCustomFieldType"},"options":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"color":{"type":"string"}},"required":["value"]}],"description":"An option for `select` / `multi_select` custom fields. Strings are shorthand for `{ value: <s>, label: <s> }`."}},"required":{"type":"boolean"},"sort_order":{"type":"number"},"created_at":{"type":["string","null"],"format":"date-time"}},"required":["id","workspace_id","project_id","name","field_type","options","required","sort_order","created_at"],"description":"A workspace- or project-scoped custom field definition for tasks."},"TaskCustomFieldType":{"type":"string","enum":["text","number","select","multi_select","date","checkbox","url"],"description":"Type of a task custom field. Controls value editor in UI and validation rules. `select`/`multi_select` require a non-empty `options` list."},"TaskCustomFieldListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskCustomField"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskCustomFieldWrappedResponse":{"type":"object","properties":{"field":{"$ref":"#/components/schemas/TaskCustomField"}},"required":["field"]},"TaskCustomFieldCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"field_type":{"$ref":"#/components/schemas/TaskCustomFieldType"},"options":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"color":{"type":"string"}},"required":["value"],"additionalProperties":false}],"description":"An option for `select` / `multi_select` custom fields. Strings are shorthand for `{ value: <s>, label: <s> }`."},"description":"Required when `field_type` is `select` or `multi_select`."},"required":{"type":"boolean"},"sort_order":{"type":"number"},"project_id":{"type":"string","format":"uuid"}},"required":["name","field_type"],"additionalProperties":false,"description":"Body of `POST /api/tasks/custom-fields`."},"TaskCustomFieldUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"field_type":{"$ref":"#/components/schemas/TaskCustomFieldType"},"options":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"color":{"type":"string"}},"required":["value"],"additionalProperties":false}],"description":"An option for `select` / `multi_select` custom fields. Strings are shorthand for `{ value: <s>, label: <s> }`."}},"required":{"type":"boolean"},"sort_order":{"type":"number"}},"additionalProperties":false,"description":"Body of `PATCH /api/tasks/custom-fields/:fieldId`."},"TaskLabel":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid","description":"`null` for workspace-level labels visible to every project; set to a project UUID for project-scoped labels."},"name":{"type":"string"},"group_name":{"type":["string","null"]},"color":{"type":"string"},"icon":{"type":["string","null"]},"sort_order":{"type":"number"},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"}},"required":["id","workspace_id","project_id","name","group_name","color","icon","sort_order","created_at","updated_at"],"description":"Task label. Workspace-scoped when `project_id` is null; project-scoped otherwise. Optional `group_name` clusters labels in pickers."},"TaskLabelListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskLabel"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskLabelWrappedResponse":{"type":"object","properties":{"label":{"$ref":"#/components/schemas/TaskLabel"}},"required":["label"]},"TaskLabelCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"project_id":{"type":["string","null"],"format":"uuid","description":"Set to scope this label to a single project; omit (or null) for a workspace-level label."},"group_name":{"type":["string","null"]},"color":{"type":"string","description":"Hex color (e.g. '#6B7280')."},"icon":{"type":"string"},"sort_order":{"type":"number"}},"required":["name"],"additionalProperties":false,"description":"Body of `POST /api/tasks/labels`."},"TaskLabelId":{"type":"string","format":"uuid"},"TaskLabelUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"group_name":{"type":["string","null"]},"color":{"type":"string"},"icon":{"type":["string","null"]},"sort_order":{"type":"number"}},"additionalProperties":false,"description":"Body of `PATCH /api/tasks/labels/:labelId`."},"TaskSlaThresholdEntry":{"type":"object","properties":{"response":{"type":"integer","exclusiveMinimum":0},"resolution":{"type":"integer","exclusiveMinimum":0}},"required":["response","resolution"]},"TaskSlaThresholds":{"type":"object","properties":{"urgent":{"$ref":"#/components/schemas/TaskSlaThresholdEntry"},"high":{"$ref":"#/components/schemas/TaskSlaThresholdEntry"},"medium":{"$ref":"#/components/schemas/TaskSlaThresholdEntry"},"low":{"$ref":"#/components/schemas/TaskSlaThresholdEntry"}},"required":["urgent","high","medium","low"],"description":"SLA response + resolution thresholds in minutes, per task priority."},"TaskSlaAxisMetrics":{"type":"object","properties":{"compliance_rate":{"type":"number"},"avg_minutes":{"type":"number"},"on_track":{"type":"integer"},"at_risk":{"type":"integer"},"breached":{"type":"integer"},"achieved":{"type":"integer"},"failed":{"type":"integer"}},"required":["compliance_rate","avg_minutes","on_track","at_risk","breached","achieved","failed"]},"TaskSlaDashboard":{"type":"object","properties":{"total_tasks":{"type":"integer"},"tasks_with_sla":{"type":"integer"},"response":{"$ref":"#/components/schemas/TaskSlaAxisMetrics"},"resolution":{"$ref":"#/components/schemas/TaskSlaAxisMetrics"}},"required":["total_tasks","tasks_with_sla","response","resolution"],"description":"Aggregate SLA metrics for the workspace, split by response and resolution."},"TaskView":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"created_by":{"type":"string","format":"uuid"},"name":{"type":"string"},"icon":{"type":["string","null"]},"filters":{"description":"Free-form filter JSON; structure matches the list query params."},"default_layout":{"type":["string","null"]},"default_group_by":{"type":["string","null"]},"default_sort_by":{"type":["string","null"]},"default_sort_direction":{"type":["string","null"]},"is_shared":{"type":["boolean","null"]},"is_default":{"type":["boolean","null"]},"sort_order":{"type":["number","null"]},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"}},"required":["id","workspace_id","project_id","created_by","name","icon","default_layout","default_group_by","default_sort_by","default_sort_direction","is_shared","is_default","sort_order","created_at","updated_at"],"description":"Saved task view (filter + layout). `is_shared: true` means visible to the whole workspace."},"TaskViewListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskView"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskViewWrappedResponse":{"type":"object","properties":{"view":{"$ref":"#/components/schemas/TaskView"}},"required":["view"]},"TaskViewCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"icon":{"type":"string"},"project_id":{"type":"string","format":"uuid"},"filters":{},"default_layout":{"type":"string"},"default_group_by":{"type":"string"},"default_sort_by":{"type":"string"},"default_sort_direction":{"type":"string"},"is_shared":{"type":"boolean"},"sort_order":{"type":"number"}},"required":["name"],"additionalProperties":false,"description":"Body of `POST /api/tasks/views`."},"TaskViewUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"icon":{"type":"string"},"project_id":{"type":"string","format":"uuid"},"filters":{},"default_layout":{"type":"string"},"default_group_by":{"type":"string"},"default_sort_by":{"type":"string"},"default_sort_direction":{"type":"string"},"is_shared":{"type":"boolean"},"sort_order":{"type":"number"}},"additionalProperties":false,"description":"Body of `PATCH /api/tasks/views/:viewId`."},"TaskViewLayoutPrefs":{"type":"object","properties":{"view_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"layout":{"type":["string","null"]},"group_by":{"type":["string","null"]},"sort_by":{"type":["string","null"]},"sort_direction":{"type":["string","null"]},"columns":{"type":["array","null"],"items":{"type":"string"}},"board_swimlanes":{"type":["string","null"]},"wip_limits":{"type":["object","null"],"additionalProperties":{"type":"number"}},"show_completed":{"type":["boolean","null"]},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"}},"required":["view_id","user_id","layout","group_by","sort_by","sort_direction","columns","board_swimlanes","wip_limits","show_completed"],"description":"Per-user, per-project view layout preferences."},"TaskViewLayoutGetResponse":{"type":"object","properties":{"layout":{"$ref":"#/components/schemas/TaskViewLayoutPrefs"},"source":{"type":"string","enum":["user","view_defaults"]}},"required":["layout","source"]},"TaskViewLayoutUpdateResponse":{"type":"object","properties":{"layout":{"$ref":"#/components/schemas/TaskViewLayoutPrefs"},"source":{"type":"string","enum":["user"]}},"required":["layout","source"]},"TaskViewLayoutUpdateInput":{"type":"object","properties":{"layout":{"type":"string"},"group_by":{"type":"string"},"sort_by":{"type":"string"},"sort_direction":{"type":"string"},"columns":{"type":["array","null"],"items":{"type":"string"}},"board_swimlanes":{"type":["string","null"]},"wip_limits":{"type":["object","null"],"additionalProperties":{"type":"number"}},"show_completed":{"type":"boolean"},"project_id":{"type":["string","null"],"format":"uuid"}},"additionalProperties":false,"description":"Body of `PATCH /api/tasks/views/:viewId/layout`."},"TaskSubscribedIdsEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"type":"string","format":"uuid"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskBurndownPoint":{"type":"object","properties":{"date":{"type":"string","format":"date"},"totalScope":{"type":"integer"},"completed":{"type":"integer"},"remaining":{"type":"integer"}},"required":["date","totalScope","completed","remaining"]},"TaskVelocityPoint":{"type":"object","properties":{"weekStart":{"type":"string","format":"date"},"completed":{"type":"integer"},"estimatedMinutes":{"type":"integer"}},"required":["weekStart","completed","estimatedMinutes"]},"TaskAnalytics":{"type":"object","properties":{"burndown":{"type":"array","items":{"$ref":"#/components/schemas/TaskBurndownPoint"}},"velocity":{"type":"array","items":{"$ref":"#/components/schemas/TaskVelocityPoint"}},"summary":{"type":"object","properties":{"totalTasks":{"type":"integer"},"completedTasks":{"type":"integer"},"totalEstimatedMinutes":{"type":"integer"},"totalSpentMinutes":{"type":"integer"}},"required":["totalTasks","completedTasks","totalEstimatedMinutes","totalSpentMinutes"]}},"required":["burndown","velocity","summary"],"description":"Response body for `GET /api/tasks/analytics`."},"TaskWorkloadAssignee":{"type":"object","properties":{"userId":{"type":["string","null"],"format":"uuid"},"displayName":{"type":"string"},"avatarUrl":{"type":["string","null"]},"totalTasks":{"type":"integer"},"todoTasks":{"type":"integer"},"inProgressTasks":{"type":"integer"},"doneTasks":{"type":"integer"},"cancelledTasks":{"type":"integer"},"openTasks":{"type":"integer"},"overdueTasks":{"type":"integer"},"dueSoonTasks":{"type":"integer"},"estimatedMinutes":{"type":"integer"},"spentMinutes":{"type":"integer"},"capacityMinutes":{"type":"integer"},"utilization":{"type":"number","description":"0..1+; >1 means overallocated."},"byPriority":{"type":"object","properties":{"urgent":{"type":"integer"},"high":{"type":"integer"},"medium":{"type":"integer"},"low":{"type":"integer"}},"required":["urgent","high","medium","low"]}},"required":["userId","displayName","avatarUrl","totalTasks","todoTasks","inProgressTasks","doneTasks","cancelledTasks","openTasks","overdueTasks","dueSoonTasks","estimatedMinutes","spentMinutes","capacityMinutes","utilization","byPriority"]},"TaskWorkload":{"type":"object","properties":{"assignees":{"type":"array","items":{"$ref":"#/components/schemas/TaskWorkloadAssignee"}},"summary":{"type":"object","properties":{"totalAssignees":{"type":"integer"},"totalOpenTasks":{"type":"integer"},"totalEstimatedMinutes":{"type":"integer"},"overallocated":{"type":"integer","description":"Count of assignees with utilization > 1."},"capacityHoursPerWeek":{"type":"number"}},"required":["totalAssignees","totalOpenTasks","totalEstimatedMinutes","overallocated","capacityHoursPerWeek"]}},"required":["assignees","summary"],"description":"Response body for `GET /api/tasks/workload`."},"TaskGoal":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"title":{"type":"string"},"description":{"type":["string","null"]},"icon":{"type":["string","null"]},"color":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/TaskGoalStatus"},"target_date":{"type":["string","null"],"format":"date"},"owner_id":{"type":["string","null"],"format":"uuid"},"sort_order":{"type":"number"},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"owner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"],"format":"email"}},"required":["id","display_name","primary_email"]},"progress":{"type":"object","properties":{"totalTasks":{"type":"integer"},"doneTasks":{"type":"integer"},"inProgressTasks":{"type":"integer"},"todoTasks":{"type":"integer"},"cancelledTasks":{"type":"integer"},"percentage":{"type":"number"}},"required":["totalTasks","doneTasks","inProgressTasks","todoTasks","cancelledTasks","percentage"],"description":"Aggregate task counts by status, plus a 0-100 percentage of tasks completed."}},"required":["id","workspace_id","project_id","title","description","icon","color","status","target_date","owner_id","sort_order","created_at","updated_at","owner","progress"],"description":"OKR-style goal entity. Tasks link to one goal via `tasks.goal_id`."},"TaskGoalStatus":{"type":"string","enum":["active","completed","archived"],"description":"Lifecycle state of an OKR-style goal."},"TaskGoalListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskGoal"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskGoalWrappedResponse":{"type":"object","properties":{"goal":{"$ref":"#/components/schemas/TaskGoal"}},"required":["goal"]},"TaskGoalCreateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"description":{"type":"string"},"icon":{"type":"string"},"color":{"type":"string","description":"Hex color. Defaults to '#405EF2' (brand blue)."},"status":{"type":"string","enum":["active","completed","archived"],"description":"Defaults to 'active'."},"start_date":{"type":"string","format":"date"},"target_date":{"type":"string","format":"date"},"project_id":{"type":"string","format":"uuid"},"owner_id":{"type":"string","format":"uuid"},"sort_order":{"type":"number"}},"required":["title"],"additionalProperties":false,"description":"Body of `POST /api/tasks/goals`."},"TaskGoalUpdateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"description":{"type":["string","null"]},"icon":{"type":["string","null"]},"color":{"type":"string"},"status":{"$ref":"#/components/schemas/TaskGoalStatus"},"start_date":{"type":["string","null"],"format":"date"},"target_date":{"type":["string","null"],"format":"date"},"project_id":{"type":["string","null"],"format":"uuid"},"owner_id":{"type":["string","null"],"format":"uuid"},"sort_order":{"type":"number"}},"additionalProperties":false,"description":"Body of `PATCH /api/tasks/goals/:goalId`."},"TaskGoalTaskSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"task_key":{"type":["string","null"]},"title":{"type":"string"},"status":{"$ref":"#/components/schemas/TaskStatus"},"priority":{"$ref":"#/components/schemas/TaskPriority"},"assignee_id":{"type":["string","null"],"format":"uuid"},"due_date":{"type":["string","null"],"format":"date"}},"required":["id","task_key","title","status","priority","assignee_id","due_date"],"description":"Lightweight task summary returned by `GET /api/tasks/goals/:goalId/tasks`."},"TaskGoalTaskSummaryListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskGoalTaskSummary"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskBulkUpdateResponse":{"type":"object","properties":{"updated":{"type":"integer"},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Task"}}},"required":["updated","tasks"]},"TaskBulkUpdateInput":{"type":"object","properties":{"task_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100,"description":"Tasks to update. Both `task_ids` and `ids` are accepted by the route."},"ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100,"description":"Alias for `task_ids`."},"status":{"$ref":"#/components/schemas/TaskStatus"},"task_status_id":{"type":["string","null"],"format":"uuid"},"priority":{"$ref":"#/components/schemas/TaskPriority"},"assignee_id":{"type":["string","null"],"format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"due_date":{"type":["string","null"],"format":"date"},"start_date":{"type":["string","null"],"format":"date"},"goal_id":{"type":["string","null"],"format":"uuid"},"estimate":{"type":["integer","null"]},"cycle_id":{"type":["string","null"],"format":"uuid"},"add_label_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"remove_label_ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"additionalProperties":false,"description":"Body of `POST /api/tasks/bulk/update`. Unknown keys are rejected — a mistyped field must fail closed, never silently no-op."},"TaskBulkDeleteResponse":{"type":"object","properties":{"deleted":{"type":"integer"}},"required":["deleted"]},"TaskBulkDeleteInput":{"type":"object","properties":{"task_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100},"ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100,"description":"Alias for `task_ids`."}},"additionalProperties":false,"description":"Body of `POST /api/tasks/bulk/delete`. Provide `task_ids` (or its alias `ids`)."},"TaskBulkArchiveResponse":{"type":"object","properties":{"archived":{"type":"integer"}},"required":["archived"]},"TaskBulkArchiveInput":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100}},"required":["ids"],"additionalProperties":false,"description":"Body of `POST /api/tasks/bulk/archive`."},"TaskClearCompletedResponse":{"type":"object","properties":{"cleared":{"type":"integer"}},"required":["cleared"]},"TaskClearCompletedInput":{"type":"object","properties":{"project_id":{"type":"string","format":"uuid","description":"Clear completed tasks within this project."},"all_projects":{"type":"boolean","description":"Explicit opt-in to clear completed tasks across ALL projects in the workspace. Destructive — must be `true` to clear workspace-wide; never the default."}},"additionalProperties":false,"description":"Body of `POST /api/tasks/clear`."},"TaskInboxCountResponse":{"type":"object","properties":{"count":{"type":"integer","description":"Untriaged tasks assigned to the caller — the sidebar inbox badge."},"triage_count":{"type":"integer","description":"Always 0 at present. Reserved for the projects-in-triage half of the bucket, which is not counted yet."}},"required":["count","triage_count"]},"TaskMaintenanceCloseResponse":{"type":"object","properties":{"closed_count":{"type":"integer"},"task_ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["closed_count","task_ids"]},"TaskMaintenanceArchiveResponse":{"type":"object","properties":{"archived_count":{"type":"integer"},"task_ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["archived_count","task_ids"]},"TaskTimeEntry":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"task_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"started_at":{"type":"string","format":"date-time"},"stopped_at":{"type":["string","null"],"format":"date-time"},"duration_minutes":{"type":["integer","null"]},"description":{"type":["string","null"]},"worked_at":{"type":["string","null"],"format":"date","description":"Date (YYYY-MM-DD) the work was performed, or null for timer-started entries."},"created_at":{"type":["string","null"],"format":"date-time"},"user_name":{"type":["string","null"],"description":"Hydrated on list endpoints for display; omitted on single-entry returns."}},"required":["id","task_id","user_id","started_at","stopped_at","duration_minutes","description","created_at"],"description":"Time tracking entry for a task. Open entries have `stopped_at: null`."},"TaskActiveTimerResponse":{"type":"object","properties":{"timer":{"anyOf":[{"$ref":"#/components/schemas/TaskTimeEntry"},{"type":"null"}]}},"required":["timer"],"description":"Returns the user's currently-running timer, or `null` if none."},"TaskFavorite":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"resource_type":{"type":"string","enum":["view","project"]},"resource_id":{"type":"string","format":"uuid"},"sort_order":{"type":["number","null"]},"created_at":{"type":["string","null"],"format":"date-time"}},"required":["id","resource_type","resource_id","sort_order","created_at"],"description":"Sidebar favorite — pins a view or project for the current user."},"TaskFavoriteListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskFavorite"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskFavoriteCreateInput":{"type":"object","properties":{"resource_type":{"type":"string","enum":["view","project"]},"resource_id":{"type":"string","format":"uuid"}},"required":["resource_type","resource_id"],"additionalProperties":false,"description":"Body of `POST /api/tasks/favorites`."},"TaskFavoriteRemoveInput":{"type":"object","properties":{"resource_type":{"type":"string"},"resource_id":{"type":"string"}},"additionalProperties":false,"description":"Body of `DELETE /api/tasks/favorites` — matched on resource_type + resource_id."},"TaskFavoriteReorderInput":{"type":"object","properties":{"ordered_ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["ordered_ids"],"additionalProperties":false,"description":"Body of `PUT /api/tasks/favorites/reorder`."},"TaskKeyResolveResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"task_key":{"type":["string","null"]}},"required":["id","task_key"]},"TaskRelationsBatchEdge":{"type":"object","properties":{"source_task_id":{"type":"string","format":"uuid"},"target_task_id":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["source_task_id","target_task_id","type"]},"TaskRelationsBatchEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskRelationsBatchEdge"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskTrashListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"],"description":"Response body for `GET /api/tasks/trash`."},"TaskListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"total":{"type":"integer"},"status_counts":{"type":"object","additionalProperties":{"type":"integer"},"description":"Count per system status across the whole filter, not just this page."},"custom_status_counts":{"type":"object","additionalProperties":{"type":"integer"},"description":"Count per custom status id across the whole filter, not just this page."},"blocked_task_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"IDs of tasks in `data` whose dependencies are not all done."},"archived_count":{"type":"integer","description":"Count of archived tasks matching the filter (regardless of `showArchived`)."},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","description":"Echo of the request `limit` (offset mode only)."},"offset":{"type":"integer","description":"Echo of the request `offset` (offset mode only)."}},"required":["data","total","status_counts","custom_status_counts","blocked_task_ids","archived_count","has_more"],"description":"Response body for `GET /api/tasks`."},"TaskListSort":{"type":"string","enum":["updated_at","sort_order","created_at","due_date","priority"],"description":"Sort order for `GET /api/tasks`. `updated_at` (recently-touched first) is the default; `sort_order` for board / drag-reorder; `created_at` for chronology; `due_date` for deadline proximity; `priority` for urgency ranking."},"TaskCreateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":255,"description":"Task title. Required. Max 255 chars; trimmed before insert."},"description":{"type":"string","description":"Markdown body. Rendered with the standard task-card markdown subset."},"status":{"type":"string","enum":["todo","in_progress","done","cancelled","blocked"],"description":"Initial status. Defaults to `todo`. If `task_status_id` is also set, that takes precedence and `status` is overridden by the custom status's category."},"task_status_id":{"type":"string","format":"uuid","description":"Custom status ID; overrides `status` category."},"priority":{"type":"string","enum":["urgent","high","medium","low"],"description":"Defaults to `medium`."},"assignee_id":{"type":"string","format":"uuid","description":"User to assign the task to. Must be in the caller's workspace (403 otherwise). Omit for unassigned."},"due_date":{"type":"string","format":"date","description":"ISO 8601 date (YYYY-MM-DD). If unset and a `priority` is given, the SLA policy auto-sets a due date and stamps `due_date_source: 'sla'`."},"start_date":{"type":"string","format":"date","description":"ISO 8601 date (YYYY-MM-DD); with `due_date` defines a date range."},"parent_task_id":{"type":"string","format":"uuid","description":"Parent task for subtasks. Omit for top-level tasks."},"project_id":{"type":"string","format":"uuid"},"contact_id":{"type":"string","format":"uuid","description":"Link the task to a CRM contact; auto-logs a CRM activity row."},"deal_id":{"type":"string","format":"uuid","description":"Link the task to a CRM deal."},"sort_order":{"type":"number","description":"Drag-reorder weight. Lower sorts first."},"recurrence_rule":{"type":"string","description":"RFC 5545 RRULE string. When set, completing the task spawns the next occurrence."},"estimate":{"type":"integer","description":"Story-point estimate (typically 1, 2, 3, 5, 8, 13)."},"estimated_minutes":{"type":"integer","exclusiveMinimum":0,"description":"Time-budget estimate in minutes."},"custom_field_values":{"type":"object","additionalProperties":{},"description":"Per-task custom-field values keyed by `task_custom_fields.id`."},"goal_id":{"type":["string","null"],"format":"uuid","description":"Link the task to an OKR-style goal."},"cycle_id":{"type":"string","format":"uuid","description":"Sprint/cycle this task is scheduled in."},"label_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Labels to assign at create time. Each ID must reference a label in the caller's workspace (404 otherwise)."},"subscriber_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Users to subscribe to the task at create time so they receive update notifications. Each must be a member of the caller's workspace; IDs outside the workspace are silently skipped. Use to link a bug reporter to the filed task."}},"required":["title"],"additionalProperties":false,"description":"Body of `POST /api/tasks`. Captures the union of fields any surface accepts."},"TaskId":{"type":"string","format":"uuid"},"TaskLabelAssignInput":{"type":"object","properties":{"label_id":{"type":"string","format":"uuid"}},"required":["label_id"],"additionalProperties":false},"TaskSubscription":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"reason":{"type":"string","description":"Why subscribed: 'manual' | 'creator' | 'assigned' | 'commented' | …"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"avatar_url":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time"}},"required":["task_id","user_id","reason","display_name","primary_email","avatar_url","created_at"],"description":"Subscription entry for a task — drives notification fan-out."},"TaskSubscriptionListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskSubscription"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskSubscriptionWrappedResponse":{"type":"object","properties":{"subscription":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"reason":{"type":"string","description":"Why subscribed: 'manual' | 'creator' | 'assigned' | 'commented' | …"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"avatar_url":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time"}}}},"required":["subscription"]},"TaskSubscribeBody":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid","description":"Subscribe another user who has access to the task. Omit (send `{}`) to subscribe the caller."}},"additionalProperties":false},"TaskUnsubscribeResponse":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]},"TaskSubscriptionStatusResponse":{"type":"object","properties":{"subscribed":{"type":"boolean"},"reason":{"type":["string","null"]}},"required":["subscribed","reason"]},"TaskPrLink":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"external_id":{"type":["string","null"]},"external_url":{"type":["string","null"]},"title":{"type":["string","null"]},"status":{"type":"string","description":"'open' | 'merged' | 'closed' (defaults to 'open')."},"branch":{"type":["string","null"]},"number":{"type":["number","null"]},"repo":{"type":["string","null"]},"ci_status":{"type":["string","null"]},"approvers":{"type":"array","items":{"type":"string"}},"created_at":{"type":["string","null"],"format":"date-time"}},"required":["id","external_id","external_url","title","status","branch","number","repo","ci_status","approvers","created_at"],"description":"Pull request linked to a task via the integration-links service."},"TaskPrLinksResponse":{"type":"object","properties":{"pr_links":{"type":"array","items":{"$ref":"#/components/schemas/TaskPrLink"}}},"required":["pr_links"]},"TaskListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskComment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"task_id":{"type":"string","format":"uuid"},"parent_id":{"type":["string","null"],"format":"uuid"},"content":{"type":"string"},"resolved":{"type":["boolean","null"]},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"author":{"anyOf":[{"$ref":"#/components/schemas/TaskCommentAuthor"},{"type":"null"}]},"reactions":{"type":"array","items":{"$ref":"#/components/schemas/CommentReaction"}},"replies":{"type":"array","items":{"$ref":"#/components/schemas/TaskComment"}}},"required":["id","task_id","content","resolved","created_at","updated_at","author","replies"],"description":"Threaded task comment. Top-level comments have `parent_id: null` and carry their replies inline; reply comments carry an empty `replies` array."},"TaskCommentAuthor":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"],"format":"email"}},"required":["id","display_name","primary_email"],"description":"Comment author summary. `primary_email` is the user's verified primary email (may be null for legacy accounts that haven't re-verified)."},"TaskCommentListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskComment"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskCommentCreateInput":{"type":"object","properties":{"content":{"type":"string","minLength":1,"description":"Markdown body. Min 1 char after trim."},"parent_id":{"type":"string","format":"uuid","description":"Parent comment ID for replies. Omit for top-level comments."}},"required":["content"],"additionalProperties":false,"description":"Body of `POST /api/tasks/:id/comments`."},"TaskCommentUpdateInput":{"type":"object","properties":{"content":{"type":"string","minLength":1},"resolved":{"type":"boolean","description":"Mark the comment thread resolved/unresolved."}},"additionalProperties":false,"description":"Body of `PATCH /api/tasks/:id/comments/:commentId`."},"TaskTimeEntryWrappedResponse":{"type":"object","properties":{"entry":{"$ref":"#/components/schemas/TaskTimeEntry"}},"required":["entry"]},"TaskTimeEntryListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskTimeEntry"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskTimeEntryCreateInput":{"type":"object","properties":{"duration_minutes":{"type":"integer","minimum":1,"description":"Duration in minutes. Manual entries only — timer auto-fills this on stop."},"minutes":{"type":"integer","minimum":1},"description":{"type":"string"},"worked_at":{"type":"string","format":"date","description":"ISO 8601 date (YYYY-MM-DD) the work was performed. Defaults to today when omitted."}},"additionalProperties":false,"description":"Body of `POST /api/tasks/:id/time-entries` (manual entry)."},"TaskActivityEntry":{"type":"object","properties":{"id":{"type":"integer","description":"BIGSERIAL row id from `audit_log`."},"task_id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"action":{"type":"string"},"old_value":{},"new_value":{},"metadata":{"type":["object","null"],"additionalProperties":{}},"created_at":{"type":["string","null"],"format":"date-time"},"user_display_name":{"type":["string","null"]},"user_avatar_url":{"type":["string","null"]}},"required":["id","task_id","user_id","action","metadata","created_at","user_display_name","user_avatar_url"],"description":"One audit-log row for a task (status change, assignment, comment, etc.)."},"TaskActivityEntryListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskActivityEntry"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskRelation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source_task_id":{"type":"string","format":"uuid"},"target_task_id":{"type":"string","format":"uuid"},"type":{"type":"string","description":"'related' | 'blocking' | 'blocked_by' | 'duplicate'"},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"],"format":"date-time"},"target_task":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string"},"priority":{"type":["string","null"]},"task_status_id":{"type":["string","null"],"format":"uuid"}},"required":["id","title","status","priority","task_status_id"]}},"required":["id","source_task_id","target_task_id","type","created_by","created_at","target_task"],"description":"Edge in the task-relations graph. `blocking`/`blocked_by` pairs are auto-mirrored."},"TaskRelationListEnvelope":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskRelation"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskRelationCreateWrappedResponse":{"type":"object","properties":{"relation":{"$ref":"#/components/schemas/TaskRelation"},"merged":{"type":"boolean"}},"required":["relation","merged"]},"TaskRelationCreateInput":{"type":"object","properties":{"target_task_id":{"type":"string","format":"uuid"},"type":{"$ref":"#/components/schemas/TaskRelationType"},"mark_as_duplicate":{"type":"boolean","description":"When `type=duplicate`: also cancel the source task and add a system comment."}},"required":["target_task_id","type"],"additionalProperties":false,"description":"Body of `POST /api/tasks/:id/relations`."},"TaskRelationType":{"type":"string","enum":["related","blocking","blocked_by","duplicate"]},"TaskRestoreResponse":{"type":"object","properties":{"task":{"$ref":"#/components/schemas/Task"}},"required":["task"]},"TaskDuplicateResponse":{"type":"object","properties":{"task":{"$ref":"#/components/schemas/Task"}},"required":["task"]},"TaskAttachmentItem":{"type":"object","properties":{"id":{"type":"string"},"task_id":{"type":"string"},"file_id":{"type":"string"},"added_by":{"type":["string","null"]},"created_at":{"type":["string","null"]},"file":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"mime_type":{"type":["string","null"]},"size_bytes":{"type":["number","null"]}},"required":["id","name","mime_type","size_bytes"]}},"required":["id","task_id","file_id","added_by","created_at","file"]},"TaskAttachmentListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaskAttachmentItem"}},"total":{"type":"number"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"TaskAttachmentResponse":{"type":"object","properties":{"attachment":{"$ref":"#/components/schemas/TaskAttachmentItem"}},"required":["attachment"]},"TaskAttachmentInput":{"type":"object","properties":{"file_id":{"type":"string","format":"uuid","description":"Drive file ID to attach"}},"required":["file_id"],"additionalProperties":false},"TaskWrappedResponse":{"type":"object","properties":{"task":{"$ref":"#/components/schemas/Task"}},"required":["task"]},"TaskUpdateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":255},"description":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/TaskStatus"},"task_status_id":{"type":["string","null"],"format":"uuid"},"priority":{"$ref":"#/components/schemas/TaskPriority"},"assignee_id":{"type":["string","null"],"format":"uuid"},"due_date":{"type":["string","null"],"format":"date"},"due_date_source":{"type":"string","enum":["manual","sla"],"description":"Defaults to `manual` when `due_date` changes through this update. Set explicitly to `sla` to mark a system-set due date."},"start_date":{"type":["string","null"],"format":"date"},"parent_task_id":{"type":["string","null"],"format":"uuid"},"project_id":{"type":["string","null"],"format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid"},"deal_id":{"type":["string","null"],"format":"uuid"},"sort_order":{"type":"number"},"recurrence_rule":{"type":["string","null"]},"estimate":{"type":["integer","null"]},"estimated_minutes":{"type":["integer","null"]},"time_spent_minutes":{"type":["integer","null"],"description":"Manual override; usually auto-managed by time entries."},"custom_field_values":{"type":"object","additionalProperties":{}},"goal_id":{"type":["string","null"],"format":"uuid"},"cycle_id":{"type":["string","null"],"format":"uuid"},"subscriber_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Users to subscribe to this task so they receive update notifications. Additive — existing subscribers are untouched. Each must be a workspace member; IDs outside the workspace are silently skipped. Use to backfill a bug reporter onto an existing task."}},"additionalProperties":false,"description":"Body of `PATCH /api/tasks/:id`. All fields optional; `null` clears nullable fields."},"ProjectTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"icon":{"type":["string","null"]},"color":{"type":["string","null"]},"visibility":{"$ref":"#/components/schemas/ProjectVisibility"},"config":{"type":"object","additionalProperties":{},"description":"Template payload — initial milestones, default tasks, member roles."},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","description","icon","color","visibility","config","created_by","created_at","updated_at"]},"ProjectVisibility":{"type":"string","enum":["private","team","workspace"]},"ProjectTemplateListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProjectTemplate"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ProjectTemplateEnvelope":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/ProjectTemplate"}},"required":["template"]},"Project":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"icon":{"type":["string","null"]},"color":{"type":["string","null"]},"visibility":{"$ref":"#/components/schemas/ProjectVisibility"},"auto_archive_days":{"type":["integer","null"]},"estimation_scale":{"type":"string","enum":["fibonacci","linear","t-shirt"]},"notification_channel_id":{"type":["string","null"],"format":"uuid"},"workspace_id":{"type":["string","null"],"format":"uuid","description":"`projects.workspace_id` is a nullable FK; a row predating workspace stamping carries none."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"task_count":{"type":"integer"},"latest_status":{"anyOf":[{"$ref":"#/components/schemas/ProjectStatus"},{"type":"null"}]},"task_progress":{"anyOf":[{"$ref":"#/components/schemas/ProjectTaskProgress"},{"type":"null"}]},"milestone_progress":{"anyOf":[{"$ref":"#/components/schemas/ProjectMilestoneProgress"},{"type":"null"}]}},"required":["id","name","description","icon","color","visibility","auto_archive_days","estimation_scale","notification_channel_id","workspace_id","created_at","updated_at","task_count","latest_status","task_progress","milestone_progress"]},"ProjectStatus":{"type":"string","enum":["on_track","at_risk","off_track","paused","completed","cancelled"],"description":"Latest status update on the project. `null` when no updates have been posted."},"ProjectTaskProgress":{"type":"object","properties":{"total":{"type":"integer","minimum":0,"description":"Tasks in the project, every status included."},"done":{"type":"integer","minimum":0},"in_progress":{"type":"integer","minimum":0},"todo":{"type":"integer","minimum":0},"cancelled":{"type":"integer","minimum":0},"percentage":{"type":"integer","description":"done / (todo + in_progress + done), rounded. Cancelled tasks are excluded from the denominator."}},"required":["total","done","in_progress","todo","cancelled","percentage"]},"ProjectMilestoneProgress":{"type":"object","properties":{"total":{"type":"integer","minimum":0,"description":"Milestones in the project."},"completed":{"type":"integer","minimum":0},"percentage":{"type":"integer","description":"completed / total, rounded."},"task_percentage":{"type":"integer","description":"Task completion across the project's milestones, rounded — the figure the sidebar bar renders when milestones exist."}},"required":["total","completed","percentage","task_percentage"]},"ProjectEnvelope":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}},"required":["project"]},"ProjectListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Project"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ProjectMember":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/ProjectMemberRole"},"added_at":{"type":["string","null"]},"user":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]}},"required":["user_id","role","added_at","user"]},"ProjectMemberRole":{"type":"string","enum":["viewer","editor","admin"]},"ProjectMembersListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProjectMember"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ProjectSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]},"ProjectUpdate":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"project_id":{"type":"string","format":"uuid"},"status":{"$ref":"#/components/schemas/ProjectStatus"},"body":{"type":["string","null"],"description":"`null` when the update carries a status change and no prose — the column is nullable and the handler has nothing to substitute."},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"author":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]}},"required":["id","project_id","status","body","created_by","created_at","author"]},"ProjectUpdatesListResponse":{"type":"object","properties":{"updates":{"type":"array","items":{"$ref":"#/components/schemas/ProjectUpdate"}}},"required":["updates"]},"ProjectUpdateEnvelope":{"type":"object","properties":{"update":{"$ref":"#/components/schemas/ProjectUpdate"}},"required":["update"]},"ProjectNotificationPreference":{"type":"object","properties":{"project_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"level":{"$ref":"#/components/schemas/ProjectNotificationLevel"},"updated_at":{"type":["string","null"]}},"required":["project_id","user_id","level","updated_at"]},"ProjectNotificationLevel":{"type":"string","enum":["subscribed","watching","ignoring"]},"ProjectNotificationPreferenceEnvelope":{"type":"object","properties":{"preference":{"$ref":"#/components/schemas/ProjectNotificationPreference"}},"required":["preference"]},"GitHubMappingListResponse":{"type":"object","properties":{"data":{"type":"array","items":{}}},"required":["data"]},"GitHubMappingEnvelope":{"type":"object","properties":{"mapping":{}}},"GitHubMappingConflictError":{"type":"object","properties":{"error":{"type":"string"},"existing_project_id":{"type":"string","format":"uuid"}},"required":["error","existing_project_id"]},"GitHubMappingDeleteResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"Cycle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"start_date":{"type":"string"},"end_date":{"type":"string"},"status":{"$ref":"#/components/schemas/CycleStatus"},"cooldown_days":{"type":"integer","minimum":0},"auto_rollover":{"type":"boolean"},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"creator":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]}},"required":["id","workspace_id","name","start_date","end_date","status","cooldown_days","auto_rollover","created_by","created_at","updated_at","creator"]},"CycleStatus":{"type":"string","enum":["planned","active","completed","cancelled"]},"CycleListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Cycle"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"CreateCycleBody":{"type":"object","properties":{"name":{"type":"string"},"start_date":{"type":"string"},"end_date":{"type":"string"},"status":{"type":"string"},"cooldown_days":{"type":"integer","minimum":0},"auto_rollover":{"type":"boolean"}},"additionalProperties":false},"CycleVelocity":{"type":"array","items":{"$ref":"#/components/schemas/VelocityEntry"},"description":"Recent completed cycles, most recent first."},"VelocityEntry":{"type":"object","properties":{"cycleId":{"type":"string","format":"uuid"},"cycleName":{"type":"string"},"startDate":{"type":"string"},"endDate":{"type":"string"},"status":{"$ref":"#/components/schemas/CycleStatus"},"completedCount":{"type":"integer"},"completedPoints":{"type":"number"}},"required":["cycleId","cycleName","startDate","endDate","status","completedCount","completedPoints"]},"CycleVelocityResponse":{"type":"object","properties":{"velocity":{"$ref":"#/components/schemas/CycleVelocity"}},"required":["velocity"]},"UpdateCycleBody":{"type":"object","properties":{"name":{"type":"string"},"start_date":{"type":"string"},"end_date":{"type":"string"},"status":{"type":"string"},"cooldown_days":{"type":"integer","minimum":0},"auto_rollover":{"type":"boolean"}},"additionalProperties":false},"BurndownPoint":{"type":"object","properties":{"date":{"type":"string"},"scope":{"type":"integer"},"completed":{"type":"integer"},"remaining":{"type":"integer"},"scopePoints":{"type":"number"},"completedPoints":{"type":"number"},"remainingPoints":{"type":"number"}},"required":["date","scope","completed","remaining","scopePoints","completedPoints","remainingPoints"]},"CycleAnalytics":{"type":"object","properties":{"cycleId":{"type":"string","format":"uuid"},"totalTasks":{"type":"integer"},"completedTasks":{"type":"integer"},"remainingTasks":{"type":"integer"},"totalPoints":{"type":"number"},"completedPoints":{"type":"number"},"remainingPoints":{"type":"number"},"burndown":{"type":"array","items":{"$ref":"#/components/schemas/BurndownPoint"}}},"required":["cycleId","totalTasks","completedTasks","remainingTasks","totalPoints","completedPoints","remainingPoints","burndown"]},"CompleteCycleResponse":{"type":"object","properties":{"completed_cycle_id":{"type":"string","format":"uuid"},"rolled_over_count":{"type":"integer","minimum":0},"next_cycle_id":{"type":["string","null"],"format":"uuid"}},"required":["completed_cycle_id","rolled_over_count","next_cycle_id"]},"CycleTasksMutationResponse":{"type":"object","properties":{"added":{"type":"integer","minimum":0},"removed":{"type":"integer","minimum":0}}},"SheetSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["sheet"]},"title":{"type":"string"},"owner_id":{"type":["string","null"],"format":"uuid"},"visibility":{"type":"string"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"pinned_at":{"type":["string","null"]},"starred_at":{"type":["string","null"]},"starred":{"type":"boolean"},"labels":{"type":"array","items":{"type":"string"}},"owner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]}},"required":["id","type","title","owner_id","visibility","link_expires_at","has_password","created_at","updated_at","pinned_at","starred_at","starred","labels","owner"],"description":"Lightweight sheet metadata returned in list responses. Does NOT carry the structured `data` body — call GET /api/sheets/:id to load the full sheet."},"SheetListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SheetSummary"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"],"description":"List of sheets accessible to the caller (owned + shared), filtered to `type: sheet`. Mirrors the `/api/documents` list envelope but without rendering doc or slide rows."},"SheetData":{"type":"object","properties":{"tabs":{"type":"array","items":{"$ref":"#/components/schemas/SheetTab"}},"sheets":{"type":"array","items":{},"description":"The wire key the server actually returns the tab list under (same element shape as `tabs`)."},"namedRanges":{"type":"array","items":{"$ref":"#/components/schemas/SheetStoredNamedRange"}},"validations":{"type":"array","items":{"$ref":"#/components/schemas/SheetValidation"}},"conditionalFormats":{"type":"array","items":{"$ref":"#/components/schemas/ConditionalFormatRule"},"description":"The key the conditional-format endpoints read and write."},"conditionalFormatRules":{"type":"array","items":{"$ref":"#/components/schemas/ConditionalFormatRule"},"description":"Import-accepted alias for `conditionalFormats` (`WORKBOOK_FIELDS`); never written by this API."},"protectedRanges":{"type":"array","items":{"$ref":"#/components/schemas/ProtectedRange"}},"connectors":{"type":"array","items":{"$ref":"#/components/schemas/DataConnector"}}},"additionalProperties":{},"description":"JSON canvas — the structured sheet body (tabs, columns, rows, formulas). Returned nested under `data` on the `Sheet` envelope; never returned at the response root."},"SheetTab":{"type":"object","properties":{"name":{"type":"string"},"columns":{"type":"array","items":{"$ref":"#/components/schemas/SheetColumn"}},"rows":{"type":"array","items":{"$ref":"#/components/schemas/SheetRow"}},"cells":{"type":"array","items":{"$ref":"#/components/schemas/SheetCell"}},"merges":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["name","columns","rows"],"additionalProperties":{}},"SheetColumn":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["text","number","currency","date","boolean","formula"]},"width":{"type":"integer"}},"required":["name"],"additionalProperties":{}},"SheetRow":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SheetCellValue"},"description":"Row keyed by column id → cell value."},"SheetCellValue":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}],"description":"Cell value. `null` = empty. Formulas are stored as `=...` strings."},"SheetCell":{"type":"object","properties":{"row":{"type":"integer"},"col":{"type":"integer"},"value":{"$ref":"#/components/schemas/SheetCellValue"},"formula":{"type":["string","null"]},"format":{"$ref":"#/components/schemas/SheetCellFormat"},"note":{"type":["string","null"]}},"required":["row","col"],"additionalProperties":{}},"SheetCellFormat":{"type":"object","properties":{"bold":{"type":"boolean"},"italic":{"type":"boolean"},"underline":{"type":"boolean"},"strikethrough":{"type":"boolean"},"color":{"type":"string"},"backgroundColor":{"type":"string"},"fontFamily":{"type":"string"},"fontSize":{"type":"number"},"horizontalAlign":{"type":"string","enum":["left","center","right"]},"verticalAlign":{"type":"string","enum":["top","middle","bottom"]},"numberFormat":{"type":"string"},"wrapStrategy":{"type":"string","enum":["overflow","clip","wrap"]}},"additionalProperties":{}},"SheetStoredNamedRange":{"type":"object","properties":{"name":{"type":"string"},"sheetName":{"type":"string"},"startRow":{"type":"integer"},"startCol":{"type":"integer"},"endRow":{"type":"integer"},"endCol":{"type":"integer"}},"required":["name","sheetName","startRow","startCol","endRow","endCol"]},"SheetValidation":{"type":"object","properties":{"range":{"type":"string","description":"A1-style range, e.g. `Sheet1!A1:A100`."},"rule":{"$ref":"#/components/schemas/ValidationRule"}},"required":["range","rule"]},"ValidationRule":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ValidationRuleType"},"values":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}},"strict":{"type":"boolean"},"inputMessage":{"type":"string"}},"required":["type"]},"ValidationRuleType":{"type":"string","enum":["ONE_OF_LIST","ONE_OF_RANGE","NUMBER_BETWEEN","NUMBER_GREATER","NUMBER_LESS","NUMBER_EQUAL","TEXT_CONTAINS","TEXT_NOT_CONTAINS","TEXT_EQ","DATE_IS","DATE_BEFORE","DATE_AFTER","DATE_BETWEEN","BOOLEAN","CUSTOM_FORMULA"],"description":"Mirror of Google Sheets API v4 validation rule types."},"ConditionalFormatRule":{"type":"object","properties":{"id":{"type":"string"},"ranges":{"type":"array","items":{"type":"string"}},"booleanRule":{"$ref":"#/components/schemas/BooleanRule"},"gradientRule":{"$ref":"#/components/schemas/GradientRule"}},"required":["id","ranges"]},"BooleanRule":{"type":"object","properties":{"condition":{"$ref":"#/components/schemas/BooleanCondition"},"format":{"$ref":"#/components/schemas/ConditionalFormat"}},"required":["condition","format"]},"BooleanCondition":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/BooleanConditionType"},"values":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}}},"required":["type"]},"BooleanConditionType":{"type":"string","enum":["NUMBER_GREATER","NUMBER_GREATER_THAN_EQ","NUMBER_LESS","NUMBER_LESS_THAN_EQ","NUMBER_EQ","NUMBER_NOT_EQ","NUMBER_BETWEEN","NUMBER_NOT_BETWEEN","TEXT_CONTAINS","TEXT_NOT_CONTAINS","TEXT_STARTS_WITH","TEXT_ENDS_WITH","TEXT_EQ","TEXT_NOT_EQ","DATE_IS","DATE_BEFORE","DATE_AFTER","DATE_EQ","BLANK","NOT_BLANK","CUSTOM_FORMULA"]},"ConditionalFormat":{"type":"object","properties":{"backgroundColor":{"type":"string"},"textFormat":{"$ref":"#/components/schemas/ConditionalTextFormat"}}},"ConditionalTextFormat":{"type":"object","properties":{"bold":{"type":"boolean"},"italic":{"type":"boolean"},"foregroundColor":{"type":"string"}}},"GradientRule":{"type":"object","properties":{"minpoint":{"$ref":"#/components/schemas/GradientPoint"},"midpoint":{"$ref":"#/components/schemas/GradientPoint"},"maxpoint":{"$ref":"#/components/schemas/GradientPoint"}},"required":["minpoint","maxpoint"]},"GradientPoint":{"type":"object","properties":{"color":{"type":"string"},"type":{"type":"string","enum":["MIN","MAX","NUMBER","PERCENT","PERCENTILE"]},"value":{"anyOf":[{"type":"string"},{"type":"number"}]}},"required":["color","type"]},"ProtectedRange":{"type":"object","properties":{"id":{"type":"string"},"range":{"type":"string"},"description":{"type":"string"},"warningOnly":{"type":"boolean"},"editorUserIds":{"type":"array","items":{"type":"string"}}},"required":["id","range","warningOnly","editorUserIds"]},"DataConnector":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"documentId":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/ConnectorType"},"config":{"$ref":"#/components/schemas/ConnectorConfig"},"targetSheet":{"type":["string","null"]},"targetRow":{"type":"integer"},"targetCol":{"type":"integer"},"lastRunAt":{"type":["string","null"]},"lastStatus":{"$ref":"#/components/schemas/ConnectorStatus"},"lastError":{"type":["string","null"]},"lastRowCount":{"type":["integer","null"]},"refreshSchedule":{"$ref":"#/components/schemas/ConnectorRefreshSchedule"},"createdBy":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":["string","null"]},"updatedAt":{"type":["string","null"]}},"required":["id","documentId","workspaceId","name","type","config","targetSheet","targetRow","targetCol","lastRunAt","lastStatus","lastError","lastRowCount","refreshSchedule","createdBy","createdAt","updatedAt"]},"ConnectorType":{"type":"string","enum":["bigquery","stripe","postgres"]},"ConnectorConfig":{"type":"object","properties":{"project_id":{"type":"string"},"dataset":{"type":"string"},"query":{"type":"string"},"secret_key":{"type":"string"},"api_version":{"type":"string"},"connection_string":{"type":"string"},"table":{"type":"string"}},"additionalProperties":{},"description":"Provider-specific connection settings; shape depends on `type`."},"ConnectorStatus":{"type":"string","enum":["idle","running","success","error"],"description":"Outcome of the connector's most recent run. `error` is what SHEETS.md E14 fans out on."},"ConnectorRefreshSchedule":{"type":"string","enum":["manual","hourly","daily"]},"Sheet":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"data":{"$ref":"#/components/schemas/SheetData"},"owner_id":{"type":["string","null"],"format":"uuid"},"visibility":{"type":"string"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"},"can_edit":{"type":"boolean","description":"True when the caller has editor or owner role on this sheet."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"starred_at":{"type":["string","null"]},"starred":{"type":"boolean"},"owner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]}},"required":["id","title","data","owner_id","visibility","link_expires_at","has_password","created_at","updated_at","starred_at","starred","owner"],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."},"SheetCreateInput":{"type":"object","properties":{"title":{"type":"string","description":"Optional title. Defaults to 'Untitled' when omitted."},"content":{"anyOf":[{"type":"string"},{"type":"object","additionalProperties":{}}],"description":"Optional initial SheetData (JSON canvas). String is parsed as JSON server-side; object is stringified."},"visibility":{"type":"string","enum":["restricted","workspace","link","public"]},"labels":{"type":"array","items":{"type":"string"}}},"additionalProperties":false},"AppendValuesResponse":{"type":"object","properties":{"updates":{"type":"object","properties":{"updatedRange":{"type":"string","description":"A1 range the append actually wrote, e.g. `Sheet1!A4:C6`."},"updatedRows":{"type":"integer"},"updatedColumns":{"type":"integer"},"updatedCells":{"type":"integer"}},"required":["updatedRange","updatedRows","updatedColumns","updatedCells"]}},"required":["updates"]},"AppendValuesInput":{"type":"object","properties":{"range":{"type":"string","description":"A1-style range — `Sheet1!A1:D10` or `A1:D10`."},"values":{"type":"array","items":{},"description":"2-D array of row × column values. Capped at 1000 rows per call."}},"additionalProperties":false},"BatchGetResponse":{"type":"object","properties":{"spreadsheetId":{"type":"string","format":"uuid"},"valueRanges":{"type":"array","items":{"type":"object","properties":{"range":{"type":"string"},"values":{"type":"array","items":{"type":"array","items":{"$ref":"#/components/schemas/SheetCellValue"}}}},"required":["range","values"]}}},"required":["spreadsheetId","valueRanges"]},"BatchRangesInput":{"type":"object","properties":{"ranges":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":100,"description":"Array of A1-style range specs. Capped at 100 per call."}},"required":["ranges"],"additionalProperties":false},"BatchClearResponse":{"type":"object","properties":{"spreadsheetId":{"type":"string","format":"uuid"},"clearedRanges":{"type":"array","items":{"type":"string"}}},"required":["spreadsheetId","clearedRanges"]},"CopySheetResponse":{"type":"object","properties":{"sheetName":{"type":"string","description":"Name the copied tab landed under in the destination spreadsheet."},"index":{"type":"integer","minimum":0,"description":"Zero-based position of the copied tab in the destination's tab list."}},"required":["sheetName","index"]},"CopySheetInput":{"type":"object","properties":{"sourceSheetName":{"type":"string"},"destinationDocumentId":{"type":"string","format":"uuid"}},"required":["sourceSheetName","destinationDocumentId"],"additionalProperties":false},"NamedRange":{"type":"object","properties":{"name":{"type":"string"},"range":{"type":"string"}},"required":["name","range"]},"NamedRangeInput":{"type":"object","properties":{"name":{"type":"string"},"range":{"type":"string","description":"A1-style range — `Sheet1!B2:B100`."}},"required":["name","range"],"additionalProperties":false},"NamedRangesListResponse":{"type":"object","properties":{"namedRanges":{"type":"array","items":{"$ref":"#/components/schemas/NamedRange"}}},"required":["namedRanges"]},"UpdateNamedRangeInput":{"type":"object","properties":{"range":{"type":"string"}},"required":["range"],"additionalProperties":false},"ValidationInput":{"type":"object","properties":{"range":{"type":"string"},"rule":{"type":"object","additionalProperties":{}}},"additionalProperties":false},"ClearValidationInput":{"type":"object","properties":{"range":{"type":"string"}},"additionalProperties":false},"ValidationsListResponse":{"type":"object","properties":{"validations":{"type":"array","items":{"$ref":"#/components/schemas/SheetValidation"}}},"required":["validations"]},"ConditionalFormatsListResponse":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/ConditionalFormatRule"}}},"required":["rules"]},"ConditionalFormatInput":{"type":"object","properties":{"ranges":{"type":"array","items":{"type":"string"}},"booleanRule":{"type":"object","properties":{"condition":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/BooleanConditionType"},"values":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}}},"required":["type"],"additionalProperties":false},"format":{"type":"object","properties":{"backgroundColor":{"type":"string"},"textFormat":{"type":"object","properties":{"bold":{"type":"boolean"},"italic":{"type":"boolean"},"foregroundColor":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["condition","format"],"additionalProperties":false},"gradientRule":{"type":"object","properties":{"minpoint":{"type":"object","properties":{"color":{"type":"string"},"type":{"type":"string","enum":["MIN","MAX","NUMBER","PERCENT","PERCENTILE"]},"value":{"anyOf":[{"type":"string"},{"type":"number"}]}},"required":["color","type"],"additionalProperties":false},"midpoint":{"type":"object","properties":{"color":{"type":"string"},"type":{"type":"string","enum":["MIN","MAX","NUMBER","PERCENT","PERCENTILE"]},"value":{"anyOf":[{"type":"string"},{"type":"number"}]}},"required":["color","type"],"additionalProperties":false},"maxpoint":{"type":"object","properties":{"color":{"type":"string"},"type":{"type":"string","enum":["MIN","MAX","NUMBER","PERCENT","PERCENTILE"]},"value":{"anyOf":[{"type":"string"},{"type":"number"}]}},"required":["color","type"],"additionalProperties":false}},"required":["minpoint","maxpoint"],"additionalProperties":false}},"additionalProperties":false},"ProtectedRangesListResponse":{"type":"object","properties":{"protectedRanges":{"type":"array","items":{"$ref":"#/components/schemas/ProtectedRange"}}},"required":["protectedRanges"]},"ProtectedRangeInput":{"type":"object","properties":{"range":{"type":"string"},"description":{"type":"string"},"warningOnly":{"type":"boolean"},"editorUserIds":{"type":"array","items":{}}},"additionalProperties":false},"SheetRangeCellValue":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"$ref":"#/components/schemas/ImageCellValue"},{"$ref":"#/components/schemas/LinkCellValue"}],"description":"A cell value as a range read returns it: the stored scalar, or — on `valueRenderOption=EVALUATED` — one of the two rendered-element sentinels."},"ImageCellValue":{"type":"object","properties":{"__imageCell":{"type":"boolean","enum":[true]},"url":{"type":"string"},"mode":{"anyOf":[{"type":"number","enum":[1]},{"type":"number","enum":[2]},{"type":"number","enum":[3]},{"type":"number","enum":[4]}]},"height":{"type":"number"},"width":{"type":"number"},"alt":{"type":"string"}},"required":["__imageCell","url","mode"],"description":"IMAGE() result — the grid renders an <img> rather than text."},"LinkCellValue":{"type":"object","properties":{"__linkCell":{"type":"boolean","enum":[true]},"url":{"type":"string"},"label":{"type":"string"}},"required":["__linkCell","url","label"],"description":"HYPERLINK() result — the grid renders an <a> rather than text."},"RangeResponse":{"type":"object","properties":{"sheet":{"type":"string"},"startCol":{"type":"string"},"startRow":{"type":"integer"},"endCol":{"type":"string"},"endRow":{"type":"integer"},"values":{"type":"array","items":{"type":"array","items":{"$ref":"#/components/schemas/SheetRangeCellValue"}}},"orientation":{"type":"string","enum":["ROWS","COLUMNS"]},"valueRenderOption":{"type":"string","enum":["STORED","FORMULA","EVALUATED"]}},"required":["sheet","startCol","startRow","endCol","endRow","values"]},"UpdatedCell":{"type":"object","properties":{"row":{"type":"integer","minimum":0},"column":{"type":"string"},"sheet":{"type":"string","description":"Tab the cell was written to; absent when the update carried no per-row tab."},"value":{"$ref":"#/components/schemas/SheetCellValue"}},"required":["row","column","value"]},"SheetWithUpdatedCells":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"updatedCells":{"type":"array","items":{"$ref":"#/components/schemas/UpdatedCell"},"description":"Present only when `includeValuesInResponse=true`: the value each updated cell holds after the write."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."},"UpdateCellsInput":{"type":"object","properties":{"sheet":{"type":"string"},"tab":{"type":"string"},"updates":{"type":"array","items":{"type":"object","additionalProperties":{}}},"cells":{"type":"array","items":{},"description":"Alias for `updates` — accepted by the API client."},"formatUpdates":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"additionalProperties":false},"MergesInput":{"type":"object","properties":{"sheet":{"type":"string"},"merges":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"additionalProperties":false},"TabInput":{"type":"object","properties":{"name":{"type":"string"}},"additionalProperties":false},"RenameTabInput":{"type":"object","properties":{"new_name":{"type":"string"},"name":{"type":"string","description":"Alias for `new_name`."}},"additionalProperties":false},"ReplaceTabInput":{"type":"object","properties":{"columns":{"type":"array","items":{"type":"object","additionalProperties":{}}},"rows":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"additionalProperties":false},"AddColumnInput":{"type":"object","properties":{"name":{"type":"string"},"column_id":{"type":"string"},"type":{},"sheet":{"type":"string"},"at_index":{"type":"number"}},"additionalProperties":false},"AddRowsInput":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","additionalProperties":{}}},"sheet":{"type":"string"},"at_index":{"type":"number"}},"additionalProperties":false},"DeleteRowsInput":{"type":"object","properties":{"indices":{"type":"array","items":{}},"sheet":{"type":"string"}},"additionalProperties":false},"SortSheetInput":{"type":"object","properties":{"column_id":{"type":"string"},"direction":{"type":"string","enum":["asc","desc"]},"sheet":{"type":"string"}},"required":["column_id","direction"],"additionalProperties":false},"MoveColumnInput":{"type":"object","properties":{"column_id":{"type":"string"},"to_index":{"type":"integer","minimum":0},"sheet":{"type":"string"}},"required":["column_id","to_index"],"additionalProperties":false},"ConnectorListResponse":{"type":"object","properties":{"connectors":{"type":"array","items":{"$ref":"#/components/schemas/DataConnector"}}},"required":["connectors"]},"ConnectorResponse":{"type":"object","properties":{"connector":{"$ref":"#/components/schemas/DataConnector"}},"required":["connector"]},"CreateConnectorInput":{"type":"object","properties":{"name":{"type":"string"},"type":{},"config":{"type":"object","additionalProperties":{}},"target_sheet":{"type":["string","null"]},"target_row":{"type":"number"},"target_col":{"type":"number"},"refresh_schedule":{},"refreshSchedule":{},"targetSheet":{},"targetRow":{},"targetCol":{}},"additionalProperties":false},"UpdateConnectorInput":{"type":"object","properties":{"name":{"type":"string"},"config":{"type":"object","additionalProperties":{}},"target_sheet":{"type":["string","null"]},"target_row":{"type":"number"},"target_col":{"type":"number"},"refresh_schedule":{},"refreshSchedule":{},"targetSheet":{},"targetRow":{},"targetCol":{}},"additionalProperties":false},"ConnectorRunLog":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"connectorId":{"type":"string","format":"uuid"},"documentId":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["success","error"]},"startedAt":{"type":"string"},"completedAt":{"type":"string"},"rowCount":{"type":["integer","null"]},"errorMessage":{"type":["string","null"]},"runTrigger":{"type":"string","enum":["manual","schedule"]},"createdAt":{"type":["string","null"]}},"required":["id","connectorId","documentId","workspaceId","status","startedAt","completedAt","rowCount","errorMessage","runTrigger"]},"ConnectorRunHistoryResponse":{"type":"object","properties":{"runs":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorRunLog"}}},"required":["runs"]},"PivotTableStored":{"type":"object","properties":{"id":{"type":"string"},"sourceRange":{},"sourceTabName":{"type":"string"},"rowFields":{"type":"array","items":{}},"columnFields":{"type":"array","items":{}},"valueFields":{"type":"array","items":{}},"filters":{},"useHeaders":{"type":"boolean"},"showRowTotals":{"type":"boolean"},"showColumnTotals":{"type":"boolean"}},"required":["id","rowFields","valueFields"],"additionalProperties":{}},"PivotListResponse":{"type":"object","properties":{"pivotTables":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/PivotTableStored"},{"type":"object","properties":{"tab":{"type":"string"}},"required":["tab"]}]},"description":"Every pivot table across every tab, each annotated with the tab name it lives in."}},"required":["pivotTables"]},"PivotTableResponse":{"type":"object","properties":{"pivot":{"$ref":"#/components/schemas/PivotTableStored"},"tabName":{"type":"string"},"tabIndex":{"type":"integer","minimum":0}},"required":["pivot","tabName","tabIndex"]},"PivotTableInput":{"type":"object","properties":{"sourceRange":{"type":"string"},"rowFields":{"type":"array","items":{}},"valueFields":{"type":"array","items":{}},"columnFields":{"type":"array","items":{}},"filters":{"type":"array","items":{}},"showRowTotals":{"type":"boolean"},"showColumnTotals":{"type":"boolean"}},"additionalProperties":false},"PivotColumnHeader":{"type":"object","properties":{"label":{"type":"string"},"key":{"type":"string"},"columnValue":{"type":"string"},"valueField":{"type":"object","properties":{"columnId":{"type":"string"},"aggregation":{"type":"string"},"label":{"type":"string"}},"required":["columnId","aggregation"]}},"required":["label","key","valueField"]},"PivotResultRow":{"type":"object","properties":{"rowHeaders":{"type":"array","items":{"type":"string"}},"values":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PivotCell"}},"isGrandTotal":{"type":"boolean"}},"required":["rowHeaders","values"]},"PivotCell":{"type":"object","properties":{"value":{"type":["number","null"]},"count":{"type":"integer","minimum":0}},"required":["value","count"]},"PivotComputeResponse":{"type":"object","properties":{"pivotId":{"type":"string"},"tabName":{"type":"string"},"result":{"type":"object","properties":{"rowFieldLabels":{"type":"array","items":{"type":"string"}},"columnHeaders":{"type":"array","items":{"$ref":"#/components/schemas/PivotColumnHeader"}},"rows":{"type":"array","items":{"$ref":"#/components/schemas/PivotResultRow"}},"columnTotals":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PivotCell"}},"rowTotals":{"type":"array","items":{"$ref":"#/components/schemas/PivotCell"}},"grandTotal":{"$ref":"#/components/schemas/PivotCell"}},"required":["rowFieldLabels","columnHeaders","rows"]}},"required":["pivotId","tabName","result"]},"PivotPatchResponse":{"type":"object","properties":{"pivot":{"$ref":"#/components/schemas/PivotTableStored"},"tab":{"type":"string"}},"required":["pivot","tab"]},"PivotUpdateInput":{"type":"object","properties":{"tab":{"type":"string"},"sourceRange":{},"sourceTabName":{"type":"string"},"rowFields":{"type":"array","items":{}},"columnFields":{"type":"array","items":{}},"valueFields":{"type":"array","items":{}},"filters":{},"useHeaders":{"type":"boolean"},"showRowTotals":{"type":"boolean"},"showColumnTotals":{"type":"boolean"}},"additionalProperties":false},"ChartConfig":{"type":"object","properties":{"id":{"type":"string"},"type":{"$ref":"#/components/schemas/ChartType"},"title":{"type":"string"},"dataRange":{"$ref":"#/components/schemas/ChartDataRange"},"useHeaders":{"type":"boolean"},"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"},"series":{"$ref":"#/components/schemas/ChartSeriesConfig"}},"required":["id","type","title","dataRange","useHeaders","x","y","width","height"],"additionalProperties":{}},"ChartType":{"type":"string","enum":["bar","line","pie","scatter"]},"ChartDataRange":{"type":"object","properties":{"startCol":{"type":"integer","minimum":0},"startRow":{"type":"integer","minimum":0},"endCol":{"type":"integer","minimum":0},"endRow":{"type":"integer","minimum":0}},"required":["startCol","startRow","endCol","endRow"]},"ChartSeriesConfig":{"type":"object","properties":{"colors":{"type":"array","items":{"type":"string"}},"stacked":{"type":"boolean"},"smooth":{"type":"boolean"},"showArea":{"type":"boolean"},"showLegend":{"type":"boolean"},"showGrid":{"type":"boolean"},"showValues":{"type":"boolean"},"showTrendLine":{"type":"boolean"},"innerRadius":{"type":"number"}},"additionalProperties":{}},"ChartListResponse":{"type":"object","properties":{"charts":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/ChartConfig"},{"type":"object","properties":{"tab":{"type":"string"}},"required":["tab"]}]},"description":"Every chart across every tab, each annotated with the tab name it lives in."}},"required":["charts"]},"ChartResponse":{"type":"object","properties":{"chart":{"$ref":"#/components/schemas/ChartConfig"},"tab":{"type":"string"}},"required":["chart","tab"]},"ChartCreateInput":{"type":"object","properties":{"tab":{"type":"string","description":"Tab name where the chart lives. Defaults to the first tab."},"type":{"$ref":"#/components/schemas/ChartType"},"title":{"type":"string"},"dataRange":{"type":"object","properties":{"startCol":{"type":"integer","minimum":0},"startRow":{"type":"integer","minimum":0},"endCol":{"type":"integer","minimum":0},"endRow":{"type":"integer","minimum":0}},"required":["startCol","startRow","endCol","endRow"],"additionalProperties":false},"useHeaders":{"type":"boolean"},"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"},"series":{"type":"object","properties":{"colors":{"type":"array","items":{"type":"string"}},"stacked":{"type":"boolean"},"smooth":{"type":"boolean"},"showArea":{"type":"boolean"},"showLegend":{"type":"boolean"},"showGrid":{"type":"boolean"},"showValues":{"type":"boolean"},"showTrendLine":{"type":"boolean"},"innerRadius":{"type":"number"}},"additionalProperties":false}},"required":["type","title","dataRange"],"additionalProperties":false},"ChartUpdateInput":{"type":"object","properties":{"tab":{"type":"string"},"type":{"$ref":"#/components/schemas/ChartType"},"title":{"type":"string"},"dataRange":{"type":"object","properties":{"startCol":{"type":"integer","minimum":0},"startRow":{"type":"integer","minimum":0},"endCol":{"type":"integer","minimum":0},"endRow":{"type":"integer","minimum":0}},"required":["startCol","startRow","endCol","endRow"],"additionalProperties":false},"useHeaders":{"type":"boolean"},"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"},"series":{"type":"object","properties":{"colors":{"type":"array","items":{"type":"string"}},"stacked":{"type":"boolean"},"smooth":{"type":"boolean"},"showArea":{"type":"boolean"},"showLegend":{"type":"boolean"},"showGrid":{"type":"boolean"},"showValues":{"type":"boolean"},"showTrendLine":{"type":"boolean"},"innerRadius":{"type":"number"}},"additionalProperties":false}},"additionalProperties":false},"SlicerConfig":{"type":"object","properties":{"id":{"type":"string"},"sourceRange":{"$ref":"#/components/schemas/SlicerSourceRange"},"columnId":{"type":"string","description":"Column id within the source range that this slicer filters."},"useHeaders":{"type":"boolean"},"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"},"selectedValues":{"type":["array","null"],"items":{"type":"string"},"description":"null = pass-through ('All'); [] = filter out everything ('None'); non-empty array = only these values pass."},"title":{"type":"string"}},"required":["id","sourceRange","columnId","useHeaders","x","y","width","height","selectedValues"],"additionalProperties":{}},"SlicerSourceRange":{"type":"object","properties":{"startCol":{"type":"integer","minimum":0},"startRow":{"type":"integer","minimum":0},"endCol":{"type":"integer","minimum":0},"endRow":{"type":"integer","minimum":0}},"required":["startCol","startRow","endCol","endRow"]},"SlicerListResponse":{"type":"object","properties":{"slicers":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/SlicerConfig"},{"type":"object","properties":{"tab":{"type":"string"}},"required":["tab"]}]},"description":"Every slicer across every tab, each annotated with the tab name it lives in."}},"required":["slicers"]},"SlicerResponse":{"type":"object","properties":{"slicer":{"$ref":"#/components/schemas/SlicerConfig"},"tab":{"type":"string"}},"required":["slicer","tab"]},"SlicerCreateInput":{"type":"object","properties":{"tab":{"type":"string","description":"Tab name where the slicer lives. Defaults to the first tab."},"sourceRange":{"type":"object","properties":{"startCol":{"type":"integer","minimum":0},"startRow":{"type":"integer","minimum":0},"endCol":{"type":"integer","minimum":0},"endRow":{"type":"integer","minimum":0}},"required":["startCol","startRow","endCol","endRow"],"additionalProperties":false},"columnId":{"type":"string"},"useHeaders":{"type":"boolean"},"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"},"selectedValues":{"type":["array","null"],"items":{"type":"string"}},"title":{"type":"string"}},"required":["sourceRange","columnId"],"additionalProperties":false},"SlicerUpdateInput":{"type":"object","properties":{"tab":{"type":"string"},"sourceRange":{"type":"object","properties":{"startCol":{"type":"integer","minimum":0},"startRow":{"type":"integer","minimum":0},"endCol":{"type":"integer","minimum":0},"endRow":{"type":"integer","minimum":0}},"required":["startCol","startRow","endCol","endRow"],"additionalProperties":false},"columnId":{"type":"string"},"useHeaders":{"type":"boolean"},"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"},"selectedValues":{"type":["array","null"],"items":{"type":"string"}},"title":{"type":"string"}},"additionalProperties":false},"SlideLayoutsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"}},"required":["id","name","description"]}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"SlideTemplate":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"defaultTheme":{"type":"string"},"previewSlide":{"$ref":"#/components/schemas/Slide"}},"required":["id","name","description","defaultTheme","previewSlide"]},"Slide":{"type":"object","properties":{"id":{"type":"string"},"layout":{"$ref":"#/components/schemas/SlideLayoutDimensions"},"background":{"type":"string"},"elements":{"type":"array","items":{"$ref":"#/components/schemas/SlideElement"}},"transition":{"$ref":"#/components/schemas/SlideTransition"},"notes":{"type":"string"},"masterSlideId":{"type":"string"},"masterInheritanceMode":{"type":"string","enum":["legacy-clone","by-reference"]},"overriddenElementIds":{"type":"array","items":{"type":"string"}}},"required":["id","layout","elements"]},"SlideLayoutDimensions":{"type":"object","properties":{"width":{"type":"number","description":"Canvas width in slide-units (e.g. 960 for 16:9)."},"height":{"type":"number","description":"Canvas height in slide-units (e.g. 540 for 16:9, 720 for 4:3)."}},"required":["width","height"]},"SlideElement":{"oneOf":[{"$ref":"#/components/schemas/SlideTextElement"},{"$ref":"#/components/schemas/SlideImageElement"},{"$ref":"#/components/schemas/SlideShapeElement"},{"$ref":"#/components/schemas/SlideTableElement"},{"$ref":"#/components/schemas/SlideChartElement"},{"$ref":"#/components/schemas/SlideVideoElement"},{"$ref":"#/components/schemas/SlideEmbedElement"},{"$ref":"#/components/schemas/SlideGroupElement"}],"discriminator":{"propertyName":"type","mapping":{"text":"#/components/schemas/SlideTextElement","image":"#/components/schemas/SlideImageElement","shape":"#/components/schemas/SlideShapeElement","table":"#/components/schemas/SlideTableElement","chart":"#/components/schemas/SlideChartElement","video":"#/components/schemas/SlideVideoElement","embed":"#/components/schemas/SlideEmbedElement","group":"#/components/schemas/SlideGroupElement"}}},"SlideTextElement":{"type":"object","properties":{"id":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"rotation":{"type":"number"},"opacity":{"type":"number"},"animation":{"$ref":"#/components/schemas/SlideElementAnimation"},"type":{"type":"string","enum":["text"]},"text":{"type":"string"},"content":{"$ref":"#/components/schemas/RichTextContent"},"fontSize":{"type":"number"},"fontWeight":{"type":"string","enum":["normal","bold"]},"fontStyle":{"type":"string","enum":["normal","italic"]},"fontFamily":{"type":"string"},"color":{"type":"string"},"colorUserSet":{"type":"boolean","description":"True when the user picked `color` explicitly; theme application preserves user-set colors instead of remapping them."},"backgroundColor":{"type":"string"},"align":{"type":"string","enum":["left","center","right"]},"verticalAlign":{"type":"string","enum":["top","middle","bottom"]},"lineHeight":{"type":"number"},"underline":{"type":"boolean"},"letterSpacing":{"type":"number"},"indent":{"type":"number"}},"required":["id","x","y","w","h","type","text"]},"SlideElementAnimation":{"type":"object","properties":{"type":{"type":"string","enum":["none","fade-in","fly-in-left","fly-in-right","fly-in-bottom","fly-in-top","zoom-in","spin","bounce","fade-out","fly-out-left","fly-out-right","fly-out-bottom","fly-out-top","zoom-out"]},"duration":{"type":"number","description":"Duration in milliseconds (default 500)."},"delay":{"type":"number","description":"Delay before the animation starts, in milliseconds."},"trigger":{"type":"string","enum":["with-previous","after-previous","on-click"]},"order":{"type":"number","description":"Sequencing index among animations on the same slide."}},"required":["type"]},"RichTextContent":{"type":"object","properties":{"type":{"type":"string"},"content":{"type":"array","items":{"$ref":"#/components/schemas/RichTextContent"}},"text":{"type":"string"},"attrs":{"type":"object","additionalProperties":{}},"marks":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"attrs":{"type":"object","additionalProperties":{}}},"required":["type"]}}},"required":["type"],"description":"ProseMirror JSON for per-character rich text. Stamped onto every text element on read, so it is present on the wire even when the deck was authored without it."},"SlideImageElement":{"type":"object","properties":{"id":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"rotation":{"type":"number"},"opacity":{"type":"number"},"animation":{"$ref":"#/components/schemas/SlideElementAnimation"},"type":{"type":"string","enum":["image"]},"src":{"type":"string"},"objectFit":{"type":"string","enum":["cover","contain","fill"]},"borderRadius":{"type":"number"},"clipRect":{"type":"object","properties":{"top":{"type":"number"},"right":{"type":"number"},"bottom":{"type":"number"},"left":{"type":"number"}},"required":["top","right","bottom","left"]}},"required":["id","x","y","w","h","type","src"]},"SlideShapeElement":{"type":"object","properties":{"id":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"rotation":{"type":"number"},"opacity":{"type":"number"},"animation":{"$ref":"#/components/schemas/SlideElementAnimation"},"type":{"type":"string","enum":["shape"]},"shape":{"type":"string","enum":["rect","circle","ellipse","line","arrow","triangle","star","diamond","pentagon","hexagon","cross","callout","heart"]},"content":{"allOf":[{"$ref":"#/components/schemas/RichTextContent"},{"description":"ProseMirror JSON for rich text inside the shape. Stamped on read, like the text element's."}]},"fill":{"type":"string"},"fillUserSet":{"type":"boolean"},"stroke":{"type":"string"},"strokeUserSet":{"type":"boolean"},"strokeWidth":{"type":"number"},"strokeDashArray":{"type":"string"},"borderRadius":{"type":"number"},"dropShadow":{"type":"object","properties":{"offsetX":{"type":"number"},"offsetY":{"type":"number"},"blur":{"type":"number"},"color":{"type":"string"}},"required":["offsetX","offsetY","blur","color"]},"reflection":{"type":"object","properties":{"distance":{"type":"number"},"transparency":{"type":"number"}},"required":["distance","transparency"]},"fontSize":{"type":"number"},"fontWeight":{"type":"string","enum":["normal","bold"]},"fontStyle":{"type":"string","enum":["normal","italic"]},"fontFamily":{"type":"string"},"color":{"type":"string"},"align":{"type":"string","enum":["left","center","right"]},"verticalAlign":{"type":"string","enum":["top","middle","bottom"]},"lineHeight":{"type":"number"},"underline":{"type":"boolean"},"letterSpacing":{"type":"number"},"indent":{"type":"number"}},"required":["id","x","y","w","h","type","shape"]},"SlideTableElement":{"type":"object","properties":{"id":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"rotation":{"type":"number"},"opacity":{"type":"number"},"animation":{"$ref":"#/components/schemas/SlideElementAnimation"},"type":{"type":"string","enum":["table"]},"rows":{"type":"array","items":{"type":"array","items":{"$ref":"#/components/schemas/SlideTableCell"}}},"headerRow":{"type":"boolean"},"headerBackground":{"type":"string"},"headerTextColor":{"type":"string"},"alternateRowFill":{"type":"string"},"borderColor":{"type":"string"},"fontSize":{"type":"number"},"color":{"type":"string"},"colorUserSet":{"type":"boolean"}},"required":["id","x","y","w","h","type","rows"]},"SlideTableCell":{"type":"object","properties":{"text":{"type":"string"},"bold":{"type":"boolean"},"align":{"type":"string","enum":["left","center","right"]},"color":{"type":"string"},"fill":{"type":"string"}},"required":["text"]},"SlideChartElement":{"type":"object","properties":{"id":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"rotation":{"type":"number"},"opacity":{"type":"number"},"animation":{"$ref":"#/components/schemas/SlideElementAnimation"},"type":{"type":"string","enum":["chart"]},"chartType":{"type":"string","enum":["bar","column","line","pie","doughnut","area"]},"categories":{"type":"array","items":{"type":"string"}},"series":{"type":"array","items":{"$ref":"#/components/schemas/SlideChartSeries"}},"title":{"type":"string"},"showLegend":{"type":"boolean"},"showValues":{"type":"boolean"},"backgroundColor":{"type":"string"},"colors":{"type":"array","items":{"type":"string"}}},"required":["id","x","y","w","h","type","chartType","categories","series"]},"SlideChartSeries":{"type":"object","properties":{"name":{"type":"string"},"data":{"type":"array","items":{"type":"number"}},"color":{"type":"string"}},"required":["name","data"]},"SlideVideoElement":{"type":"object","properties":{"id":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"rotation":{"type":"number"},"opacity":{"type":"number"},"animation":{"$ref":"#/components/schemas/SlideElementAnimation"},"type":{"type":"string","enum":["video"]},"src":{"type":"string"},"provider":{"type":"string","enum":["youtube","drive","vimeo","loom","url"]},"autoPlay":{"type":"boolean"},"startSeconds":{"type":"number"},"endSeconds":{"type":"number"},"muted":{"type":"boolean"},"posterUrl":{"type":"string"}},"required":["id","x","y","w","h","type","src"]},"SlideEmbedElement":{"type":"object","properties":{"id":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"rotation":{"type":"number"},"opacity":{"type":"number"},"animation":{"$ref":"#/components/schemas/SlideElementAnimation"},"type":{"type":"string","enum":["embed"]},"embedKind":{"type":"string","enum":["video","youtube","vimeo","audio","iframe"]},"src":{"type":"string"},"caption":{"type":"string"},"autoplay":{"type":"boolean"},"loop":{"type":"boolean"},"muted":{"type":"boolean"},"controls":{"type":"boolean"},"posterUrl":{"type":"string"}},"required":["id","x","y","w","h","type","embedKind","src"]},"SlideGroupElement":{"type":"object","properties":{"id":{"type":"string"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"rotation":{"type":"number"},"opacity":{"type":"number"},"animation":{"$ref":"#/components/schemas/SlideElementAnimation"},"type":{"type":"string","enum":["group"]},"children":{"type":"array","items":{"$ref":"#/components/schemas/SlideElement"}}},"required":["id","x","y","w","h","type","children"]},"SlideTransition":{"type":"object","properties":{"type":{"type":"string","enum":["none","fade","slide-left","slide-right","slide-up","slide-down","dissolve","zoom-in","zoom-out","flip","wipe","split","cover","uncover"]},"duration_s":{"type":"number","minimum":0.1,"maximum":10,"description":"Transition duration in seconds (float, 0.1–10). Canonical field."},"speed":{"type":"string","enum":["slow","medium","fast"],"description":"Legacy preset (slow=1.0s, medium=0.5s, fast=0.3s) — normalized to duration_s on write."}},"required":["type"]},"SlideTemplatesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SlideTemplate"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"SlideStarIdsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"string","format":"uuid"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"SlideDeckData":{"type":"object","properties":{"settings":{"$ref":"#/components/schemas/SlideDeckSettings"},"slides":{"type":"array","items":{"$ref":"#/components/schemas/Slide"}},"masterSlides":{"type":"array","items":{"$ref":"#/components/schemas/MasterSlide"}}},"required":["settings","slides"],"description":"JSON canvas — the structured deck body (settings, slides, master slides). Returned nested under `data` on the `SlideDeck` envelope; never returned at the response root."},"SlideDeckSettings":{"type":"object","properties":{"aspectRatio":{"type":"string","enum":["16:9","4:3"]},"theme":{"type":"string"},"defaultBackground":{"type":"string"},"showSlideNumbers":{"type":"boolean"}},"required":["aspectRatio"],"additionalProperties":{}},"MasterSlide":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"layout":{"$ref":"#/components/schemas/SlideLayoutDimensions"},"background":{"type":"string"},"elements":{"type":"array","items":{"$ref":"#/components/schemas/SlideElement"}}},"required":["id","name","layout","elements"]},"SlideDeck":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"data":{"$ref":"#/components/schemas/SlideDeckData"},"slide_count":{"type":"integer","minimum":0},"owner_id":{"type":["string","null"],"format":"uuid"},"visibility":{"type":"string"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"},"can_edit":{"type":"boolean","description":"True when the caller has editor or owner role on this deck (can mutate slides, settings, masters). False for viewer/commenter callers — clients use this to gate the editor toolbar, drag/resize handles, and write-path UI."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"owner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":"string"}},"required":["id","display_name","primary_email"]}},"required":["id","title","data","slide_count","owner_id","visibility","link_expires_at","has_password","can_edit","created_at","updated_at","owner"],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."},"CreatePresentationInput":{"type":"object","properties":{"title":{"type":"string","description":"Title for the new deck. Defaults to 'Untitled' if omitted."},"visibility":{"type":"string","enum":["restricted","workspace"],"description":"Initial visibility. Defaults to 'restricted'."}},"additionalProperties":false},"SlideStarResponse":{"type":"object","properties":{"starred_at":{"type":"string"}},"required":["starred_at"]},"AddSlideInput":{"type":"object","properties":{"slide":{"type":"object","additionalProperties":{},"description":"Slide body (full or partial — service merges)."},"elements":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"Element list. Convenience for callers that don't wrap in `slide`."},"background":{},"layout":{"type":"string"},"notes":{"type":"string"},"after_index":{"type":"integer","description":"Insert position. Omit to append."}},"additionalProperties":false},"UpdateSlideInput":{"type":"object","properties":{"elements":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"Full-replace element list for the slide."},"background":{},"layout":{},"notes":{"type":"string"},"transition":{},"slide":{"type":"object","additionalProperties":{},"description":"Alternative envelope — fields merged with top-level keys."}},"additionalProperties":false},"ApplyMasterInput":{"type":"object","properties":{"master_id":{"type":"string","description":"Master slide ID to apply."}},"required":["master_id"],"additionalProperties":false},"SlideDeckWithGroup":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"group":{"allOf":[{"$ref":"#/components/schemas/SlideElement"},{"description":"The group element just created, spread beside the deck."}]}},"required":["group"]}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."},"GroupInput":{"type":"object","properties":{"element_ids":{"type":"array","items":{"type":"string"},"minItems":1,"description":"Element IDs to group on the slide."}},"required":["element_ids"],"additionalProperties":false},"SlideDeckWithPromotedElements":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"promoted_elements":{"type":"array","items":{"$ref":"#/components/schemas/SlideElement"},"description":"The elements lifted out of the dissolved group, now top-level on the slide."}},"required":["promoted_elements"]}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."},"SlideDeckWithDuplicatedSlide":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"duplicated_slide":{"allOf":[{"$ref":"#/components/schemas/Slide"},{"description":"The newly created copy."}]},"new_index":{"type":"integer","minimum":0,"description":"Position of the copy in `data.slides`."}},"required":["duplicated_slide","new_index"]}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."},"TransitionAllInput":{"type":"object","properties":{"transition":{"type":"object","properties":{"type":{"type":"string","enum":["none","fade","slide-left","slide-right","slide-up","slide-down","dissolve","zoom-in","zoom-out","flip","wipe","split","cover","uncover"]},"duration_s":{"type":"number","minimum":0.1,"maximum":10,"description":"Transition duration in seconds (float, 0.1–10). Preferred over speed/duration."},"speed":{"type":"string","enum":["slow","medium","fast"],"description":"Legacy preset — normalized to duration_s (slow=1.0, medium=0.5, fast=0.3)."},"duration":{"type":"number","description":"Legacy duration in ms — normalized to duration_s (duration/1000, clamped 0.1–10)."}},"required":["type"],"additionalProperties":false,"description":"Transition applied to every slide. Provide duration_s (seconds, preferred), speed (legacy preset), or duration (legacy ms)."}},"required":["transition"],"additionalProperties":false},"ReorderInput":{"type":"object","properties":{"order":{"type":"array","items":{"type":"integer","minimum":0},"description":"New slide order — array of original indices in the desired sequence."}},"required":["order"],"additionalProperties":false},"DeckSettingsInput":{"type":"object","properties":{"theme":{},"aspect_ratio":{"type":"string","enum":["16:9","4:3"]},"default_background":{},"defaultBackground":{"description":"Camel-case alias accepted by the SDK."},"show_slide_numbers":{"type":"boolean"},"showSlideNumbers":{"type":"boolean","description":"Camel-case alias accepted by the SDK (AMB-6729)."}},"additionalProperties":false},"MasterSlidesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MasterSlide"}}},"required":["data"]},"CreateMasterInput":{"type":"object","properties":{"name":{"type":"string"},"background":{},"elements":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"additionalProperties":false},"UpdateMasterInput":{"type":"object","properties":{"name":{"type":"string"},"background":{},"elements":{"type":"array","items":{"type":"object","additionalProperties":{}}},"layout":{"type":"string"}},"additionalProperties":false},"MasterSlideInUseError":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["master_slide_in_use"]},"referencing_slide_count":{"type":"integer","exclusiveMinimum":0}},"required":["error","code","referencing_slide_count"]},"SlideDeckWithOccurrences":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"occurrences_changed":{"type":"integer","minimum":0}},"required":["occurrences_changed"]}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."},"FindReplaceInput":{"type":"object","properties":{"find":{"type":"string","minLength":1,"maxLength":10000},"replace":{"type":"string","maxLength":10000},"match_case":{"type":"boolean"}},"required":["find","replace"],"additionalProperties":false},"SlideDeckWithReplacements":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"replacements_count":{"type":"integer","minimum":0}},"required":["replacements_count"]}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."},"ReplaceShapesInput":{"type":"object","properties":{"find":{"type":"string","minLength":1},"image_url":{"type":"string"},"match_case":{"type":"boolean"},"replace_method":{"type":"string","enum":["CENTER_INSIDE","CENTER_CROP"]}},"required":["find","image_url"],"additionalProperties":false},"ApplyTemplateInput":{"type":"object","properties":{"template_id":{"type":"string","minLength":1,"description":"ID of the template to apply (e.g. `business-pitch`)."},"scope":{"type":"string","enum":["all","current_slide"],"description":"`all` repaints the entire deck with the template; `current_slide` replaces just one slide with the template's first slide."},"current_slide_index":{"type":"integer","minimum":0,"description":"Required when `scope = current_slide`. Zero-based index of the slide to replace."},"placeholders":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of `{{key}}` → value substitutions. Unknown keys are left literal so the user can spot them."}},"required":["template_id","scope"],"additionalProperties":false},"WorkspaceUserRef":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"type":{"type":["string","null"]},"email":{"type":"string"},"is_self":{"type":"boolean"}},"required":["id","display_name","type","email","is_self"]},"CrmWorkspaceUsersListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceUserRef"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"AddressBookEntry":{"type":"object","properties":{"email":{"type":"string"},"name":{"type":["string","null"]},"source":{"type":"string","enum":["contact","private"]},"contact_id":{"type":"string","format":"uuid"},"user_contact_id":{"type":"string","format":"uuid"}},"required":["email","name","source"]},"AddressBookListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AddressBookEntry"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"AddressBookPurgeResponse":{"type":"object","properties":{"purged":{"type":"integer","minimum":0}},"required":["purged"]},"AddressBookPurgeInput":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"],"additionalProperties":false},"PromotionCandidate":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":["string","null"]},"company_name":{"type":["string","null"]},"owner_id":{"type":["string","null"],"format":"uuid"},"last_contacted_at":{"type":["string","null"]}},"required":["id","name","email","company_name","owner_id","last_contacted_at"]},"PromotionCandidatesResponse":{"type":"object","properties":{"email":{"type":"string"},"candidates":{"type":"array","items":{"$ref":"#/components/schemas/PromotionCandidate"}}},"required":["email","candidates"]},"PromoteUserContactResponse":{"type":"object","properties":{"contact_id":{"type":"string","format":"uuid"},"created":{"type":"boolean"}},"required":["contact_id","created"]},"PromoteUserContactInput":{"type":"object","properties":{"target_contact_id":{"type":["string","null"],"format":"uuid"}},"additionalProperties":false},"CrmPropertyDefinition":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"entity_type":{"$ref":"#/components/schemas/CrmPropertyEntityType"},"key":{"type":"string"},"label":{"type":"string"},"field_type":{"$ref":"#/components/schemas/CrmPropertyFieldType"},"options":{"type":"array","items":{"type":"string"}},"relation_target":{"anyOf":[{"$ref":"#/components/schemas/CrmRelationTarget"},{"type":"null"}]},"required":{"type":"boolean"},"sort_order":{"type":"number"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","workspace_id","entity_type","key","label","field_type","options","relation_target","required","sort_order","created_at","updated_at"]},"CrmPropertyEntityType":{"type":"string","enum":["contact","company","deal"]},"CrmPropertyFieldType":{"type":"string","enum":["text","number","select","multi_select","date","checkbox","url","email","phone","relation"]},"CrmRelationTarget":{"type":"string","enum":["contact","company","deal"]},"CrmPropertyDefinitionsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CrmPropertyDefinition"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"CrmPropertyDefinitionResponse":{"type":"object","properties":{"definition":{"$ref":"#/components/schemas/CrmPropertyDefinition"}},"required":["definition"]},"CrmPropertyDefinitionCreateInput":{"type":"object","properties":{"entity_type":{"$ref":"#/components/schemas/CrmPropertyEntityType"},"key":{"type":"string","minLength":1,"maxLength":100},"label":{"type":"string","minLength":1,"maxLength":200},"field_type":{"$ref":"#/components/schemas/CrmPropertyFieldType"},"options":{"type":"array","items":{"type":"string"}},"relation_target":{"$ref":"#/components/schemas/CrmRelationTarget"},"required":{"type":"boolean"},"sort_order":{"type":"number"}},"required":["entity_type","key","label","field_type"],"additionalProperties":false},"CrmPropertyDefinitionUpdateInput":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"options":{"type":"array","items":{"type":"string"}},"required":{"type":"boolean"},"sort_order":{"type":"number"}},"additionalProperties":false},"CrmSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]},"CrmMetricsResponse":{"type":"object","properties":{"deals_by_stage":{"type":"array","items":{"type":"object","properties":{"stage_name":{"type":"string"},"count":{"type":"integer"},"total_amount":{"type":"number"}},"required":["stage_name","count","total_amount"]}},"total_pipeline_value":{"type":"number"},"deals_won_count":{"type":"integer"},"deals_lost_count":{"type":"integer"},"avg_deal_value":{"type":"number"},"weighted_pipeline":{"type":"number"}},"required":["deals_by_stage","total_pipeline_value","deals_won_count","deals_lost_count","avg_deal_value","weighted_pipeline"]},"CrmReportsResponse":{"type":"object","properties":{"period":{"type":"string","enum":["this_month","this_quarter","ytd","all_time"]},"generated_at":{"type":"string"},"revenue_ytd":{"type":"object","properties":{"months":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string"},"revenue":{"type":"number"},"deals_closed":{"type":"integer"}},"required":["month","revenue","deals_closed"]}},"total_ytd":{"type":"number"},"total_prev_year":{"type":"number"},"yoy_growth_pct":{"type":["number","null"]},"avg_monthly_revenue":{"type":"number"},"deals_closed_ytd":{"type":"integer"}},"required":["months","total_ytd","total_prev_year","yoy_growth_pct","avg_monthly_revenue","deals_closed_ytd"]},"deals_by_source":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"label":{"type":"string"},"open_count":{"type":"integer"},"open_value":{"type":"number"},"won_count":{"type":"integer"},"won_value":{"type":"number"},"lost_count":{"type":"integer"},"total_count":{"type":"integer"}},"required":["source","label","open_count","open_value","won_count","won_value","lost_count","total_count"]}},"total_deals":{"type":"integer"},"total_open_value":{"type":"number"},"total_won_value":{"type":"number"}},"required":["rows","total_deals","total_open_value","total_won_value"]},"pipeline_by_owner":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","properties":{"owner_id":{"type":"string"},"owner_name":{"type":"string"},"owner_email":{"type":["string","null"]},"deal_count":{"type":"integer"},"total_open_value":{"type":"number"},"weighted_value":{"type":"number"},"won_value":{"type":"number"},"by_stage":{"type":"array","items":{"type":"object","properties":{"stage_id":{"type":"string"},"stage_name":{"type":"string"},"count":{"type":"integer"},"value":{"type":"number"},"sort_order":{"type":"integer"}},"required":["stage_id","stage_name","count","value","sort_order"]}}},"required":["owner_id","owner_name","owner_email","deal_count","total_open_value","weighted_value","won_value","by_stage"]}},"stages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"sort_order":{"type":"integer"}},"required":["id","name","sort_order"]}},"total_open_value":{"type":"number"},"total_weighted_value":{"type":"number"},"total_won_value":{"type":"number"}},"required":["rows","stages","total_open_value","total_weighted_value","total_won_value"]},"activity_metrics":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string"},"user_name":{"type":"string"},"user_email":{"type":["string","null"]},"notes":{"type":"integer"},"calls":{"type":"integer"},"emails":{"type":"integer"},"meetings":{"type":"integer"},"tasks":{"type":"integer"},"chats":{"type":"integer"},"total":{"type":"integer"},"auto_count":{"type":"integer","description":"Of `total`, how many were auto-logged from Mail/Chat/Calendar rather than logged by hand (CRM.md P4/P5)."},"total_duration_minutes":{"type":"integer"}},"required":["user_id","user_name","user_email","notes","calls","emails","meetings","tasks","chats","total","auto_count","total_duration_minutes"]}},"totals":{"type":"object","properties":{"notes":{"type":"integer"},"calls":{"type":"integer"},"emails":{"type":"integer"},"meetings":{"type":"integer"},"tasks":{"type":"integer"},"chats":{"type":"integer"},"total":{"type":"integer"}},"required":["notes","calls","emails","meetings","tasks","chats","total"]},"period_start":{"type":["string","null"]},"period_end":{"type":["string","null"]}},"required":["rows","totals","period_start","period_end"]}},"required":["period","generated_at","revenue_ytd","deals_by_source","pipeline_by_owner","activity_metrics"]},"Contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"owner_id":{"type":["string","null"],"format":"uuid"},"type":{"$ref":"#/components/schemas/ContactType"},"name":{"type":"string"},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"company_id":{"type":["string","null"],"format":"uuid"},"title":{"type":["string","null"]},"website":{"type":["string","null"]},"industry":{"type":["string","null"]},"lifecycle_stage":{"anyOf":[{"$ref":"#/components/schemas/LifecycleStage"},{"type":"null"}]},"custom_properties":{"type":["object","null"],"additionalProperties":{}},"lead_score":{"type":"integer","description":"Sum of matched scoring-rule points. Defaults to 0."},"avatar_url":{"type":["string","null"]},"last_contacted_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"company":{"anyOf":[{"$ref":"#/components/schemas/CompanyRef"},{"type":"null"}]},"owner":{"anyOf":[{"$ref":"#/components/schemas/CrmUserRef"},{"type":"null"}]},"file_count":{"type":"integer","minimum":0},"activity_count":{"type":"integer","minimum":0}},"required":["id","owner_id","type","name","email","phone","company_id","title","website","industry","lifecycle_stage","lead_score","avatar_url","last_contacted_at","created_at","updated_at","file_count","activity_count"]},"ContactType":{"type":"string","enum":["person","company"],"description":"`person` is a human contact; `company` is the organisation entity."},"LifecycleStage":{"type":"string","enum":["subscriber","lead","mql","sql","opportunity","customer","evangelist"],"description":"HubSpot-style funnel stage. Drives default board columns and per-stage automation."},"CompanyRef":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"industry":{"type":["string","null"]},"website":{"type":["string","null"]}},"required":["id","name"]},"CrmUserRef":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]},"ContactsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"ContactResponse":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/Contact"}},"required":["contact"]},"DuplicateContactError":{"type":"object","properties":{"error":{"type":"string"},"contact_id":{"type":"string"},"contact_name":{"type":"string"}},"required":["error","contact_id","contact_name"]},"ContactCreateInput":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ContactType"},"name":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"company_id":{"type":["string","null"]},"title":{"type":["string","null"]},"website":{"type":["string","null"]},"industry":{"type":["string","null"]},"lifecycle_stage":{"anyOf":[{"$ref":"#/components/schemas/LifecycleStage"},{"type":"null"}]},"custom_properties":{"type":"object","additionalProperties":{}}},"additionalProperties":false,"description":"Create a CRM contact. `name` is the canonical field; `first_name`/`last_name` are accepted as a HubSpot-style alias and concatenated to `name` server-side. `type` defaults to `person` when `first_name`/`last_name` are provided. Sending both `name` and `first_name`/`last_name` with conflicting values 400s. Unknown keys are rejected with 400 so a mistyped field (e.g. camelCase `customProperties`) fails loudly instead of silently dropping data."},"ContactBatchResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ContactMergeResponse":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/Contact"},"activities_moved":{"type":"integer"},"deals_moved":{"type":"integer"},"contacts_relinked":{"type":"integer"}},"required":["contact","activities_moved","deals_moved","contacts_relinked"]},"ContactMergeInput":{"type":"object","properties":{"primary_id":{"type":"string","format":"uuid"},"secondary_id":{"type":"string","format":"uuid"},"field_overrides":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"]},"title":{"type":["string","null"]},"website":{"type":["string","null"]},"industry":{"type":["string","null"]},"lifecycle_stage":{"anyOf":[{"$ref":"#/components/schemas/LifecycleStage"},{"type":"null"}]},"custom_properties":{"type":["object","null"],"additionalProperties":{}}},"additionalProperties":false}},"required":["primary_id","secondary_id"],"additionalProperties":false},"ContactBulkResultResponse":{"type":"object","properties":{"updated":{"type":"integer"},"skipped":{"type":"integer"},"errors":{"type":"array","items":{"type":"string"}}},"required":["updated"]},"ContactBulkIdsInput":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1}},"required":["ids"],"additionalProperties":false},"ContactBulkUpdateInput":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1},"lifecycle_stage":{"anyOf":[{"$ref":"#/components/schemas/LifecycleStage"},{"type":"null"}]},"owner_id":{"type":["string","null"],"format":"uuid"},"company_id":{"type":["string","null"],"format":"uuid"},"industry":{"type":["string","null"]}},"required":["ids"],"additionalProperties":false},"ContactImportPreviewResponse":{"type":"object","properties":{"headers":{"type":"array","items":{"type":"string"}},"total_rows":{"type":"integer"},"preview":{"type":"array","items":{"type":"object","additionalProperties":{"type":"string"}}}},"required":["headers","total_rows","preview"]},"ContactImportResultResponse":{"type":"object","properties":{"result":{"type":"object","properties":{"total":{"type":"integer"},"created":{"type":"integer"},"updated":{"type":"integer"},"skipped":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"row":{"type":"integer"},"error":{"type":"string"}},"required":["row","error"]}}},"required":["total","created","updated","skipped","errors"]}},"required":["result"]},"ContactId":{"type":"string","format":"uuid"},"ContactUpdateInput":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"company_id":{"type":["string","null"]},"title":{"type":["string","null"]},"website":{"type":["string","null"]},"industry":{"type":["string","null"]},"lifecycle_stage":{"anyOf":[{"$ref":"#/components/schemas/LifecycleStage"},{"type":"null"}]},"custom_properties":{"type":["object","null"],"additionalProperties":{}}},"additionalProperties":false},"CrmActivity":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"$ref":"#/components/schemas/CrmActivityType"},"subject":{"type":["string","null"]},"body":{"type":["string","null"]},"contact_id":{"type":["string","null"],"format":"uuid"},"deal_id":{"type":["string","null"],"format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"occurred_at":{"type":["string","null"]},"duration_minutes":{"type":["integer","null"]},"source":{"$ref":"#/components/schemas/ActivitySource"},"created_at":{"type":["string","null"]},"opened_at":{"type":["string","null"]},"user":{"anyOf":[{"$ref":"#/components/schemas/CrmUserRef"},{"type":"null"}]}},"required":["id","type","subject","body","contact_id","deal_id","user_id","occurred_at","duration_minutes","source","created_at"]},"CrmActivityType":{"type":"string","enum":["note","call","email","meeting","task","chat"],"description":"Activity timeline event type. Used for filtering and badges in the UI. Mirrors the `activities.type` column enum at apps/api/src/db/schema.ts."},"ActivitySource":{"type":"string","enum":["manual","auto"],"description":"`manual` = user-logged. `auto` = emitted by the EventBus (mail send, deal stage change, calendar event)."},"ContactActivitiesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CrmActivity"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ScoreBreakdownEntry":{"type":"object","properties":{"ruleId":{"type":"string","format":"uuid"},"ruleName":{"type":"string"},"field":{"type":"string"},"points":{"type":"integer"},"matched":{"type":"boolean"}},"required":["ruleId","ruleName","field","points","matched"]},"ContactScoreResponse":{"type":"object","properties":{"score":{"type":"integer"},"breakdown":{"type":"array","items":{"$ref":"#/components/schemas/ScoreBreakdownEntry"}}},"required":["score","breakdown"]},"ContactFile":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"file_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":["integer","null"]},"attached_at":{"type":["string","null"]},"attached_by":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"}},"required":["id","display_name"]}},"required":["id","file_id","name","mime_type","size_bytes","attached_at","attached_by"]},"ContactFilesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactFile"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ContactFileResponse":{"type":"object","properties":{"file":{"$ref":"#/components/schemas/ContactFile"}},"required":["file"]},"ContactFileAttachInput":{"type":"object","properties":{"file_id":{"type":"string","format":"uuid"}},"required":["file_id"],"additionalProperties":false},"ContactPhotoUploadResponse":{"type":"object","properties":{"avatar_url":{"type":"string"}},"required":["avatar_url"]},"ContactGroup":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"color":{"type":["string","null"]},"sort_order":{"type":["integer","null"]},"member_count":{"type":"integer"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","color","sort_order","member_count","created_at"]},"ContactGroupsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactGroup"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ContactGroupResponse":{"type":"object","properties":{"group":{"$ref":"#/components/schemas/ContactGroup"}},"required":["group"]},"DuplicateContactGroupError":{"type":"object","properties":{"error":{"type":"string"},"group_id":{"type":"string"},"group_name":{"type":"string"}},"required":["error","group_id","group_name"]},"ContactGroupCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"color":{"type":"string"}},"required":["name"],"additionalProperties":false},"ContactGroupUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"color":{"type":"string"},"sort_order":{"type":"integer"}},"additionalProperties":false},"ContactGroupMemberItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":["string","null"]},"type":{"type":"string","enum":["person","company"]}},"required":["id","name","email","type"]},"ContactGroupMembersListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactGroupMemberItem"}}},"required":["data"]},"ContactGroupMembersUpdateResponse":{"type":"object","properties":{"added_count":{"type":"integer"},"removed_count":{"type":"integer"},"members":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":["string","null"]},"type":{"type":"string","enum":["person","company"]}},"required":["id","name","email","type"]}}},"required":["added_count","removed_count"]},"ContactGroupMembersInput":{"type":"object","properties":{"add":{"type":"array","items":{"type":"string"}},"remove":{"type":"array","items":{"type":"string"}}},"additionalProperties":false},"Deal":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"amount":{"type":["number","null"]},"currency":{"type":["string","null"]},"pipeline_id":{"type":["string","null"],"format":"uuid"},"stage_id":{"type":["string","null"],"format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid"},"company_id":{"type":["string","null"],"format":"uuid"},"owner_id":{"type":["string","null"],"format":"uuid"},"close_date":{"type":["string","null"]},"probability":{"type":["integer","null"]},"status":{"$ref":"#/components/schemas/DealStatus"},"lost_reason":{"type":["string","null"]},"custom_properties":{"type":["object","null"],"additionalProperties":{}},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"contact":{"anyOf":[{"$ref":"#/components/schemas/ContactRef"},{"type":"null"}]},"company":{"anyOf":[{"$ref":"#/components/schemas/CompanyRef"},{"type":"null"}]},"stage":{"anyOf":[{"$ref":"#/components/schemas/StageRef"},{"type":"null"}]},"pipeline":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]},"owner":{"anyOf":[{"$ref":"#/components/schemas/CrmUserRef"},{"type":"null"}]},"line_item_count":{"type":"integer"},"quote_status":{"anyOf":[{"$ref":"#/components/schemas/QuoteStatus"},{"type":"null"}]},"file_count":{"type":"integer"},"activity_count":{"type":"integer"},"line_items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"deal_id":{"type":"string","format":"uuid"},"product_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"quantity":{"type":"number"},"unit_price":{"type":"number"},"amount":{"type":"number"},"sort_order":{"type":"integer"},"created_at":{"type":["string","null"]}},"required":["id","deal_id","product_id","name","description","quantity","unit_price","amount","sort_order","created_at"]}}},"required":["id","title","amount","currency","pipeline_id","stage_id","contact_id","company_id","owner_id","close_date","probability","status","lost_reason","created_at","updated_at"]},"DealStatus":{"type":"string","enum":["open","won","lost"],"description":"Lifecycle of a deal. `won` and `lost` close the deal; `lost` requires a `lost_reason`."},"ContactRef":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":["string","null"]}},"required":["id","name"]},"StageRef":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"probability":{"type":["integer","null"]}},"required":["id","name","probability"]},"QuoteStatus":{"type":"string","enum":["draft","sent","viewed","accepted","rejected","expired"],"description":"Quote lifecycle. `accepted`/`rejected` are terminal; `viewed` is recorded by the open-tracking pixel."},"DealsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Deal"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"DealResponse":{"type":"object","properties":{"deal":{"$ref":"#/components/schemas/Deal"}},"required":["deal"]},"DuplicateDealError":{"type":"object","properties":{"error":{"type":"string"},"deal_id":{"type":"string"},"deal_title":{"type":"string"}},"required":["error","deal_id","deal_title"]},"DealCreateInput":{"type":"object","properties":{"title":{"type":"string"},"amount":{"type":["number","null"]},"currency":{"type":"string"},"pipeline_id":{"type":"string"},"stage_id":{"type":"string"},"contact_id":{"type":["string","null"]},"primary_contact_id":{"type":["string","null"],"description":"Alias for `contact_id`. Either is accepted; sending both with different values returns 400."},"company_id":{"type":["string","null"]},"owner_id":{"type":["string","null"]},"close_date":{"type":["string","null"]},"probability":{"type":"integer"},"status":{"$ref":"#/components/schemas/DealStatus"},"lost_reason":{"type":["string","null"]},"custom_properties":{"type":"object","additionalProperties":{}},"confirm_zero":{"type":"boolean"}},"required":["title"],"additionalProperties":false},"DealBatchResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Deal"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"DealId":{"type":"string","format":"uuid"},"DealUpdateInput":{"type":"object","properties":{"title":{"type":"string"},"amount":{"type":["number","null"]},"currency":{"type":"string"},"pipeline_id":{"type":"string"},"stage_id":{"type":"string"},"contact_id":{"type":["string","null"]},"primary_contact_id":{"type":["string","null"],"description":"Alias for `contact_id`. Either is accepted; sending both with different values returns 400."},"company_id":{"type":["string","null"]},"owner_id":{"type":["string","null"]},"close_date":{"type":["string","null"]},"probability":{"type":"integer"},"status":{"$ref":"#/components/schemas/DealStatus"},"lost_reason":{"type":["string","null"]},"custom_properties":{"type":"object","additionalProperties":{}},"confirm_zero":{"type":"boolean"}},"additionalProperties":false},"DealActivitiesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CrmActivity"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"DealBulkResultResponse":{"type":"object","properties":{"updated":{"type":"integer"},"skipped":{"type":"integer"},"errors":{"type":"array","items":{"type":"string"}}},"required":["updated"]},"DealBulkUpdateInput":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1},"stage_id":{"type":["string","null"],"format":"uuid"},"pipeline_id":{"type":["string","null"],"format":"uuid"},"owner_id":{"type":["string","null"],"format":"uuid"},"status":{"$ref":"#/components/schemas/DealStatus"},"lost_reason":{"type":["string","null"]}},"required":["ids"],"additionalProperties":false},"DealLineItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"deal_id":{"type":"string","format":"uuid"},"product_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"quantity":{"type":"number"},"unit_price":{"type":"number"},"amount":{"type":"number"},"billing_interval":{"anyOf":[{"$ref":"#/components/schemas/CrmBillingInterval"},{"type":"null"}]},"sort_order":{"type":"integer"},"created_at":{"type":["string","null"]}},"required":["id","deal_id","product_id","name","description","quantity","unit_price","amount","billing_interval","sort_order","created_at"]},"CrmBillingInterval":{"type":"string","enum":["one_time","monthly","quarterly","yearly"]},"DealLineItemsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DealLineItem"}},"total":{"type":"integer","minimum":0},"recurring_total":{"type":"number"},"billing_interval":{"anyOf":[{"$ref":"#/components/schemas/CrmBillingInterval"},{"type":"null"}]},"has_more":{"type":"boolean"}},"required":["data","total","recurring_total","billing_interval","has_more"]},"DealLineItemResponse":{"type":"object","properties":{"line_item":{"$ref":"#/components/schemas/DealLineItem"},"deal_total":{"type":"number"}},"required":["line_item"]},"DealLineItemCreateInput":{"type":"object","properties":{"product_id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"quantity":{"type":"number","exclusiveMinimum":0},"unit_price":{"type":"number","minimum":0},"discount_percent":{"type":"number","minimum":0,"maximum":100},"billing_interval":{"anyOf":[{"$ref":"#/components/schemas/CrmBillingInterval"},{"type":"null"}]},"sort_order":{"type":"integer"},"sync_deal_amount":{"type":"boolean"}},"required":["quantity","unit_price"],"additionalProperties":false},"DealLineItemUpdateInput":{"type":"object","properties":{"product_id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"quantity":{"type":"number","exclusiveMinimum":0},"unit_price":{"type":"number","minimum":0},"discount_percent":{"type":"number","minimum":0,"maximum":100},"billing_interval":{"anyOf":[{"$ref":"#/components/schemas/CrmBillingInterval"},{"type":"null"}]},"sort_order":{"type":"integer"},"sync_deal_amount":{"type":"boolean"}},"additionalProperties":false},"DealLineItemDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"deal_total":{"type":"number"}},"required":["success"]},"DealFile":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"file_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":["integer","null"]},"attached_at":{"type":["string","null"]},"attached_by":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"}},"required":["id","display_name"]}},"required":["id","file_id","name","mime_type","size_bytes","attached_at","attached_by"]},"DealFilesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DealFile"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"DealFileResponse":{"type":"object","properties":{"file":{"$ref":"#/components/schemas/DealFile"}},"required":["file"]},"DealFileAttachInput":{"type":"object","properties":{"file_id":{"type":"string","format":"uuid"}},"required":["file_id"],"additionalProperties":false},"DealTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"title_template":{"type":["string","null"]},"pipeline_id":{"type":["string","null"],"format":"uuid"},"stage_id":{"type":["string","null"],"format":"uuid"},"amount":{"type":["number","null"]},"currency":{"type":"string"},"probability":{"type":["integer","null"]},"close_date_offset_days":{"type":["integer","null"]},"custom_properties":{"type":"object","additionalProperties":{}},"is_active":{"type":"boolean"},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"line_items":{"type":"array","items":{"$ref":"#/components/schemas/DealTemplateLineItem"}},"pipeline":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]},"stage":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]}},"required":["id","workspace_id","name","description","title_template","pipeline_id","stage_id","amount","currency","probability","close_date_offset_days","custom_properties","is_active","created_by","created_at","updated_at","line_items","pipeline","stage"]},"DealTemplateLineItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"template_id":{"type":"string","format":"uuid"},"product_id":{"type":["string","null"],"format":"uuid"},"sort_order":{"type":"integer"},"name":{"type":"string"},"description":{"type":["string","null"]},"quantity":{"type":"number"},"unit_price":{"type":"number"},"discount_percent":{"type":"number"},"product":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"sku":{"type":["string","null"]}},"required":["id","name","sku"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","template_id","product_id","sort_order","name","description","quantity","unit_price","discount_percent","product","created_at","updated_at"]},"DealTemplatesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DealTemplate"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"DealTemplateResponse":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/DealTemplate"}},"required":["template"]},"DealTemplateCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"title_template":{"type":["string","null"]},"pipeline_id":{"type":["string","null"],"format":"uuid"},"stage_id":{"type":["string","null"],"format":"uuid"},"amount":{"type":["number","null"],"minimum":0},"currency":{"type":"string"},"probability":{"type":["integer","null"],"minimum":0,"maximum":100},"close_date_offset_days":{"type":["integer","null"]},"custom_properties":{"type":"object","additionalProperties":{}},"is_active":{"type":"boolean"},"line_items":{"type":"array","items":{}}},"required":["name"],"additionalProperties":false},"DealTemplateUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"title_template":{"type":["string","null"]},"pipeline_id":{"type":["string","null"],"format":"uuid"},"stage_id":{"type":["string","null"],"format":"uuid"},"amount":{"type":["number","null"],"minimum":0},"currency":{"type":"string"},"probability":{"type":["integer","null"],"minimum":0,"maximum":100},"close_date_offset_days":{"type":["integer","null"]},"custom_properties":{"type":"object","additionalProperties":{}},"is_active":{"type":"boolean"},"line_items":{"type":"array","items":{}}},"additionalProperties":false},"DealTemplateApplyInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"contact_id":{"type":["string","null"],"format":"uuid"},"company_id":{"type":["string","null"],"format":"uuid"},"close_date":{"type":["string","null"]},"amount_override":{"type":["number","null"]},"stage_id":{"type":["string","null"],"format":"uuid"},"include_line_items":{"type":"boolean"}},"additionalProperties":false},"Pipeline":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"is_default":{"type":["boolean","null"]},"visibility":{"$ref":"#/components/schemas/PipelineVisibility"},"stages":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStage"}}},"required":["id","name","is_default","stages"]},"PipelineVisibility":{"type":"string","enum":["workspace","restricted"]},"PipelineStage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"sort_order":{"type":"integer"},"probability":{"type":["integer","null"]},"required_fields":{"type":["array","null"],"items":{"type":"string"},"description":"Custom-property keys a deal must have filled before it can move into this stage."}},"required":["id","name","sort_order","probability"]},"PipelinesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Pipeline"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"PipelineResponse":{"type":"object","properties":{"pipeline":{"$ref":"#/components/schemas/Pipeline"}},"required":["pipeline"]},"PipelineCreateInput":{"type":"object","properties":{"name":{"type":"string"},"is_default":{"type":"boolean"},"stages":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"sort_order":{"type":"integer"},"probability":{"type":"integer"},"required_fields":{"type":"array","items":{"type":"string"}}},"required":["name"],"additionalProperties":false},"description":"Ordered pipeline stages as a JSON array of objects, each {name, probability?} where probability is the win-odds 0-100. Stage order follows array position; an optional sort_order is accepted for symmetry with update but ignored. Example: [{\"name\":\"Lead\",\"probability\":10},{\"name\":\"Qualified\",\"probability\":40},{\"name\":\"Won\",\"probability\":100}]"},"visibility":{"type":"string","enum":["workspace","restricted"],"description":"workspace (default) shares the pipeline's deals with the whole workspace via the Everyone team; restricted scopes deals to explicit pipeline members."}},"required":["name"],"additionalProperties":false},"PipelineId":{"type":"string","format":"uuid"},"PipelineUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"is_default":{"type":"boolean"},"stages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1},"sort_order":{"type":"integer"},"probability":{"type":["integer","null"],"minimum":0,"maximum":100},"required_fields":{"type":["array","null"],"items":{"type":"string"}}},"required":["name"],"additionalProperties":false}},"visibility":{"$ref":"#/components/schemas/PipelineVisibility"}},"additionalProperties":false},"PipelineAnalyticsResponse":{"type":"object","properties":{"total_pipeline_value":{"type":"number"},"weighted_pipeline":{"type":"number"},"deals_won_value":{"type":"number"},"deals_lost_value":{"type":"number"},"avg_deal_value":{"type":"number"},"win_rate":{"type":"number"},"avg_deal_velocity_days":{"type":"number"},"open_deals_count":{"type":"integer"},"won_deals_count":{"type":"integer"},"lost_deals_count":{"type":"integer"},"forecast_90d":{"type":"number"},"funnel":{"type":"array","items":{"type":"object","properties":{"stage_name":{"type":"string"},"stage_id":{"type":"string","format":"uuid"},"count":{"type":"integer"},"value":{"type":"number"},"probability":{"type":"number"},"weighted_value":{"type":"number"},"sort_order":{"type":"integer"}},"required":["stage_name","stage_id","count","value","probability","weighted_value","sort_order"]}},"revenue_by_owner":{"type":"array","items":{"type":"object","properties":{"owner_id":{"type":"string","format":"uuid"},"owner_name":{"type":"string"},"won_value":{"type":"number"},"open_value":{"type":"number"},"deal_count":{"type":"integer"}},"required":["owner_id","owner_name","won_value","open_value","deal_count"]}},"monthly_trend":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string"},"won":{"type":"number"},"lost":{"type":"number"},"created":{"type":"integer"}},"required":["month","won","lost","created"]}},"activity_breakdown":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"count":{"type":"integer"}},"required":["type","count"]}},"previous":{"type":"object","properties":{"total_pipeline_value":{"type":"number"},"weighted_pipeline":{"type":"number"},"deals_won_value":{"type":"number"},"deals_lost_value":{"type":"number"},"avg_deal_value":{"type":"number"},"win_rate":{"type":"number"},"avg_deal_velocity_days":{"type":"number"},"open_deals_count":{"type":"integer"},"won_deals_count":{"type":"integer"},"lost_deals_count":{"type":"integer"},"forecast_90d":{"type":"number"}},"required":["total_pipeline_value","weighted_pipeline","deals_won_value","deals_lost_value","avg_deal_value","win_rate","avg_deal_velocity_days","open_deals_count","won_deals_count","lost_deals_count","forecast_90d"]}},"required":["total_pipeline_value","weighted_pipeline","deals_won_value","deals_lost_value","avg_deal_value","win_rate","avg_deal_velocity_days","open_deals_count","won_deals_count","lost_deals_count","forecast_90d","funnel","revenue_by_owner","monthly_trend","activity_breakdown"]},"PipelineMemberEntry":{"type":"object","properties":{"type":{"type":"string","enum":["user","team"]},"user_id":{"type":["string","null"],"format":"uuid"},"team_id":{"type":["string","null"],"format":"uuid"},"role":{"type":"string"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"team_name":{"type":["string","null"]},"added_at":{"type":["string","null"]}},"required":["type","role"],"additionalProperties":{}},"PipelineMembersListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PipelineMemberEntry"}}},"required":["data"]},"PipelineMemberAddInput":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"team_id":{"type":"string","format":"uuid"},"role":{"type":"string"}},"additionalProperties":false},"CrmActivityResponse":{"type":"object","properties":{"activity":{"$ref":"#/components/schemas/CrmActivity"},"linked_event_id":{"type":"string","format":"uuid"}},"required":["activity"]},"CrmActivityCreateInput":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/CrmActivityType"},"subject":{"type":"string"},"body":{"type":"string"},"content":{"type":"string","description":"Alias for `body`. Either field is accepted; sending both with different values returns 400."},"contact_id":{"type":["string","null"],"format":"uuid"},"deal_id":{"type":["string","null"],"format":"uuid"},"occurred_at":{"type":"string"},"scheduled_at":{"type":"string"},"location":{"type":"string"},"duration_minutes":{"type":"integer"}},"required":["type"],"additionalProperties":false},"Sequence":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"is_active":{"type":"boolean"},"enrollment_count":{"type":"integer"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/SequenceStep"}},"creator":{"anyOf":[{"$ref":"#/components/schemas/CrmUserRef"},{"type":"null"}]},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","description","is_active","enrollment_count","steps","created_by","created_at","updated_at"]},"SequenceStep":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"step_type":{"$ref":"#/components/schemas/SequenceStepType"},"delay_days":{"type":"integer","minimum":0,"description":"Defaults to 0."},"step_config":{"$ref":"#/components/schemas/SequenceStepConfig"},"sort_order":{"type":"integer","description":"Defaults to position in array (1-indexed)."}},"required":["step_type"]},"SequenceStepType":{"type":"string","enum":["email","wait","task","call","branch"],"description":"Step kind within a sequence. `email` sends an email; `wait` defers the next step by `delay_days`; `task`/`call` create follow-ups; `branch` evaluates `branchRules` to choose the next step."},"SequenceStepConfig":{"type":"object","additionalProperties":{},"description":"Defaults to {}."},"SequencesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Sequence"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"SequenceResponse":{"type":"object","properties":{"sequence":{"$ref":"#/components/schemas/Sequence"}},"required":["sequence"]},"SequenceCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"is_active":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"step_type":{"$ref":"#/components/schemas/SequenceStepType"},"delay_days":{"type":"integer","minimum":0,"description":"Defaults to 0."},"step_config":{"type":"object","additionalProperties":{},"description":"Defaults to {}."},"sort_order":{"type":"integer","description":"Defaults to position in array (1-indexed)."}},"required":["step_type"],"additionalProperties":false},"minItems":1}},"required":["name","steps"],"additionalProperties":false},"SequenceId":{"type":"string","format":"uuid"},"SequenceUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"is_active":{"type":"boolean"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"step_type":{"$ref":"#/components/schemas/SequenceStepType"},"delay_days":{"type":"integer","minimum":0,"description":"Defaults to 0."},"step_config":{"type":"object","additionalProperties":{},"description":"Defaults to {}."},"sort_order":{"type":"integer","description":"Defaults to position in array (1-indexed)."}},"required":["step_type"],"additionalProperties":false}}},"additionalProperties":false},"SequenceProcessResponse":{"type":"object","properties":{"processed":{"type":"integer"},"errors":{"type":"array","items":{"type":"string"}}},"required":["processed"]},"SequenceEnrollment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sequence_id":{"type":"string","format":"uuid"},"contact_id":{"type":"string","format":"uuid"},"enrolled_by":{"type":["string","null"],"format":"uuid"},"current_step_index":{"type":"integer"},"status":{"$ref":"#/components/schemas/EnrollmentStatus"},"next_execute_at":{"type":["string","null"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"contact":{"anyOf":[{"$ref":"#/components/schemas/ContactRef"},{"type":"null"}]},"enrolled_by_user":{"anyOf":[{"$ref":"#/components/schemas/CrmUserRef"},{"type":"null"}]}},"required":["id","sequence_id","contact_id","enrolled_by","current_step_index","status","next_execute_at","started_at","completed_at","created_at"]},"EnrollmentStatus":{"type":"string","enum":["active","completed","paused","bounced","replied","unenrolled"],"description":"State of a single contact's run through a sequence. `bounced`/`replied` are auto-set by inbound email handling."},"SequenceEnrollmentsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SequenceEnrollment"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"SequenceEnrollResponse":{"type":"object","properties":{"enrollment":{"$ref":"#/components/schemas/SequenceEnrollment"}},"required":["enrollment"]},"SequenceEnrollInput":{"type":"object","properties":{"contact_id":{"type":"string","format":"uuid"}},"required":["contact_id"],"additionalProperties":false},"SequenceEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"enrollment_id":{"type":"string","format":"uuid"},"step_sort_order":{"type":["integer","null"]},"event_type":{"type":"string","enum":["email_sent","email_opened","email_replied","email_bounced","step_executed","branch_evaluated"]},"email_id":{"type":["string","null"]},"metadata":{},"created_at":{"type":["string","null"]}},"required":["id","enrollment_id","step_sort_order","event_type","email_id","created_at"]},"SequenceEventsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SequenceEvent"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ScoringField":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["text","number","enum"]}},"required":["key","label","type"]},"ScoringFieldsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ScoringField"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ScoringRecalculateResponse":{"type":"object","properties":{"updated":{"type":"integer"}},"required":["updated"]},"ScoringRule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"field":{"type":"string"},"operator":{"type":"string","description":"Stored operator value. Unknown values remain readable and evaluate as false."},"value":{"type":["string","null"]},"points":{"type":"integer"},"is_active":{"type":["boolean","null"]},"created_by":{"type":["string","null"],"format":"uuid","description":"Nulled when the authoring user is deleted (ADMIN.md P8 — content survives, attribution drops)."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","workspace_id","name","field","operator","value","points","is_active","created_by","created_at","updated_at"]},"ScoringRulesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ScoringRule"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"ScoringRuleResponse":{"type":"object","properties":{"rule":{"$ref":"#/components/schemas/ScoringRule"}},"required":["rule"]},"ScoringRuleCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"field":{"type":"string","minLength":1},"operator":{"$ref":"#/components/schemas/ScoringOperator"},"value":{"type":"string"},"points":{"type":"integer"},"is_active":{"type":"boolean"}},"required":["name","field","operator","points"],"additionalProperties":false},"ScoringOperator":{"type":"string","enum":["equals","not_equals","contains","not_contains","is_set","is_not_set","greater_than","less_than"],"description":"Comparison operator for a lead-scoring rule."},"ScoringRuleUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"field":{"type":"string","minLength":1},"operator":{"type":"string","description":"PATCH preserves unknown operator values for forward compatibility."},"value":{"type":["string","null"]},"points":{"type":"integer"},"is_active":{"type":"boolean"}},"additionalProperties":false},"Quote":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"deal_id":{"type":["string","null"],"format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid"},"company_id":{"type":["string","null"],"format":"uuid"},"quote_number":{"type":"string"},"title":{"type":"string"},"status":{"$ref":"#/components/schemas/QuoteStatus"},"subtotal":{"type":"number"},"tax_rate":{"type":"number"},"tax_amount":{"type":"number"},"discount_type":{"anyOf":[{"$ref":"#/components/schemas/QuoteDiscountType"},{"type":"null"}]},"discount_value":{"type":"number"},"discount_amount":{"type":"number"},"total":{"type":"number"},"recurring_total":{"type":"number"},"billing_interval":{"anyOf":[{"$ref":"#/components/schemas/CrmBillingInterval"},{"type":"null"}]},"recurring_by_interval":{"type":"array","items":{"type":"object","properties":{"billing_interval":{"$ref":"#/components/schemas/CrmBillingInterval"},"amount":{"type":"number"}},"required":["billing_interval","amount"]}},"currency":{"type":"string"},"notes":{"type":["string","null"]},"terms":{"type":["string","null"]},"valid_until":{"type":["string","null"]},"sent_at":{"type":["string","null"]},"sent_to_email":{"type":["string","null"]},"accepted_at":{"type":["string","null"]},"rejected_at":{"type":["string","null"]},"owner_id":{"type":["string","null"],"format":"uuid"},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"line_items":{"type":"array","items":{"$ref":"#/components/schemas/QuoteLineItem"}},"deal":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"}},"required":["id","title"]},"contact":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":["string","null"]}},"required":["id","name","email"]},"company":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]},"owner":{"anyOf":[{"$ref":"#/components/schemas/CrmUserRef"},{"type":"null"}]}},"required":["id","workspace_id","deal_id","contact_id","company_id","quote_number","title","status","subtotal","tax_rate","tax_amount","discount_type","discount_value","discount_amount","total","recurring_total","billing_interval","recurring_by_interval","currency","notes","terms","valid_until","sent_at","sent_to_email","accepted_at","rejected_at","owner_id","created_by","created_at","updated_at","line_items","deal","contact","company","owner"]},"QuoteDiscountType":{"type":"string","enum":["percent","fixed"],"description":"Discount unit for a quote. `percent` = 10 means 10%; `fixed` = 10 means $10."},"QuoteLineItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sort_order":{"type":"integer"},"name":{"type":"string"},"description":{"type":["string","null"]},"quantity":{"type":"number"},"unit_price":{"type":"number"},"amount":{"type":"number"},"billing_interval":{"anyOf":[{"$ref":"#/components/schemas/CrmBillingInterval"},{"type":"null"}]},"contract_term_months":{"type":["integer","null"]}},"required":["id","sort_order","name","description","quantity","unit_price","amount","billing_interval","contract_term_months"]},"QuotesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Quote"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"QuoteResponse":{"type":"object","properties":{"quote":{"$ref":"#/components/schemas/Quote"}},"required":["quote"]},"QuoteCreateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"deal_id":{"type":["string","null"],"format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid"},"company_id":{"type":["string","null"],"format":"uuid"},"quote_number":{"type":"string"},"status":{"$ref":"#/components/schemas/QuoteStatus"},"tax_rate":{"type":"number"},"discount_type":{"anyOf":[{"$ref":"#/components/schemas/QuoteDiscountType"},{"type":"null"}]},"discount_value":{"type":["number","null"]},"currency":{"type":"string"},"notes":{"type":["string","null"]},"terms":{"type":["string","null"]},"valid_until":{"type":["string","null"]},"owner_id":{"type":["string","null"],"format":"uuid"},"line_items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"quantity":{"type":"number","exclusiveMinimum":0},"unit_price":{"type":"number","minimum":0},"billing_interval":{"anyOf":[{"$ref":"#/components/schemas/CrmBillingInterval"},{"type":"null"}]},"contract_term_months":{"type":["integer","null"],"exclusiveMinimum":0},"sort_order":{"type":"integer"}},"required":["name","quantity","unit_price"],"additionalProperties":false}}},"required":["title"],"additionalProperties":false},"QuoteId":{"type":"string","format":"uuid"},"QuoteUpdateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"deal_id":{"type":["string","null"],"format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid"},"company_id":{"type":["string","null"],"format":"uuid"},"quote_number":{"type":"string"},"status":{"$ref":"#/components/schemas/QuoteStatus"},"tax_rate":{"type":"number"},"discount_type":{"anyOf":[{"$ref":"#/components/schemas/QuoteDiscountType"},{"type":"null"}]},"discount_value":{"type":["number","null"]},"currency":{"type":"string"},"notes":{"type":["string","null"]},"terms":{"type":["string","null"]},"valid_until":{"type":["string","null"]},"owner_id":{"type":["string","null"],"format":"uuid"},"line_items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"quantity":{"type":"number","exclusiveMinimum":0},"unit_price":{"type":"number","minimum":0},"billing_interval":{"anyOf":[{"$ref":"#/components/schemas/CrmBillingInterval"},{"type":"null"}]},"contract_term_months":{"type":["integer","null"],"exclusiveMinimum":0},"sort_order":{"type":"integer"}},"required":["name","quantity","unit_price"],"additionalProperties":false}}},"additionalProperties":false},"QuoteSendInput":{"type":"object","properties":{"recipient_email":{"type":"string","format":"email"},"subject":{"type":"string"},"message":{"type":"string"}},"additionalProperties":false},"CrmProduct":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"name":{"type":"string"},"description":{"type":["string","null"]},"unit_price":{"type":"number"},"currency":{"type":"string"},"billing_interval":{"$ref":"#/components/schemas/CrmBillingInterval"},"contract_term_months":{"type":["integer","null"]},"is_active":{"type":"boolean"},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","workspace_id","sku","name","description","unit_price","currency","billing_interval","contract_term_months","is_active","created_by","created_at","updated_at"]},"CrmProductsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CrmProduct"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"CrmProductResponse":{"type":"object","properties":{"product":{"$ref":"#/components/schemas/CrmProduct"}},"required":["product"]},"CrmProductCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"sku":{"type":["string","null"]},"unit_price":{"type":"number","minimum":0},"currency":{"type":"string"},"billing_interval":{"$ref":"#/components/schemas/CrmBillingInterval"},"contract_term_months":{"type":["integer","null"],"exclusiveMinimum":0},"is_active":{"type":"boolean"}},"required":["name","unit_price"],"additionalProperties":false},"ProductId":{"type":"string","format":"uuid"},"CrmProductUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"sku":{"type":["string","null"]},"unit_price":{"type":"number","minimum":0},"currency":{"type":"string"},"billing_interval":{"$ref":"#/components/schemas/CrmBillingInterval"},"contract_term_months":{"type":["integer","null"],"exclusiveMinimum":0},"is_active":{"type":"boolean"}},"additionalProperties":false},"SavedView":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"entity_type":{"$ref":"#/components/schemas/SavedViewEntity"},"name":{"type":"string"},"filters":{"type":"object","additionalProperties":{}},"sort_field":{"type":["string","null"]},"sort_direction":{"type":["string","null"],"enum":["asc","desc",null]},"is_default":{"type":"boolean"},"is_shared":{"type":"boolean"},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","entity_type","name","filters","sort_field","sort_direction","is_default","is_shared","created_by","created_at","updated_at"]},"SavedViewEntity":{"type":"string","enum":["contacts","companies","deals"],"description":"Which list page the saved view applies to. Mirrors crm_saved_views.entity_type enum at apps/api/src/db/schema.ts."},"SavedViewsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SavedView"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"SavedViewResponse":{"type":"object","properties":{"view":{"$ref":"#/components/schemas/SavedView"}},"required":["view"]},"SavedViewCreateInput":{"type":"object","properties":{"entity_type":{"$ref":"#/components/schemas/SavedViewEntity"},"name":{"type":"string","minLength":1},"filters":{"type":"object","additionalProperties":{}},"sort_field":{"type":"string"},"sort_direction":{"type":"string","enum":["asc","desc"]},"is_default":{"type":"boolean"},"is_shared":{"type":"boolean"}},"required":["entity_type","name"],"additionalProperties":false},"SavedViewUpdateInput":{"type":"object","properties":{"entity_type":{"$ref":"#/components/schemas/SavedViewEntity"},"name":{"type":"string","minLength":1},"filters":{"type":"object","additionalProperties":{}},"sort_field":{"type":"string"},"sort_direction":{"type":"string","enum":["asc","desc"]},"is_default":{"type":"boolean"},"is_shared":{"type":"boolean"}},"additionalProperties":false},"Workflow":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"trigger_type":{"$ref":"#/components/schemas/WorkflowTriggerType"},"trigger_config":{"type":"object","additionalProperties":{}},"is_active":{"type":"boolean"},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"actions":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowAction"}},"creator":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"primary_email":{"type":"string"}},"required":["id","display_name","primary_email"]}},"required":["id","name","description","trigger_type","trigger_config","is_active","created_by","created_at","updated_at","actions","creator"]},"WorkflowTriggerType":{"type":"string","enum":["deal_stage_changed","deal_created","deal_won","deal_lost","contact_created","contact_lifecycle_changed","activity_logged","quote_accepted","sequence_bounced"]},"WorkflowAction":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"action_type":{"$ref":"#/components/schemas/WorkflowActionType"},"action_config":{"type":"object","additionalProperties":{}},"sort_order":{"type":"integer"}},"required":["id","action_type","action_config","sort_order"]},"WorkflowActionType":{"type":"string","enum":["create_task","send_email","notify_owner","update_deal","update_contact","create_activity"]},"WorkflowsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Workflow"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WorkflowResponse":{"type":"object","properties":{"workflow":{"$ref":"#/components/schemas/Workflow"}},"required":["workflow"]},"WorkflowCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"trigger_type":{"$ref":"#/components/schemas/WorkflowTriggerType"},"trigger_config":{"type":"object","additionalProperties":{}},"is_active":{"type":"boolean"},"actions":{"type":"array","items":{"type":"object","properties":{"action_type":{"$ref":"#/components/schemas/WorkflowActionType"},"action_config":{"type":"object","additionalProperties":{}},"sort_order":{"type":"integer"}},"required":["action_type","action_config","sort_order"],"additionalProperties":false}}},"required":["name","trigger_type","actions"],"additionalProperties":false},"CrmWorkflowId":{"type":"string","format":"uuid"},"WorkflowUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"trigger_type":{"$ref":"#/components/schemas/WorkflowTriggerType"},"trigger_config":{"type":"object","additionalProperties":{}},"is_active":{"type":"boolean"},"actions":{"type":"array","items":{"type":"object","properties":{"action_type":{"$ref":"#/components/schemas/WorkflowActionType"},"action_config":{"type":"object","additionalProperties":{}},"sort_order":{"type":"integer"}},"required":["action_type","action_config","sort_order"],"additionalProperties":false}}},"additionalProperties":false},"WorkflowLog":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workflow_id":{"type":"string","format":"uuid"},"trigger_event":{"type":"string"},"trigger_resource_id":{"type":["string","null"],"format":"uuid"},"status":{"type":"string","enum":["success","partial","failed"]},"actions_executed":{"type":"array","items":{"type":"object","properties":{"actionId":{"type":"string"},"actionType":{"type":"string"},"status":{"type":"string"},"error":{"type":"string"}},"required":["actionId","actionType","status"]}},"error":{"type":["string","null"]},"executed_at":{"type":["string","null"]}},"required":["id","workflow_id","trigger_event","trigger_resource_id","status","actions_executed","error","executed_at"]},"WorkflowLogsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowLog"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"SchedulerLink":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"owner_id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"location":{"type":["string","null"]},"duration_minutes":{"type":"integer"},"buffer_before_minutes":{"type":"integer"},"buffer_after_minutes":{"type":"integer"},"min_notice_minutes":{"type":"integer"},"max_advance_days":{"type":"integer"},"availability_hours":{},"member_user_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"timezone":{"type":["string","null"]},"auto_create_contact":{"type":"boolean"},"pipeline_id":{"type":["string","null"],"format":"uuid"},"stage_id":{"type":["string","null"],"format":"uuid"},"brand_color":{"type":["string","null"]},"is_active":{"type":"boolean"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"owner_name":{"type":["string","null"]},"owner_avatar_url":{"type":["string","null"]},"owner_username":{"type":["string","null"]},"workspace_slug":{"type":["string","null"]},"booking_count":{"type":"integer"}},"required":["id","workspace_id","owner_id","slug","title","description","location","duration_minutes","buffer_before_minutes","buffer_after_minutes","min_notice_minutes","max_advance_days","member_user_ids","timezone","auto_create_contact","pipeline_id","stage_id","brand_color","is_active","created_at","updated_at","owner_name","owner_avatar_url","owner_username","workspace_slug","booking_count"]},"SchedulerLinksListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SchedulerLink"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"SchedulerLinkResponse":{"type":"object","properties":{"link":{"$ref":"#/components/schemas/SchedulerLink"}},"required":["link"]},"SchedulerLinkCreateInput":{"type":"object","properties":{"slug":{"type":"string","minLength":1},"title":{"type":"string","minLength":1},"description":{"type":["string","null"]},"location":{"type":["string","null"]},"duration_minutes":{"type":"integer","exclusiveMinimum":0},"buffer_before_minutes":{"type":"integer","minimum":0},"buffer_after_minutes":{"type":"integer","minimum":0},"min_notice_minutes":{"type":"integer","minimum":0},"max_advance_days":{"type":"integer","minimum":0},"availability_hours":{},"member_user_ids":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":20,"description":"Round-robin roster: workspace user ids that share this link's bookings. Empty/omitted = solo (owner only). When set, a slot is offered while any member is free and each booking is assigned to the least-loaded free member."},"timezone":{"type":"string"},"auto_create_contact":{"type":"boolean"},"pipeline_id":{"type":["string","null"],"format":"uuid"},"stage_id":{"type":["string","null"],"format":"uuid"},"brand_color":{"type":["string","null"]},"is_active":{"type":"boolean"}},"required":["title"],"additionalProperties":false},"SchedulerLinkId":{"type":"string","format":"uuid"},"SchedulerLinkUpdateInput":{"type":"object","properties":{"slug":{"type":"string","minLength":1},"title":{"type":"string","minLength":1},"description":{"type":["string","null"]},"location":{"type":["string","null"]},"duration_minutes":{"type":"integer","exclusiveMinimum":0},"buffer_before_minutes":{"type":"integer","minimum":0},"buffer_after_minutes":{"type":"integer","minimum":0},"min_notice_minutes":{"type":"integer","minimum":0},"max_advance_days":{"type":"integer","minimum":0},"availability_hours":{},"member_user_ids":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":20,"description":"Round-robin roster: workspace user ids that share this link's bookings. Empty/omitted = solo (owner only). When set, a slot is offered while any member is free and each booking is assigned to the least-loaded free member."},"timezone":{"type":"string"},"auto_create_contact":{"type":"boolean"},"pipeline_id":{"type":["string","null"],"format":"uuid"},"stage_id":{"type":["string","null"],"format":"uuid"},"brand_color":{"type":["string","null"]},"is_active":{"type":"boolean"}},"additionalProperties":false},"SchedulerBooking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"link_id":{"type":"string","format":"uuid"},"link_title":{"type":["string","null"]},"link_slug":{"type":["string","null"]},"owner_id":{"type":"string","format":"uuid"},"event_id":{"type":["string","null"],"format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid"},"assigned_user_id":{"type":["string","null"],"format":"uuid"},"guest_name":{"type":"string"},"guest_email":{"type":"string"},"guest_phone":{"type":["string","null"]},"notes":{"type":["string","null"]},"start_at":{"type":"string"},"end_at":{"type":"string"},"status":{"type":"string"},"cancelled_at":{"type":["string","null"]},"cancel_reason":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","link_id","link_title","link_slug","owner_id","event_id","contact_id","assigned_user_id","guest_name","guest_email","guest_phone","notes","start_at","end_at","status","cancelled_at","cancel_reason","created_at"]},"SchedulerBookingsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SchedulerBooking"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"PublicForm":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"schema":{},"slug":{"type":["string","null"]},"workspace_slug":{"type":["string","null"]},"closed":{"type":"boolean"},"require_auth":{"type":"boolean"},"captcha_enabled":{"type":"boolean"},"stripe_publishable_key":{"type":["string","null"]},"turnstile_site_key":{"type":["string","null"]},"variant_id":{"type":["string","null"]},"allow_multiple_responses":{"type":"boolean"}},"required":["id","title","description","slug","workspace_slug","closed","require_auth","captcha_enabled","stripe_publishable_key"]},"FormSubmitResponse":{"type":"object","properties":{"id":{"type":"string"},"submitted_at":{"type":["string","null"]},"message":{"type":"string"},"redirect_url":{"type":["string","null"]}},"required":["id","submitted_at","message","redirect_url"]},"FormSubmitInput":{"type":"object","properties":{"answers":{"type":"object","additionalProperties":{},"description":"Canonical wire name. Map of field_id -> respondent value. Either `answers` or `data` (alias) is required; sending both with disagreeing values returns 400."},"data":{"type":"object","additionalProperties":{},"description":"Legacy alias for `answers`. Same payload."},"respondent_email":{"type":"string"},"captcha_token":{"type":"string","description":"Cloudflare Turnstile token (when captcha_enabled)."}}},"FormSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]},"FormId":{"type":"string","format":"uuid"},"FormViewInput":{"type":"object","properties":{"sessionId":{"type":"string"},"fieldReached":{"anyOf":[{"type":"string"},{"type":"number"}]},"completed":{"type":"boolean"},"durationMs":{"type":"number"},"variantId":{"type":["string","null"]}},"additionalProperties":{}},"PaymentIntentResponse":{"type":"object","properties":{"client_secret":{"type":"string"},"payment_intent_id":{"type":"string"},"amount":{"type":"number"},"currency":{"type":"string"}},"required":["client_secret","payment_intent_id","amount","currency"]},"StripeWebhookResponse":{"type":"object","properties":{"received":{"type":"boolean"}},"required":["received"]},"FormUploadResponse":{"type":"object","properties":{"file_id":{"type":"string"},"file_name":{"type":"string"},"size_bytes":{"type":"integer","minimum":0},"mime_type":{"type":"string"},"url":{"type":"string"}},"required":["file_id","file_name","size_bytes","mime_type","url"]},"Form":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"owner_id":{"type":["string","null"]},"workspace_id":{"type":"string"},"workspace_slug":{"type":["string","null"]},"schema":{},"settings":{},"is_published":{"type":["boolean","null"]},"slug":{"type":["string","null"]},"closes_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"question_count":{"type":"integer","minimum":0},"response_count":{"type":"integer","minimum":0},"visibility":{"type":"string","enum":["restricted","workspace","link","public"],"description":"Who can reach the form: restricted (explicit grants), workspace, link, or public."},"link_expires_at":{"type":["string","null"],"description":"ISO 8601 expiry of the public link, or null when it does not expire."},"has_password":{"type":"boolean","description":"True when the public link is password-gated. The hash itself is never served."},"link_permission":{"type":"string","enum":["viewer","editor"],"description":"Permission level granted to anyone arriving via the public link."}},"required":["id","title","description","owner_id","workspace_id","workspace_slug","is_published","slug","closes_at","created_at","updated_at","question_count","response_count","visibility","link_expires_at","has_password","link_permission"]},"FormListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Form"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"FormResponseRecord":{"type":"object","properties":{"id":{"type":"string"},"form_id":{"type":"string"},"respondent_id":{"type":["string","null"]},"respondent_email":{"type":["string","null"]},"answers":{"type":"object","additionalProperties":{},"description":"Map of field_id -> respondent value."},"submitted_at":{"type":["string","null"]}},"required":["id","form_id","respondent_id","respondent_email","answers","submitted_at"]},"FormResponseListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FormResponseRecord"}},"total":{"type":"integer"},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["data","total","has_more","limit","offset"]},"FormVariant":{"type":"object","properties":{"id":{"type":"string"},"parent_form_id":{"type":"string","description":"The form being A/B tested."},"variant_form_id":{"type":"string","description":"The standalone form carrying this variant's fields. Fetch it for the overrides."},"name":{"type":"string"},"traffic_weight":{"type":"number","description":"Share of traffic routed to this variant, 0-100. Control serves the remainder."},"is_active":{"type":"boolean"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","parent_form_id","variant_form_id","name","traffic_weight","is_active","created_at","updated_at"]},"FormVariantListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FormVariant"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"FormAnalyticsResponse":{"type":"object","properties":{"totalViews":{"type":"number","description":"Total browser page views of the public form."},"totalResponses":{"type":"number","description":"Total submitted responses."},"completionRate":{"type":["number","null"],"description":"Percentage of views that resulted in a submission (0–100), or null when no views exist. This is NOT a 0–1 fraction.","example":42.86},"averageDurationMs":{"type":["number","null"],"description":"Average time from form load to submission in milliseconds, or null."},"responsesByDay":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"count":{"type":"number"}},"required":["date","count"]},"description":"Daily response counts for the last 30 days."},"fieldDropOff":{"type":"array","items":{"type":"object","properties":{"fieldId":{"type":"string"},"label":{"type":"string"},"reached":{"type":"number"},"answered":{"type":"number"},"dropOffPct":{"type":"number"}},"required":["fieldId","label","reached","answered","dropOffPct"]}},"fieldSummaries":{"type":"array","items":{"type":"object","properties":{"fieldId":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"},"answered":{"type":"number"},"total":{"type":"number"},"data":{}},"required":["fieldId","label","type","answered","total"]}},"viewSource":{"type":"string","enum":["browser"],"description":"Views are counted from browser page loads only; API submissions never increment views."}},"required":["totalViews","totalResponses","completionRate","averageDurationMs","responsesByDay","fieldDropOff","fieldSummaries","viewSource"]},"FormABAnalyticsResponse":{"type":"object","properties":{"control":{"type":"object","properties":{"variantId":{"type":["string","null"]},"name":{"type":"string"},"formId":{"type":"string"},"trafficWeight":{"type":"number"},"views":{"type":"number"},"responses":{"type":"number"},"completionRate":{"type":["number","null"],"description":"Percentage of views that resulted in a submission (0–100), or null when no views exist. This is NOT a 0–1 fraction.","example":42.86},"averageDurationMs":{"type":["number","null"]}},"required":["variantId","name","formId","trafficWeight","views","responses","completionRate","averageDurationMs"]},"variants":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":["string","null"]},"name":{"type":"string"},"formId":{"type":"string"},"trafficWeight":{"type":"number"},"views":{"type":"number"},"responses":{"type":"number"},"completionRate":{"type":["number","null"],"description":"Percentage of views that resulted in a submission (0–100), or null when no views exist. This is NOT a 0–1 fraction.","example":42.86},"averageDurationMs":{"type":["number","null"]}},"required":["variantId","name","formId","trafficWeight","views","responses","completionRate","averageDurationMs"]}}},"required":["control","variants"]},"FormPermissionEntry":{"type":"object","properties":{"type":{"type":"string","enum":["user","team","guest"]},"user_id":{"type":["string","null"],"format":"uuid"},"team_id":{"type":["string","null"],"format":"uuid"},"guest_id":{"type":["string","null"],"format":"uuid"},"role":{"type":"string"},"expires_at":{"type":["string","null"]},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"workspace_email":{"type":["string","null"]},"username":{"type":["string","null"]},"team_name":{"type":["string","null"]},"member_count":{"type":"integer"},"guest_email":{"type":["string","null"]},"guest_name":{"type":["string","null"]}},"required":["type","role"],"additionalProperties":{}},"FormPermissionsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FormPermissionEntry"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]},"pending":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string"},"created_at":{"type":["string","null"]}},"required":["id","email","role","created_at"]}}},"required":["data","total","has_more","pending"]},"FormSetPermissionResponse":{"type":"object","properties":{"form_id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"team_id":{"type":["string","null"],"format":"uuid"},"role":{"type":"string","enum":["viewer","editor"]},"expires_at":{"type":["string","null"]}},"required":["form_id","role"]},"FormSetPermissionInput":{"type":"object","properties":{"role":{"type":"string"},"user_id":{"type":"string"},"team_id":{"type":"string"},"expires_at":{"type":["string","null"]}},"additionalProperties":false},"FormDeletedResponse":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"]},"FormRevokePendingShareResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"FormVisibilityResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"visibility":{"type":"string"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"},"link_permission":{"type":"string","enum":["viewer","editor"]}},"required":["id","visibility","link_expires_at","has_password","link_permission"]},"FormRevokeLinkResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"visibility":{"type":"string","enum":["restricted"]},"link_expires_at":{"type":"null"},"has_password":{"type":"boolean","enum":[false]}},"required":["id","visibility","link_expires_at","has_password"]},"ColorPaletteResponse":{"type":"object","properties":{"calendar":{"type":"object","additionalProperties":{"type":"object","properties":{"background":{"type":"string"},"foreground":{"type":"string"}},"required":["background","foreground"]}},"event":{"type":"object","additionalProperties":{"type":"object","properties":{"background":{"type":"string"},"foreground":{"type":"string"}},"required":["background","foreground"]}}},"required":["calendar","event"]},"AvailabilityResponse":{"type":"object","properties":{"availability":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"},"title":{"type":"string"}},"required":["start","end","title"]}}}},"required":["availability"]},"ConflictMap":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"event_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"start_at":{"type":"string"},"end_at":{"type":"string"}},"required":["event_id","title","start_at","end_at"]}}},"ConflictsResponse":{"type":"object","properties":{"conflicts":{"$ref":"#/components/schemas/ConflictMap"}},"required":["conflicts"]},"OooUserStatus":{"type":"object","properties":{"is_ooo":{"type":"boolean"},"event":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"start_at":{"type":"string"},"end_at":{"type":"string"}},"required":["id","title","start_at","end_at"]}},"required":["is_ooo"]},"OooStatusResponse":{"type":"object","properties":{"ooo_status":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/OooUserStatus"}}},"required":["ooo_status"]},"OooConflictsResponse":{"type":"object","properties":{"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"start_at":{"type":"string"},"end_at":{"type":"string"},"organizer_id":{"type":["string","null"]},"organizer_name":{"type":["string","null"]}},"required":["id","title","start_at","end_at","organizer_id","organizer_name"]}}},"required":["events"]},"UpcomingReminder":{"allOf":[{"$ref":"#/components/schemas/EventReminder"},{"type":"object","properties":{"trigger_at":{"type":["string","null"]},"event_title":{"type":"string"},"event_start_at":{"type":["string","null"]},"event_end_at":{"type":["string","null"]},"event_status":{"$ref":"#/components/schemas/EventStatus"},"event_location":{"type":["string","null"]},"calendar_id":{"type":"string","format":"uuid"}},"required":["trigger_at","event_title","event_start_at","event_end_at","event_status","event_location","calendar_id"]}]},"ReminderMethod":{"type":"string","enum":["popup","email","notification"],"description":"How the reminder fires for the user."},"EventStatus":{"type":"string","enum":["confirmed","tentative","cancelled","outofoffice"],"description":"Event status. `outofoffice` is used by the OOO responder."},"EventReminder":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"event_id":{"type":"string","format":"uuid"},"user_id":{"type":["string","null"],"format":"uuid"},"method":{"$ref":"#/components/schemas/ReminderMethod"},"minutes_before":{"type":"integer","minimum":0},"fired_at":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","event_id","user_id","method","minutes_before","fired_at","created_at"]},"UpcomingReminderListResponse":{"type":"object","properties":{"reminders":{"type":"array","items":{"$ref":"#/components/schemas/UpcomingReminder"}}},"required":["reminders"]},"Calendar":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"},"color":{"type":["string","null"]},"timezone":{"type":"string","description":"IANA TZ database name. Defaults to `America/Los_Angeles`."},"is_default":{"type":"boolean"},"owner_id":{"type":["string","null"],"format":"uuid"},"owner_name":{"type":["string","null"]},"working_hours":{"anyOf":[{"$ref":"#/components/schemas/WorkingHours"},{"type":"null"}]},"source":{"type":["string","null"],"description":"Origin: `local` (user-created) or `google` (synced mirror)."},"external_connection_id":{"type":["string","null"],"format":"uuid"},"external_calendar_id":{"type":["string","null"]},"publish_token":{"type":["string","null"],"description":"Public-feed token. When non-null the calendar is exposed at `/api/calendars/public/{token}/feed.ics`."},"last_synced_at":{"type":["string","null"],"description":"ISO timestamp of the last successful Google sync."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","workspace_id","name","color","timezone","is_default","owner_id","working_hours","publish_token","created_at","updated_at"]},"WorkingHours":{"type":"object","additionalProperties":{"type":"array","prefixItems":[{"type":"string","description":"Start time in `HH:mm` (24h) local to the calendar's timezone."},{"type":"string","description":"End time in `HH:mm`."}],"description":"[start, end] window for that weekday."},"description":"Working-hours configuration. Drives the availability + free/busy heat map."},"CalendarListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Calendar"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"CalendarResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":["string","null"],"format":"uuid"},"name":{"type":"string"},"color":{"type":["string","null"]},"timezone":{"type":"string","description":"IANA TZ database name. Defaults to `America/Los_Angeles`."},"is_default":{"type":"boolean"},"owner_id":{"type":["string","null"],"format":"uuid"},"owner_name":{"type":["string","null"]},"working_hours":{"anyOf":[{"$ref":"#/components/schemas/WorkingHours"},{"type":"null"}]},"source":{"type":["string","null"],"description":"Origin: `local` (user-created) or `google` (synced mirror)."},"external_connection_id":{"type":["string","null"],"format":"uuid"},"external_calendar_id":{"type":["string","null"]},"publish_token":{"type":["string","null"],"description":"Public-feed token. When non-null the calendar is exposed at `/api/calendars/public/{token}/feed.ics`."},"last_synced_at":{"type":["string","null"],"description":"ISO timestamp of the last successful Google sync."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","workspace_id","name","color","timezone","is_default","owner_id","working_hours","publish_token","created_at","updated_at"]},"CalendarCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"color":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},"timezone":{"type":"string"},"is_default":{"type":"boolean"},"working_hours":{"anyOf":[{"type":"object","additionalProperties":{"type":"array","prefixItems":[{"type":"string","description":"Start time in `HH:mm` (24h) local to the calendar's timezone."},{"type":"string","description":"End time in `HH:mm`."}],"description":"[start, end] window for that weekday."}},{"type":"null"}]}},"additionalProperties":false},"CalendarBinaryBody":{"type":"string"},"ExternalOAuthStatusResponse":{"type":"object","properties":{"google_oauth_configured":{"type":"boolean"}},"required":["google_oauth_configured"]},"ExternalAuthUrlResponse":{"type":"object","properties":{"auth_url":{"type":"string","format":"uri"},"state":{"type":"string"}},"required":["auth_url","state"]},"CalendarSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]},"ExternalCalendarConnection":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"provider":{"$ref":"#/components/schemas/ExternalCalendarProvider"},"provider_email":{"type":["string","null"]},"sync_enabled":{"type":"boolean"},"last_sync_at":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","user_id","provider","provider_email","sync_enabled","last_sync_at","created_at"]},"ExternalCalendarProvider":{"type":"string","enum":["google"],"description":"External calendar sync provider. Currently only Google."},"ExternalConnectionListResponse":{"type":"object","properties":{"connections":{"type":"array","items":{"$ref":"#/components/schemas/ExternalCalendarConnection"}}},"required":["connections"]},"CalendarId":{"type":"string","format":"uuid"},"ExternalCalendar":{"type":"object","properties":{"external_id":{"type":"string"},"summary":{"type":"string"},"primary":{"type":"boolean"},"sync_enabled":{"type":"boolean"},"sync_direction":{"$ref":"#/components/schemas/ExternalSyncDirection"},"local_calendar_id":{"type":["string","null"],"format":"uuid"},"color":{"type":["string","null"]}},"required":["external_id","summary","sync_enabled","color"]},"ExternalSyncDirection":{"type":"string","enum":["pull","bidirectional"],"description":"Sync direction for an external calendar. `pull` mirrors external → workspace. `bidirectional` also pushes workspace edits upstream."},"ExternalCalendarsListResponse":{"type":"object","properties":{"calendars":{"type":"array","items":{"$ref":"#/components/schemas/ExternalCalendar"}}},"required":["calendars"]},"ExternalSyncEnableResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"calendar_id":{"type":"string","format":"uuid","description":"The local mirror calendar the external calendar now syncs into."}},"required":["success","calendar_id"]},"ExternalCalendarSyncEnableInput":{"type":"object","properties":{"google_calendar_id":{"type":"string","description":"The Google calendar ID to sync"},"name":{"type":"string","description":"Display name for the mirrored calendar"},"color":{"type":"string","description":"Optional calendar color"}},"required":["google_calendar_id","name"],"additionalProperties":false},"ExternalSyncResult":{"type":"object","properties":{"calendar_id":{"type":"string","format":"uuid"},"created":{"type":"integer","minimum":0},"updated":{"type":"integer","minimum":0},"deleted":{"type":"integer","minimum":0}},"required":["calendar_id","created","updated","deleted"]},"ExternalForceSyncResponse":{"type":"object","properties":{"synced":{"type":"array","items":{"$ref":"#/components/schemas/ExternalSyncResult"}},"errors":{"type":"array","items":{"type":"object","properties":{"calendar_id":{"type":"string","format":"uuid"},"error":{"type":"string"}},"required":["calendar_id","error"]}}},"required":["synced"]},"Event":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":["string","null"],"format":"uuid"},"calendar_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":["string","null"]},"location":{"type":["string","null"]},"start_at":{"type":"string"},"end_at":{"type":"string"},"all_day":{"type":"boolean"},"recurrence_rule":{"type":["string","null"],"description":"RFC 5545 RRULE string. Master events only."},"master_event_id":{"type":["string","null"],"format":"uuid","description":"Set on exception/override rows that split out of a recurring series."},"original_start_at":{"type":["string","null"],"description":"Original RECURRENCE-ID for an exception row."},"excluded_dates":{"type":"array","items":{"type":"string"},"description":"Occurrence dates suppressed from the series (the EXDATE set). Master events only; `[]` elsewhere."},"status":{"$ref":"#/components/schemas/EventStatus"},"visibility":{"$ref":"#/components/schemas/EventVisibility"},"transparency":{"$ref":"#/components/schemas/EventTransparency"},"color":{"type":["string","null"]},"conference_url":{"type":["string","null"],"description":"Video-call URL. New writes are http(s)-gated at the input boundary, but rows predating that guard are not migrated — sanitize before rendering as an href."},"conference_provider":{"anyOf":[{"$ref":"#/components/schemas/ConferenceProvider"},{"type":"null"}]},"creator_id":{"type":["string","null"],"format":"uuid"},"event_type":{"$ref":"#/components/schemas/CalendarEventType"},"dispatch_prompt":{"type":["string","null"],"description":"Agent-dispatch prompt handed to the assignee (D246)."},"dispatch_references":{"type":"array","items":{"$ref":"#/components/schemas/DispatchReference"},"description":"Cross-module + external references for an agent dispatch (D246)."},"confirmation_task_id":{"type":["string","null"],"format":"uuid","description":"The standing confirmation task the assignee accepts by RSVPing (D246)."},"contact_id":{"type":["string","null"],"format":"uuid","description":"CRM contact link (D121/D210)."},"deal_id":{"type":["string","null"],"format":"uuid","description":"CRM deal link (D121/D210)."},"auto_decline_scope":{"type":"string","enum":["new_only","new_and_existing"],"description":"OOO auto-decline reach. Only meaningful when `status === 'outofoffice'` (CALENDAR P5)."},"auto_decline_message":{"type":["string","null"],"description":"Message attached to an OOO decline. Reaches organizers; NEVER free/busy (CALENDAR P2)."},"external_id":{"type":["string","null"],"description":"Originating provider's event id (Google) for a synced mirror row. Null for a local event."},"guests_can_modify":{"type":"boolean"},"guests_can_invite_others":{"type":"boolean"},"guests_can_see_other_guests":{"type":"boolean"},"meeting_notes_doc_id":{"type":["string","null"],"format":"uuid"},"attendees":{"type":"array","items":{"$ref":"#/components/schemas/Attendee"}},"resources":{"type":"array","items":{"$ref":"#/components/schemas/EventResource"}},"reminders":{"type":"array","items":{"$ref":"#/components/schemas/EventReminder"}},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"has_more_attendees":{"type":"boolean"},"total_attendees":{"type":"integer"},"is_task":{"type":"boolean","description":"True for a due-task chip synthesised into an event list, not a stored event."},"task":{"anyOf":[{"$ref":"#/components/schemas/CalendarTaskRef"},{"type":"null"}]},"self_conflicts":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Ids of the creator's own events this new event overlaps."},"attendee_conflicts":{"allOf":[{"$ref":"#/components/schemas/ConflictMap"},{"description":"Double-booked attendees, keyed by user id."}]},"external_invites_sent":{"type":"array","items":{"type":"string"},"description":"Addresses outside the workspace that were emailed an invite."},"ooo_auto_declined":{"type":"object","additionalProperties":{"type":"object","properties":{"title":{"type":"string"},"start_at":{"type":"string"},"end_at":{"type":"string"}},"required":["title","start_at","end_at"]},"description":"Attendees auto-declined because they are OOO, keyed by user id (CALENDAR P5)."},"auto_declined_existing":{"type":"array","items":{"type":"object","properties":{"eventId":{"type":"string","format":"uuid"},"organizerId":{"type":["string","null"],"format":"uuid"}},"required":["eventId","organizerId"]},"description":"Existing events bulk-declined by an OOO block whose scope is `new_and_existing`."},"resource_booking_error":{"type":"string","description":"Set when the event was created but a requested resource could not be booked."}},"required":["id","workspace_id","calendar_id","title","description","location","start_at","end_at","all_day","recurrence_rule","master_event_id","original_start_at","excluded_dates","status","visibility","transparency","color","conference_url","conference_provider","creator_id","event_type","dispatch_prompt","dispatch_references","confirmation_task_id","contact_id","deal_id","auto_decline_scope","auto_decline_message","external_id","guests_can_modify","guests_can_invite_others","guests_can_see_other_guests","meeting_notes_doc_id","attendees","created_at","updated_at"]},"EventVisibility":{"type":"string","enum":["default","public","private"],"description":"Visibility scope for the event."},"EventTransparency":{"type":"string","enum":["opaque","transparent"],"description":"Free/busy classification (RFC 5545 TRANSP). `opaque` = Busy (default; blocks availability). `transparent` = Free (e.g. focus time)."},"ConferenceProvider":{"type":"string","enum":["jitsi","meet","zoom","custom"],"description":"Video-conference provider for the event link."},"CalendarEventType":{"type":"string","enum":["default","outOfOffice","focusTime","agentDispatch"],"description":"Calendar event type — a display/filter category. It does not change event behavior: OOO auto-decline keys on `status: \"outofoffice\"`, and free/busy keys on `transparency` (independent inputs). The one behavioral value is `agentDispatch`, which routes a confirmation task to the assignee on create."},"DispatchReference":{"type":"object","properties":{"kind":{"type":"string","enum":["entity","url"]},"module":{"type":"string","description":"Module key for an `entity` reference (docs, tasks, …)."},"id":{"type":"string","format":"uuid","description":"Entity id for an `entity` reference."},"url":{"type":"string","pattern":"^([Hh][Tt][Tt][Pp][Ss]?:\\/\\/.*)?$","description":"http(s) URL for a `url` reference. Rendered as an href, so any other scheme is rejected 400."}},"required":["kind"]},"Attendee":{"type":"object","properties":{"id":{"type":["string","null"],"format":"uuid","description":"User id when `kind === 'user'`. Null for `guest`/`group`."},"user_id":{"type":["string","null"],"format":"uuid"},"email":{"type":["string","null"]},"display_name":{"type":["string","null"]},"avatar_url":{"type":["string","null"]},"workspace_email":{"type":["string","null"],"description":"The attendee's workspace address. Absent on list reads: it needs a `workspaces` join `list_events` does not run."},"kind":{"$ref":"#/components/schemas/AttendeeKind"},"rsvp":{"$ref":"#/components/schemas/RsvpStatus"},"rsvp_at":{"type":["string","null"],"description":"When the attendee accepted. The monotonic dispatch gate (D246)."},"is_organizer":{"type":"boolean"},"comment":{"type":["string","null"],"description":"Attendee's RSVP note, shown to the organizer in the guest list."}},"required":["id","user_id","email","display_name","kind","rsvp"]},"AttendeeKind":{"type":"string","enum":["user","guest","group"],"description":"Attendee identity. `user` = workspace user. `guest` = external email-only invite. `group` = expanded from a workspace group at create time."},"RsvpStatus":{"type":"string","enum":["accepted","declined","tentative","needs_action"],"description":"RSVP state for an attendee."},"EventResource":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/ResourceType"},"description":{"type":["string","null"]},"capacity":{"type":["integer","null"]},"location":{"type":["string","null"]},"amenities":{"type":"array","items":{"type":"string"}},"status":{"type":["string","null"],"description":"Booking status on this event — `confirmed` | `declined`."}},"required":["id","name","type"]},"ResourceType":{"type":"string","enum":["room","equipment","other"],"description":"Calendar resource type. Rooms count for capacity; equipment for inventory."},"CalendarTaskRef":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":["string","null"]},"priority":{"type":["string","null"]},"due_date":{"type":["string","null"]}},"required":["id","title","status","priority","due_date"]},"EventListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"total":{"type":"integer"},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["data","total","has_more"]},"EventSearchResult":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"start":{"type":"string"},"end":{"type":"string"},"calendar_id":{"type":"string"},"calendar_name":{"type":"string"}},"required":["id","title","start","end","calendar_id","calendar_name"]},"EventSearchResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EventSearchResult"}},"total":{"type":"integer"}},"required":["data","total"]},"EventResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":["string","null"],"format":"uuid"},"calendar_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":["string","null"]},"location":{"type":["string","null"]},"start_at":{"type":"string"},"end_at":{"type":"string"},"all_day":{"type":"boolean"},"recurrence_rule":{"type":["string","null"],"description":"RFC 5545 RRULE string. Master events only."},"master_event_id":{"type":["string","null"],"format":"uuid","description":"Set on exception/override rows that split out of a recurring series."},"original_start_at":{"type":["string","null"],"description":"Original RECURRENCE-ID for an exception row."},"excluded_dates":{"type":"array","items":{"type":"string"},"description":"Occurrence dates suppressed from the series (the EXDATE set). Master events only; `[]` elsewhere."},"status":{"$ref":"#/components/schemas/EventStatus"},"visibility":{"$ref":"#/components/schemas/EventVisibility"},"transparency":{"$ref":"#/components/schemas/EventTransparency"},"color":{"type":["string","null"]},"conference_url":{"type":["string","null"],"description":"Video-call URL. New writes are http(s)-gated at the input boundary, but rows predating that guard are not migrated — sanitize before rendering as an href."},"conference_provider":{"anyOf":[{"$ref":"#/components/schemas/ConferenceProvider"},{"type":"null"}]},"creator_id":{"type":["string","null"],"format":"uuid"},"event_type":{"$ref":"#/components/schemas/CalendarEventType"},"dispatch_prompt":{"type":["string","null"],"description":"Agent-dispatch prompt handed to the assignee (D246)."},"dispatch_references":{"type":"array","items":{"$ref":"#/components/schemas/DispatchReference"},"description":"Cross-module + external references for an agent dispatch (D246)."},"confirmation_task_id":{"type":["string","null"],"format":"uuid","description":"The standing confirmation task the assignee accepts by RSVPing (D246)."},"contact_id":{"type":["string","null"],"format":"uuid","description":"CRM contact link (D121/D210)."},"deal_id":{"type":["string","null"],"format":"uuid","description":"CRM deal link (D121/D210)."},"auto_decline_scope":{"type":"string","enum":["new_only","new_and_existing"],"description":"OOO auto-decline reach. Only meaningful when `status === 'outofoffice'` (CALENDAR P5)."},"auto_decline_message":{"type":["string","null"],"description":"Message attached to an OOO decline. Reaches organizers; NEVER free/busy (CALENDAR P2)."},"external_id":{"type":["string","null"],"description":"Originating provider's event id (Google) for a synced mirror row. Null for a local event."},"guests_can_modify":{"type":"boolean"},"guests_can_invite_others":{"type":"boolean"},"guests_can_see_other_guests":{"type":"boolean"},"meeting_notes_doc_id":{"type":["string","null"],"format":"uuid"},"attendees":{"type":"array","items":{"$ref":"#/components/schemas/Attendee"}},"resources":{"type":"array","items":{"$ref":"#/components/schemas/EventResource"}},"reminders":{"type":"array","items":{"$ref":"#/components/schemas/EventReminder"}},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"has_more_attendees":{"type":"boolean"},"total_attendees":{"type":"integer"},"is_task":{"type":"boolean","description":"True for a due-task chip synthesised into an event list, not a stored event."},"task":{"anyOf":[{"$ref":"#/components/schemas/CalendarTaskRef"},{"type":"null"}]},"self_conflicts":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Ids of the creator's own events this new event overlaps."},"attendee_conflicts":{"allOf":[{"$ref":"#/components/schemas/ConflictMap"},{"description":"Double-booked attendees, keyed by user id."}]},"external_invites_sent":{"type":"array","items":{"type":"string"},"description":"Addresses outside the workspace that were emailed an invite."},"ooo_auto_declined":{"type":"object","additionalProperties":{"type":"object","properties":{"title":{"type":"string"},"start_at":{"type":"string"},"end_at":{"type":"string"}},"required":["title","start_at","end_at"]},"description":"Attendees auto-declined because they are OOO, keyed by user id (CALENDAR P5)."},"auto_declined_existing":{"type":"array","items":{"type":"object","properties":{"eventId":{"type":"string","format":"uuid"},"organizerId":{"type":["string","null"],"format":"uuid"}},"required":["eventId","organizerId"]},"description":"Existing events bulk-declined by an OOO block whose scope is `new_and_existing`."},"resource_booking_error":{"type":"string","description":"Set when the event was created but a requested resource could not be booked."}},"required":["id","workspace_id","calendar_id","title","description","location","start_at","end_at","all_day","recurrence_rule","master_event_id","original_start_at","excluded_dates","status","visibility","transparency","color","conference_url","conference_provider","creator_id","event_type","dispatch_prompt","dispatch_references","confirmation_task_id","contact_id","deal_id","auto_decline_scope","auto_decline_message","external_id","guests_can_modify","guests_can_invite_others","guests_can_see_other_guests","meeting_notes_doc_id","attendees","created_at","updated_at"]},"EventCreateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"start_at":{"type":"string"},"end_at":{"type":"string"},"auto_conference":{"type":"boolean"},"auto_meeting_notes":{"type":"boolean"},"force":{"type":"boolean","description":"Allow creating an event in the past."},"resource_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Resources (rooms/equipment) to book for the new event; booked server-side after insert."},"description":{"type":["string","null"]},"location":{"type":["string","null"]},"all_day":{"type":"boolean"},"recurrence_rule":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/EventStatus"},"visibility":{"$ref":"#/components/schemas/EventVisibility"},"transparency":{"$ref":"#/components/schemas/EventTransparency"},"color":{"type":["string","null"],"pattern":"^#[0-9A-Fa-f]{6}$"},"conference_url":{"type":["string","null"],"pattern":"^([Hh][Tt][Tt][Pp][Ss]?:\\/\\/.*)?$","description":"http(s) URL of the video call. Any other scheme is rejected 400 — it would render as an executable href. Empty string or null clears the link (and its provider)."},"conference_provider":{"anyOf":[{"$ref":"#/components/schemas/ConferenceProvider"},{"type":"null"}]},"attendees":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","additionalProperties":{}}]},"description":"Array of attendee identifiers. Each entry is a string (UUID or email) or an iCal-natural object naming the attendee via `email`, `id`, or `user_id`; any other object key is ignored. An object with none of those three returns 400."},"guests_can_modify":{"type":"boolean"},"guests_can_invite_others":{"type":"boolean"},"guests_can_see_other_guests":{"type":"boolean"},"meeting_notes_doc_id":{"type":["string","null"],"format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid"},"deal_id":{"type":["string","null"],"format":"uuid"},"event_type":{"$ref":"#/components/schemas/CalendarEventType"},"dispatch_prompt":{"type":["string","null"],"description":"Agent-dispatch prompt (D246). Only meaningful when event_type=agentDispatch."},"dispatch_references":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["entity","url"]},"module":{"type":"string","description":"Module key for an `entity` reference (docs, tasks, …)."},"id":{"type":"string","format":"uuid","description":"Entity id for an `entity` reference."},"url":{"type":"string","pattern":"^([Hh][Tt][Tt][Pp][Ss]?:\\/\\/.*)?$","description":"http(s) URL for a `url` reference. Rendered as an href, so any other scheme is rejected 400."}},"required":["kind"],"additionalProperties":false},"description":"Cross-module + external references for an agent dispatch (D246)."},"auto_decline_scope":{"type":"string","enum":["new_only","new_and_existing"],"description":"OOO auto-decline granularity (only meaningful when status=outofoffice). `new_only` declines invitations arriving during the window; `new_and_existing` also bulk-declines events already attended."},"auto_decline_message":{"type":["string","null"],"description":"Auto-reply note sent with an OOO decline."},"skip_event_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Existing-event ids the `new_and_existing` bulk-decline should leave untouched."}},"required":["title","start_at","end_at"],"additionalProperties":false},"EventId":{"type":"string","format":"uuid"},"EventInstance":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","properties":{"instance_index":{"type":"integer"},"dispatch_state":{"anyOf":[{"$ref":"#/components/schemas/DispatchOccurrenceState"},{"type":"null"}],"description":"Per-occurrence dispatch state for an agentDispatch series (D246); absent for non-dispatch events."}}}]},"DispatchOccurrenceState":{"type":"object","properties":{"occurrence_start_at":{"type":"string"},"state":{"type":"string","enum":["scheduled","not_accepted","accepted"]},"task_id":{"type":["string","null"],"description":"Confirmation task (not_accepted) or execution task (accepted); null when scheduled."},"completion":{"type":["boolean","null"],"description":"Execution-task completion for an accepted occurrence; null otherwise."}},"required":["occurrence_start_at","state","task_id","completion"]},"EventInstancesResponse":{"type":"object","properties":{"instances":{"type":"array","items":{"$ref":"#/components/schemas/EventInstance"}},"expanded_from":{"type":"string","format":"uuid","description":"Master event id the instances were expanded from."}},"required":["instances"]},"EventUpdateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"start_at":{"type":"string"},"end_at":{"type":"string"},"force":{"type":"boolean"},"description":{"type":["string","null"]},"location":{"type":["string","null"]},"all_day":{"type":"boolean"},"recurrence_rule":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/EventStatus"},"visibility":{"$ref":"#/components/schemas/EventVisibility"},"transparency":{"$ref":"#/components/schemas/EventTransparency"},"color":{"type":["string","null"],"pattern":"^#[0-9A-Fa-f]{6}$"},"conference_url":{"type":["string","null"],"pattern":"^([Hh][Tt][Tt][Pp][Ss]?:\\/\\/.*)?$","description":"http(s) URL of the video call. Any other scheme is rejected 400 — it would render as an executable href. Empty string or null clears the link (and its provider)."},"conference_provider":{"anyOf":[{"$ref":"#/components/schemas/ConferenceProvider"},{"type":"null"}]},"attendees":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","additionalProperties":{}}]},"description":"Array of attendee identifiers. Each entry is a string (UUID or email) or an iCal-natural object naming the attendee via `email`, `id`, or `user_id`; any other object key is ignored. An object with none of those three returns 400."},"guests_can_modify":{"type":"boolean"},"guests_can_invite_others":{"type":"boolean"},"guests_can_see_other_guests":{"type":"boolean"},"meeting_notes_doc_id":{"type":["string","null"],"format":"uuid"},"contact_id":{"type":["string","null"],"format":"uuid"},"deal_id":{"type":["string","null"],"format":"uuid"},"event_type":{"$ref":"#/components/schemas/CalendarEventType"},"dispatch_prompt":{"type":["string","null"],"description":"Agent-dispatch prompt (D246). Only meaningful when event_type=agentDispatch."},"dispatch_references":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["entity","url"]},"module":{"type":"string","description":"Module key for an `entity` reference (docs, tasks, …)."},"id":{"type":"string","format":"uuid","description":"Entity id for an `entity` reference."},"url":{"type":"string","pattern":"^([Hh][Tt][Tt][Pp][Ss]?:\\/\\/.*)?$","description":"http(s) URL for a `url` reference. Rendered as an href, so any other scheme is rejected 400."}},"required":["kind"],"additionalProperties":false},"description":"Cross-module + external references for an agent dispatch (D246)."},"auto_decline_scope":{"type":"string","enum":["new_only","new_and_existing"],"description":"OOO auto-decline granularity (only meaningful when status=outofoffice). `new_only` declines invitations arriving during the window; `new_and_existing` also bulk-declines events already attended."},"auto_decline_message":{"type":["string","null"],"description":"Auto-reply note sent with an OOO decline."},"skip_event_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Existing-event ids the `new_and_existing` bulk-decline should leave untouched."}},"additionalProperties":false},"RsvpResponse":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/Event"},"rsvp":{"$ref":"#/components/schemas/RsvpStatus"}},"required":["event","rsvp"]},"RsvpInput":{"type":"object","properties":{"rsvp":{"$ref":"#/components/schemas/RsvpStatus"},"comment":{"type":"string","maxLength":500}},"required":["rsvp"],"additionalProperties":false},"RsvpEmailPayload":{"type":"object","properties":{},"additionalProperties":{}},"EventEditSingleInput":{"allOf":[{"$ref":"#/components/schemas/EventUpdateInput"},{"type":"object","properties":{"occurrence_date":{"type":"string","description":"RECURRENCE-ID of the occurrence to split out as an exception."}},"required":["occurrence_date"],"additionalProperties":false}]},"EventEditFutureInput":{"allOf":[{"$ref":"#/components/schemas/EventUpdateInput"},{"type":"object","properties":{"split_date":{"type":"string","description":"Date at which to split the series; the master ends the day before."}},"required":["split_date"],"additionalProperties":false}]},"DeleteSingleBody":{"type":"object","properties":{"occurrence_date":{"type":"string"}},"required":["occurrence_date"],"additionalProperties":false},"DeleteFutureBody":{"type":"object","properties":{"split_date":{"type":"string"}},"required":["split_date"],"additionalProperties":false},"EventResourcesResponse":{"type":"object","properties":{"resources":{"type":"array","items":{"$ref":"#/components/schemas/EventResource"}},"conflicts":{"type":"array","items":{"type":"object","properties":{"resource_id":{"type":"string","format":"uuid"},"resource_name":{"type":"string"},"conflicts_with":{"type":"string"}},"required":["resource_id","resource_name","conflicts_with"]},"description":"Requested resources that could not be booked, with the event that already holds them."}},"required":["resources"]},"ResourceBookingInput":{"type":"object","properties":{"resource_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1}},"required":["resource_ids"],"additionalProperties":false},"ReminderListResponse":{"type":"object","properties":{"reminders":{"type":"array","items":{"$ref":"#/components/schemas/EventReminder"}}},"required":["reminders"]},"ReminderResponse":{"type":"object","properties":{"reminder":{"$ref":"#/components/schemas/EventReminder"}},"required":["reminder"]},"ReminderCreateInput":{"type":"object","properties":{"method":{"$ref":"#/components/schemas/ReminderMethod"},"minutes_before":{"type":"integer","minimum":0}},"required":["method","minutes_before"],"additionalProperties":false},"ReminderSetInput":{"type":"object","properties":{"reminders":{"type":"array","items":{"type":"object","properties":{"method":{"$ref":"#/components/schemas/ReminderMethod"},"minutes_before":{"type":"integer","minimum":0}},"required":["method","minutes_before"],"additionalProperties":false}}},"required":["reminders"],"additionalProperties":false},"MeetingNotesResponse":{"type":"object","properties":{"document_id":{"type":"string","format":"uuid"},"document_url":{"type":"string"}},"required":["document_id","document_url"]},"MeetingNotesCreateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"template":{"type":"string"},"document_id":{"type":"string","format":"uuid","description":"Link this EXISTING document to the event as its meeting notes (and grant attendees access) instead of creating a new doc. Used by the @-mention 'Share & attach' flow."}},"additionalProperties":false},"CalendarResource":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"$ref":"#/components/schemas/ResourceType"},"description":{"type":["string","null"]},"capacity":{"type":["integer","null"]},"location":{"type":["string","null"]},"amenities":{"type":"array","items":{"type":"string"}},"calendar_id":{"type":["string","null"],"format":"uuid"},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","workspace_id","name","type","description","capacity","location","amenities","calendar_id","created_by","created_at","updated_at"]},"ResourceListResponse":{"type":"object","properties":{"resources":{"type":"array","items":{"$ref":"#/components/schemas/CalendarResource"}}},"required":["resources"]},"ResourceResponse":{"type":"object","properties":{"resource":{"$ref":"#/components/schemas/CalendarResource"}},"required":["resource"]},"ResourceCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"type":{"$ref":"#/components/schemas/ResourceType"},"description":{"type":"string"},"capacity":{"type":["integer","null"]},"location":{"type":"string"},"amenities":{"type":"array","items":{"type":"string"}},"calendar_id":{"type":["string","null"],"format":"uuid"}},"required":["name"],"additionalProperties":false},"ResourceUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"type":{"$ref":"#/components/schemas/ResourceType"},"description":{"type":["string","null"]},"capacity":{"type":["integer","null"]},"location":{"type":["string","null"]},"amenities":{"type":"array","items":{"type":"string"}},"calendar_id":{"type":["string","null"],"format":"uuid"}},"additionalProperties":false},"ResourceAvailabilityResponse":{"type":"object","properties":{"available":{"type":"boolean"},"conflicts":{"type":"array","items":{"type":"object","properties":{"event_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"start_at":{"type":"string"},"end_at":{"type":"string"}},"required":["event_id","title","start_at","end_at"]}}},"required":["available","conflicts"]},"CalendarPermissionEntry":{"type":"object","properties":{"type":{"type":"string","enum":["user","team"]},"id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/CalendarPermissionRole"},"display_name":{"type":["string","null"]},"email":{"type":["string","null"]},"member_count":{"type":"integer"}},"required":["type","id","role","display_name"]},"CalendarPermissionRole":{"type":"string","enum":["viewer","editor"],"description":"Role on a shared calendar."},"PendingShare":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"$ref":"#/components/schemas/CalendarPermissionRole"},"invited_by":{"type":["string","null"],"format":"uuid"},"invited_at":{"type":["string","null"]}},"required":["id","email","role","invited_by","invited_at"]},"PermissionListResponse":{"type":"object","properties":{"permissions":{"type":"array","items":{"$ref":"#/components/schemas/CalendarPermissionEntry"}},"pending_shares":{"type":"array","items":{"$ref":"#/components/schemas/PendingShare"}}},"required":["permissions"]},"PermissionSetInput":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"team_id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/CalendarPermissionRole"}},"required":["role"],"additionalProperties":false},"PermissionUpdateInput":{"type":"object","properties":{"role":{"$ref":"#/components/schemas/CalendarPermissionRole"}},"required":["role"],"additionalProperties":false},"CalendarShareInviteResponse":{"type":"object","properties":{"invite_id":{"type":["string","null"],"format":"uuid"},"pending_share_id":{"type":["string","null"],"format":"uuid"},"email":{"type":"string"},"role":{"type":"string"},"granted":{"type":"string","enum":["direct","pending"]},"user_id":{"type":"string","format":"uuid"}},"required":["invite_id","pending_share_id","email","role","granted"]},"CalendarShareInviteInput":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"$ref":"#/components/schemas/CalendarPermissionRole"},"invite_to_workspace":{"type":"boolean"},"message":{"type":"string"}},"required":["email","role"],"additionalProperties":false},"PublishResponse":{"type":"object","properties":{"publish_token":{"type":"string"},"feed_url":{"type":"string","format":"uri"}},"required":["publish_token","feed_url"]},"ImportIcsResponse":{"type":"object","properties":{"imported":{"type":"integer","minimum":0},"updated":{"type":"integer","minimum":0},"skipped":{"type":"integer","minimum":0},"errors":{"type":"integer","minimum":0},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"}},"required":["id","title"]}},"failed":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"error":{"type":"string"}},"required":["title","error"]}}},"required":["imported","skipped"]},"ImportIcsInput":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"The .ics calendar file to import (multipart `file` field)."}}},"ImportIcsUrlInput":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Publicly reachable http(s) URL of an .ics feed to fetch and import."}},"required":["url"],"additionalProperties":false},"CalendarClearResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"deleted_count":{"type":"integer","minimum":0,"description":"Events removed from the calendar. Not recoverable from a later read — the rows are gone."}},"required":["success","deleted_count"]},"CalendarUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"color":{"type":["string","null"],"pattern":"^#[0-9A-Fa-f]{6}$"},"timezone":{"type":"string"},"is_default":{"type":"boolean"},"working_hours":{"anyOf":[{"type":"object","additionalProperties":{"type":"array","prefixItems":[{"type":"string","description":"Start time in `HH:mm` (24h) local to the calendar's timezone."},{"type":"string","description":"End time in `HH:mm`."}],"description":"[start, end] window for that weekday."}},{"type":"null"}]}},"additionalProperties":false},"WikiSpace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"icon":{"type":["string","null"]},"owner_id":{"type":["string","null"],"format":"uuid"},"visibility":{"$ref":"#/components/schemas/WikiVisibility"},"pages":{"type":"array","items":{"$ref":"#/components/schemas/WikiPageSummary"}},"page_count":{"type":"integer"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","name","slug","description","icon","owner_id","created_at","updated_at"],"additionalProperties":{}},"WikiVisibility":{"type":"string","enum":["restricted","workspace","link","public"],"description":"Space/page visibility. `restricted` = invitees only. `workspace` = any workspace member. `link` = anyone with the link. `public` = indexable."},"WikiPageSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"slug":{"type":"string"},"icon":{"type":["string","null"]},"parent_page_id":{"type":["string","null"],"format":"uuid"},"sort_order":{"type":["number","null"]},"is_template":{"type":"boolean"},"updated_at":{"type":["string","null"]},"last_edited_by":{"type":["string","null"],"format":"uuid"},"children":{"type":"array","items":{"$ref":"#/components/schemas/WikiPageSummary"}}},"required":["id","title","slug","icon","parent_page_id","sort_order","is_template","updated_at","last_edited_by"]},"WikiSpaceListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiSpace"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WikiSpaceCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"slug":{"type":"string"},"description":{"type":["string","null"]},"icon":{"type":["string","null"]},"visibility":{"$ref":"#/components/schemas/WikiVisibility"},"is_private":{"type":"boolean"}},"required":["name"],"additionalProperties":false},"WikiSpaceMember":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"avatar_url":{"type":["string","null"]},"role":{"type":"string"}},"required":["user_id","display_name","avatar_url","role"]},"WikiSpaceMemberListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiSpaceMember"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WikiSpaceId":{"type":"string","format":"uuid"},"WikiSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"WikiSpaceMemberAddInput":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"type":"string","enum":["viewer","commenter","editor"]}},"required":["user_id","role"],"additionalProperties":false},"WikiGraphNode":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"slug":{"type":"string"},"icon":{"type":["string","null"]},"parent_page_id":{"type":["string","null"],"format":"uuid"}},"required":["id","title","slug","icon","parent_page_id"]},"WikiGraphEdge":{"type":"object","properties":{"source":{"type":"string","format":"uuid"},"target":{"type":"string","format":"uuid"}},"required":["source","target"]},"WikiGraphResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiGraphNode"}},"total":{"type":"integer"},"has_more":{"type":"boolean"},"edges":{"type":"array","items":{"$ref":"#/components/schemas/WikiGraphEdge"}}},"required":["data","total","has_more","edges"]},"WikiPageChild":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"slug":{"type":"string"},"icon":{"type":["string","null"]},"parent_page_id":{"type":["string","null"],"format":"uuid"},"sort_order":{"type":["number","null"]},"is_template":{"type":"boolean"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","title","slug","icon","parent_page_id","sort_order","is_template","created_at","updated_at"]},"WikiPageChildListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiPageChild"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WikiPageRole":{"type":"string","enum":["viewer","commenter","editor","owner"],"description":"Per-page role for a user / group / guest."},"WikiPage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"space_id":{"type":"string","format":"uuid"},"parent_page_id":{"type":["string","null"],"format":"uuid"},"title":{"type":"string"},"slug":{"type":"string"},"content":{"type":["string","null"]},"icon":{"type":["string","null"]},"cover_image":{"type":["string","null"]},"sort_order":{"type":["number","null"]},"is_template":{"type":"boolean"},"visibility":{"anyOf":[{"$ref":"#/components/schemas/WikiVisibility"},{"type":"null"}]},"created_by":{"type":["string","null"],"format":"uuid"},"last_edited_by":{"type":["string","null"],"format":"uuid"},"children":{"type":"array","items":{}},"backlinks":{"type":"array","items":{}},"created_by_user":{},"last_edited_by_user":{},"effective_role":{"$ref":"#/components/schemas/WikiPageRole"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","space_id","parent_page_id","title","slug","content","icon","cover_image","sort_order","is_template","created_by","last_edited_by","created_at","updated_at"],"additionalProperties":{}},"WikiPageCreateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"slug":{"type":"string"},"parent_page_id":{"type":["string","null"],"format":"uuid"},"content":{"anyOf":[{"type":"string"},{"type":"object","additionalProperties":{}}],"description":"Page content as Markdown string or ProseMirror JSON object."},"content_markdown":{"type":"string","description":"Legacy alias for `content`."},"icon":{"type":["string","null"]},"cover_image":{"type":["string","null"]},"sort_order":{"type":"number"},"is_template":{"type":"boolean"}},"required":["title"],"additionalProperties":false},"WikiSpaceUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"slug":{"type":"string"},"description":{"type":["string","null"]},"icon":{"type":["string","null"]},"visibility":{"$ref":"#/components/schemas/WikiVisibility"},"is_private":{"type":"boolean"}},"additionalProperties":false},"WikiTrashListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"pages":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"Trashed pages reachable by the caller, with space context."}},"required":["success","pages"]},"WikiPageId":{"type":"string","format":"uuid"},"WikiBacklink":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"slug":{"type":"string"},"space_id":{"type":["string","null"],"format":"uuid"},"icon":{"type":["string","null"]}},"required":["id","title","slug","space_id","icon"]},"WikiBacklinkListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiBacklink"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WikiPageVersionSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":["string","null"]},"user_id":{"type":["string","null"],"format":"uuid"},"user_name":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","title","user_id","user_name","created_at"]},"WikiPageVersionListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiPageVersionSummary"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WikiPageVersionCreateBody":{"type":"object","properties":{"label":{"type":"string"}},"additionalProperties":false},"WikiPageVersion":{"allOf":[{"$ref":"#/components/schemas/WikiPageVersionSummary"},{"type":"object","properties":{"content":{"type":["string","null"]}},"required":["content"]}]},"WikiOkResponse":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]},"WikiPageDuplicateInput":{"type":"object","properties":{"include_children":{"type":"boolean"},"space_id":{"type":"string","format":"uuid"},"parent_page_id":{"type":"string","format":"uuid"}},"additionalProperties":false},"WikiPageExportBody":{"type":"object","properties":{"format":{"type":"string"}},"additionalProperties":false},"WikiDatabase":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"page_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"schema":{},"views":{},"rows":{"type":"array","items":{}},"created_at":{"type":["string","null"]}},"required":["id","page_id","name","created_at"],"additionalProperties":{}},"WikiDatabaseListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiDatabase"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WikiDatabaseInPageCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"title":{"type":"string","minLength":1},"schema":{},"views":{}},"additionalProperties":false},"WikiPagePermission":{"type":"object","properties":{"page_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["user","team"]},"user_id":{"type":["string","null"],"format":"uuid"},"team_id":{"type":["string","null"],"format":"uuid"},"guest_id":{"type":["string","null"],"format":"uuid"},"role":{"$ref":"#/components/schemas/WikiPageRole"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]},"team_name":{"type":["string","null"]},"member_count":{"type":"integer"}},"required":["page_id","role"],"additionalProperties":{}},"WikiPagePermissionListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiPagePermission"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WikiPagePermissionSetResponse":{"type":"object","properties":{"page_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"team_id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/WikiPageRole"}},"required":["page_id","role"],"additionalProperties":{}},"WikiPagePermissionSetInput":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"team_id":{"type":"string","format":"uuid"},"role":{"$ref":"#/components/schemas/WikiPageRole"}},"required":["role"],"additionalProperties":false},"WikiDeletedResponse":{"type":"object","properties":{"deleted":{"type":"boolean"}},"required":["deleted"]},"WikiPageShareInviteResponse":{"type":"object","properties":{},"additionalProperties":{}},"WikiPageShareInviteInput":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"$ref":"#/components/schemas/WikiPageRole"},"message":{"type":"string"}},"required":["email","role"],"additionalProperties":false},"WikiPageVisibilityResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"space_id":{"type":"string","format":"uuid"},"visibility":{"$ref":"#/components/schemas/WikiVisibility"},"link_expires_at":{"type":["string","null"]},"has_password":{"type":"boolean"},"link_permission":{"type":"string","enum":["viewer","commenter","editor"]}},"required":["id","space_id","visibility","link_expires_at","has_password"]},"WikiPageVisibilityInput":{"type":"object","properties":{"visibility":{"$ref":"#/components/schemas/WikiVisibility"},"linkExpiresAt":{"type":["string","null"]},"linkPassword":{"type":["string","null"]},"linkPermission":{"type":"string","enum":["viewer","commenter","editor"]},"link_permission":{"type":"string","enum":["viewer","commenter","editor"]}},"required":["visibility"],"additionalProperties":false},"WikiPageComment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"wiki_page_id":{"type":"string","format":"uuid"},"document_id":{"type":"string","format":"uuid","description":"Alias for wiki_page_id — lets the shared Docs CommentsPanel render wiki comments unchanged."},"parent_id":{"type":["string","null"],"format":"uuid"},"content":{"type":"string"},"anchor":{},"resolved":{"type":"boolean"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"author":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]}},"required":["id","display_name","primary_email"]},"reactions":{"type":"array","items":{"$ref":"#/components/schemas/CommentReaction"}},"replies":{"type":"array","items":{"$ref":"#/components/schemas/WikiPageComment"}}},"required":["id","wiki_page_id","document_id","parent_id","content","resolved","created_at","updated_at","author"]},"WikiPageCommentListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiPageComment"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WikiPageCommentCreateInput":{"type":"object","properties":{"content":{"type":"string","minLength":1},"parent_id":{"type":["string","null"],"format":"uuid"},"anchor":{}},"required":["content"],"additionalProperties":false},"WikiPageCommentUpdateInput":{"type":"object","properties":{"resolved":{"type":"boolean"}},"required":["resolved"],"additionalProperties":false},"WikiPageUpdateInput":{"type":"object","properties":{"title":{"type":"string","minLength":1},"slug":{"type":"string"},"parent_page_id":{"type":["string","null"],"format":"uuid"},"content":{"anyOf":[{"type":"string"},{"type":"object","additionalProperties":{}}],"description":"Page content as Markdown string or ProseMirror JSON object."},"content_markdown":{"type":"string","description":"Legacy alias for `content`."},"icon":{"type":["string","null"]},"cover_image":{"type":["string","null"]},"sort_order":{"type":"number"},"is_template":{"type":"boolean"},"space_id":{"type":"string","format":"uuid","description":"Target space ID for cross-space move."}},"additionalProperties":false},"WikiPageDeleteCascadeRequiredResponse":{"type":"object","properties":{"error":{"type":"string"},"requires_cascade":{"type":"boolean"},"children_count":{"type":"integer"}},"required":["error","requires_cascade","children_count"]},"WikiSearchResult":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"slug":{"type":"string"},"space_id":{"type":["string","null"],"format":"uuid"},"snippet":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","title","slug"],"additionalProperties":{}},"WikiSearchResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiSearchResult"}},"total":{"type":"integer"},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer"}},"required":["data","has_more"],"additionalProperties":{}},"WikiDatabaseCreateInput":{"type":"object","properties":{"page_id":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1},"title":{"type":"string","minLength":1},"schema":{},"views":{}},"additionalProperties":false},"WikiDatabaseRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"database_id":{"type":"string","format":"uuid"},"properties":{},"page_id":{"type":["string","null"],"format":"uuid"},"page_cover_image":{"type":["string","null"]},"page_icon":{"type":["string","null"]},"sort_order":{"type":["number","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","database_id","page_id","page_cover_image","page_icon","sort_order","created_at","updated_at"],"additionalProperties":{}},"WikiDatabaseRowCreateInput":{"type":"object","properties":{"properties":{},"page_id":{"type":"string","format":"uuid"},"sort_order":{"type":"number"}},"additionalProperties":false},"WikiDatabaseRowUpdateInput":{"type":"object","properties":{"properties":{},"sort_order":{"type":"number"}},"additionalProperties":false},"WikiDatabaseQueryResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiDatabaseRow"}},"total":{"type":"integer"},"has_more":{"type":"boolean"},"page_size":{"type":"integer"},"offset":{"type":"integer"}},"required":["data","total","has_more","page_size","offset"]},"WikiDatabaseEnsureReverseRelationResponse":{"type":"object","properties":{"reverse_property_id":{"type":"string"}},"required":["reverse_property_id"]},"WikiDatabaseEnsureReverseRelationInput":{"type":"object","properties":{"property_id":{"type":"string"},"property_name":{"type":"string"},"target_database_id":{"type":"string","format":"uuid"}},"required":["property_id","target_database_id"],"additionalProperties":false},"WikiDatabaseRollupListResponse":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{}}},"has_more":{"type":"boolean"}},"required":["data","has_more"]},"WikiDatabaseUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1},"schema":{},"views":{}},"additionalProperties":false},"WikiSyncedBlock":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"source_page_id":{"type":["string","null"],"format":"uuid"},"content":{},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","workspace_id","source_page_id","created_by","created_at","updated_at"]},"WikiSyncedBlockListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WikiSyncedBlock"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"WikiSyncedBlockCreateInput":{"type":"object","properties":{"source_page_id":{"type":["string","null"],"format":"uuid"},"content":{}},"additionalProperties":false},"WikiSyncedBlockUpdateInput":{"type":"object","properties":{"content":{}},"additionalProperties":false},"AdminSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]},"AdminWorkspaceResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"timezone":{"type":["string","null"]},"logo_url":{"type":["string","null"]},"locale":{"type":["string","null"]},"domain":{"type":["string","null"]},"email_domain":{"type":"string"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","slug","name","email_domain","created_at"]},"AdminWorkspaceUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[^<>]*$"},"slug":{"type":"string","minLength":1},"timezone":{"type":"string"},"locale":{"type":"string"},"domain":{"type":["string","null"]}},"additionalProperties":false},"AdminLogoUploadResponse":{"type":"object","properties":{"logo_url":{"type":"string"}},"required":["logo_url"]},"AdminWorkspaceSettingsResponse":{"type":"object","properties":{"timezone":{"type":["string","null"]},"locale":{"type":["string","null"]},"sla_thresholds":{}}},"AdminWorkspaceSettingsUpdateInput":{"type":"object","additionalProperties":{}},"SecuritySettingsResponse":{"type":"object","properties":{"require_2fa":{"type":"boolean"},"require_2fa_enforcement":{"type":"string","enum":["enforced","coming_soon"]},"session_timeout_hours":{"type":"integer","exclusiveMinimum":0},"password_min_length":{"type":"integer","exclusiveMinimum":0},"ip_allowlist":{"type":"array","items":{"type":"string"}},"ip_allowlist_enforcement":{"type":"string","enum":["enforced","coming_soon"]}},"required":["require_2fa","session_timeout_hours","password_min_length","ip_allowlist"],"description":"Workspace-level security policy."},"SecuritySettingsUpdateInput":{"type":"object","properties":{"require_2fa":{"type":"boolean"},"require_2fa_enforcement":{"type":"string","enum":["enforced","coming_soon"]},"session_timeout_hours":{"type":"integer","exclusiveMinimum":0},"password_min_length":{"type":"integer","exclusiveMinimum":0},"ip_allowlist":{"type":"array","items":{"type":"string"}},"ip_allowlist_enforcement":{"type":"string","enum":["enforced","coming_soon"]}},"additionalProperties":false},"NotificationDefaultsResponse":{"type":"object","properties":{"email_notifications_enabled":{"type":"boolean","description":"Master switch — when false, no email notification is sent for this workspace."},"email_on_task_assigned":{"type":"boolean"},"email_on_document_shared":{"type":"boolean"},"email_on_comment_added":{"type":"boolean"},"email_on_mention":{"type":"boolean"},"email_on_deal_won":{"type":"boolean"},"email_on_deal_lost":{"type":"boolean"}},"required":["email_notifications_enabled","email_on_task_assigned","email_on_document_shared","email_on_comment_added","email_on_mention","email_on_deal_won","email_on_deal_lost"]},"NotificationDefaultsUpdateInput":{"type":"object","properties":{"email_notifications_enabled":{"type":"boolean"},"email_on_task_assigned":{"type":"boolean"},"email_on_document_shared":{"type":"boolean"},"email_on_comment_added":{"type":"boolean"},"email_on_mention":{"type":"boolean"},"email_on_deal_won":{"type":"boolean"},"email_on_deal_lost":{"type":"boolean"}},"additionalProperties":false},"EmailSignatureResponse":{"type":"object","properties":{"signature":{"type":["string","null"]}},"required":["signature"]},"EmailSignatureUpdateInput":{"type":"object","properties":{"markdown":{"type":["string","null"],"maxLength":5000}},"required":["markdown"],"additionalProperties":false},"EmailDeliverabilityResponse":{"type":"object","properties":{"deliverabilityScore":{"type":"integer","minimum":0,"maximum":100},"volumeSent":{"type":"object","properties":{"totalSent":{"type":"integer"},"last7Days":{"type":"integer"},"last30Days":{"type":"integer"}},"required":["totalSent","last7Days","last30Days"]},"recommendationItems":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["SPF","DKIM","DMARC","MX","UNVERIFIED","NO_DOMAINS","OPTIMAL"]},"severity":{"type":"string","enum":["error","warning","info","success"]},"domain":{"type":"string"},"message":{"type":"string"}},"required":["kind","severity","message"]}},"domains":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"domain":{"type":"string"},"domainType":{"type":"string"},"status":{"type":"string"},"verified":{"type":"boolean"},"spfVerified":{"type":"boolean"},"dkimVerified":{"type":"boolean"},"dmarcVerified":{"type":"boolean"},"mxVerified":{"type":"boolean"},"deliverabilityScore":{"type":"integer","minimum":0,"maximum":100},"emailStats":{"type":"object","properties":{"totalSent":{"type":"integer"},"last7Days":{"type":"integer"},"last30Days":{"type":"integer"}},"required":["totalSent","last7Days","last30Days"]},"missingRecords":{"type":"array","items":{"type":"string"}}},"required":["id","domain","domainType","status","verified","spfVerified","dkimVerified","dmarcVerified","mxVerified","deliverabilityScore","emailStats","missingRecords"]}}},"required":["deliverabilityScore","volumeSent","recommendationItems","domains"],"additionalProperties":{}},"AdminUser":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"workspace_email":{"type":["string","null"]},"username":{"type":["string","null"]},"account_email":{"type":["string","null"],"description":"The `accounts` login address; null for an agent, which holds no account."},"custom_email":{"type":["string","null"]},"storage_quota_bytes":{"type":["integer","null"],"description":"Per-user override; null means the workspace default applies (DRIVE.md P3)."},"storage_used_bytes":{"type":"integer","minimum":0},"last_active_at":{"type":["string","null"],"description":"Deliberate-activity stamp, not incidental API traffic (IDENTITY.md — Presence activity timestamps)."},"display_name":{"type":["string","null"]},"type":{"$ref":"#/components/schemas/AdminUserType"},"avatar_url":{"type":["string","null"]},"roles":{"type":"array","items":{"type":"string"}},"capacity_hours":{"type":["integer","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"last_login_at":{"type":["string","null"]},"suspended_at":{"type":["string","null"],"format":"date-time"},"coworker_config":{"anyOf":[{"$ref":"#/components/schemas/AdminCoworkerConfig"},{"type":"null"}],"description":"Present only when `?include_coworker_config=true` is passed. `null` for humans and for agents without a `coworker_configs` row."}},"required":["id","email","display_name","type","created_at"]},"AdminUserType":{"type":"string","enum":["human","agent"],"description":"User identity. Humans authenticate with passwords / SSO; agents with API keys."},"AdminCoworkerConfig":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"coworker_service_id":{"type":"string"},"status":{"type":"string"},"persona":{"type":["string","null"]},"focus_areas":{"type":["array","null"],"items":{"type":"string"}}},"required":["id","coworker_service_id","status","persona","focus_areas"]},"AdminUsersListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdminUser"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"AdminCreateUserResponse":{"anyOf":[{"$ref":"#/components/schemas/AdminAgentProvisionedResponse"},{"type":"object","properties":{"message":{"type":"string"},"invite":{"anyOf":[{"$ref":"#/components/schemas/AdminInvite"},{"type":"null"}]}},"required":["message","invite"]}]},"AdminAgentProvisionedResponse":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"primary_email":{"type":["string","null"]},"username":{"type":"string"},"display_name":{"type":["string","null"]},"type":{"$ref":"#/components/schemas/AdminUserType"},"role":{"type":"string","enum":["admin","member"]},"workspace_email":{"type":"string"}},"required":["id","primary_email","username","display_name","type","role","workspace_email"]},"api_key":{"type":"string"}},"required":["user","api_key"]},"AdminInvite":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"$ref":"#/components/schemas/AdminInviteRole"},"invited_by":{"type":["string","null"],"format":"uuid"},"invited_by_name":{"type":["string","null"]},"invited_by_email":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","email","role","invited_by","invited_by_name","invited_by_email","expires_at","created_at"]},"AdminInviteRole":{"type":"string","enum":["admin","member"],"description":"Role assigned to the new member when they accept the invite."},"AdminCreateUserInput":{"type":"object","properties":{"type":{"type":"string","enum":["human","agent"],"description":"Account type. Required."},"display_name":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[^<>]*$","description":"Display name for the user. Required."},"email":{"type":"string","minLength":1,"description":"Email address. For humans: their real email. For agents: just the local part (e.g., 'sales-bot' → sales-bot@ambi.cc). Required."},"role":{"type":"string","enum":["owner","admin","member","limited"],"description":"Role to assign. Optional, defaults to 'member'."}},"required":["type","display_name","email"],"additionalProperties":false},"AdminProvisionAgentInput":{"type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[^<>]*$"},"username":{"type":"string","description":"Explicit username; otherwise derived from display_name."},"role":{"$ref":"#/components/schemas/AdminUserRoleName"},"avatar_url":{"type":"string"},"manager_user_id":{"type":"string","format":"uuid","description":"Workspace user accountable for this agent. Defaults to the provisioning caller."}},"required":["display_name"],"additionalProperties":false},"AdminUserRoleName":{"type":"string","enum":["owner","admin","member","limited"],"description":"System role. Custom roles are surfaced through the role catalog."},"AdminInviteCreatedResponse":{"type":"object","properties":{"message":{"type":"string"},"invite":{"anyOf":[{"$ref":"#/components/schemas/AdminInvite"},{"type":"null"}]}},"required":["message","invite"]},"AdminInviteUsersInput":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Single recipient email."},"role":{"type":"string","enum":["admin","member"],"description":"Defaults to `member`."}},"required":["email"],"additionalProperties":false},"AdminUserResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"workspace_email":{"type":["string","null"]},"username":{"type":["string","null"]},"account_email":{"type":["string","null"],"description":"The `accounts` login address; null for an agent, which holds no account."},"custom_email":{"type":["string","null"]},"storage_quota_bytes":{"type":["integer","null"],"description":"Per-user override; null means the workspace default applies (DRIVE.md P3)."},"storage_used_bytes":{"type":"integer","minimum":0},"last_active_at":{"type":["string","null"],"description":"Deliberate-activity stamp, not incidental API traffic (IDENTITY.md — Presence activity timestamps)."},"display_name":{"type":["string","null"]},"type":{"$ref":"#/components/schemas/AdminUserType"},"avatar_url":{"type":["string","null"]},"roles":{"type":"array","items":{"type":"string"}},"capacity_hours":{"type":["integer","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"last_login_at":{"type":["string","null"]},"suspended_at":{"type":["string","null"],"format":"date-time"},"coworker_config":{"anyOf":[{"$ref":"#/components/schemas/AdminCoworkerConfig"},{"type":"null"}],"description":"Present only when `?include_coworker_config=true` is passed. `null` for humans and for agents without a `coworker_configs` row."}},"required":["id","email","display_name","type","created_at"]},"AdminUserRoleAssignInput":{"type":"object","properties":{"role":{"type":"string","minLength":1},"role_name":{"type":"string","minLength":1,"description":"Alias for `role` (TASK-027)."}},"additionalProperties":false},"AdminUserUpdateInput":{"type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[^<>]*$"},"username":{"type":"string"},"type":{"$ref":"#/components/schemas/AdminUserType"},"avatar_url":{"type":["string","null"]},"roles":{"type":"array","items":{"type":"string"}},"storage_quota_bytes":{"type":["integer","null"],"minimum":0},"capacity_hours":{"type":["integer","null"],"minimum":1,"maximum":168,"description":"Per-user weekly Workload capacity in hours. Null clears the override back to the workspace default."}},"additionalProperties":false},"AdminPasswordResetResponse":{"type":"object","properties":{"sent":{"type":"boolean","description":"False when the reset email bounced — the caller shares `reset_url` by hand."},"email":{"type":"string","description":"Address the reset was sent to."},"expires_at":{"type":"string","description":"ISO instant the reset link stops working."},"reset_url":{"type":"string","description":"One-time reset link. Shown once; not retrievable later."}},"required":["sent","email","expires_at","reset_url"]},"AdminInvitesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdminInvite"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"AdminInviteResponse":{"allOf":[{"$ref":"#/components/schemas/AdminInvite"},{"type":"object","properties":{"invite_url":{"type":"string"}},"required":["invite_url"]}]},"AdminInviteLinkResponse":{"type":"object","properties":{"invite_url":{"type":"string"}},"required":["invite_url"]},"AdminRole":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"permissions":{"type":"array","items":{"type":"string"}},"is_system":{"type":"boolean"},"created_at":{"type":["string","null"]},"user_count":{"type":"integer","minimum":0}},"required":["id","name","permissions","user_count"]},"AdminRolesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdminRole"}}},"required":["data"]},"AdminRoleResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":["string","null"]},"permissions":{"type":"array","items":{"type":"string"}},"is_system":{"type":"boolean"},"created_at":{"type":["string","null"]},"user_count":{"type":"integer","minimum":0}},"required":["id","name","permissions","user_count"]},"AdminRoleCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"}},"confirm_wildcard":{"type":"boolean"}},"required":["name","permissions"],"additionalProperties":false},"AdminRoleUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":["string","null"]},"permissions":{"type":"array","items":{"type":"string"}}},"additionalProperties":false},"AdminAuditEntry":{"type":"object","properties":{"id":{"type":"integer"},"user_id":{"type":["string","null"],"format":"uuid"},"user_name":{"type":["string","null"]},"user_email":{"type":["string","null"]},"action":{"$ref":"#/components/schemas/AdminAuditActionRead"},"resource_type":{"type":["string","null"]},"resource_id":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":{},"description":"Per-action key-value bag. Shape varies by action — see the audit-log event reference for the exact metadata fields per action verb."},"ip_address":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","user_id","user_name","user_email","action","resource_type","resource_id","metadata","ip_address","user_agent","created_at"]},"AdminAuditActionRead":{"type":"string","description":"Audit-log action verb. Current vocabulary: see AdminAuditAction. Historic rows may carry a retired verb — audit_log is INSERT-only, so a narrowed enum can never be made true of rows already written."},"AdminAuditLogResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdminAuditEntry"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"AdminBinaryBody":{"type":"string"},"AdminExternalCollaborator":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid","description":"The `users.id` the grants point at — a row in the collaborator's OWN workspace, never this one."},"display_name":{"type":"string"},"email":{"type":["string","null"]},"resources":{"type":"array","items":{"$ref":"#/components/schemas/AdminExternalCollaboratorResource"},"description":"What they can currently reach in this workspace, capped; `resource_count` is the true total."},"resource_count":{"type":"integer","minimum":0},"last_access_at":{"type":["string","null"],"description":"When they last acted in THIS workspace. Null means never — not merely unknown."}},"required":["user_id","display_name","email","resources","resource_count","last_access_at"]},"AdminExternalCollaboratorResource":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["doc","sheet","slide"]},"title":{"type":"string"},"role":{"type":"string","enum":["viewer","commenter","editor","owner"]}},"required":["id","type","title","role"]},"AdminExternalCollaboratorsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdminExternalCollaborator"}},"total":{"type":"integer","minimum":0}},"required":["data","total"]},"AdminExternalCollaboratorRevokeResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"revoked_count":{"type":"integer","minimum":0,"description":"How many grants in this workspace were removed. Every one they held, so this is the blast radius of the action just taken."}},"required":["success","revoked_count"]},"AdminApiKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"user_name":{"type":["string","null"]},"user_email":{"type":["string","null"]},"name":{"type":"string"},"scopes":{},"rate_limit":{"type":"integer"},"last_used_at":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"key_prefix":{"type":["string","null"]},"last_rotated_at":{"type":["string","null"]},"old_key_expires_at":{"type":["string","null"]}},"required":["id","user_id","user_name","user_email","name","rate_limit","last_used_at","expires_at","created_at","key_prefix"]},"AdminApiKeysListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdminApiKey"}}},"required":["data"]},"AdminApiKeyWithSecretResponse":{"type":"object","properties":{"key":{"$ref":"#/components/schemas/AdminApiKey"},"raw_key":{"type":"string","description":"Plaintext API key. Only returned at create time."},"old_key_expires_at":{"type":["string","null"],"description":"ISO timestamp when the previous key stops working (rotate only)."}},"required":["key","raw_key"]},"AdminApiKeyCreateInput":{"type":"object","properties":{"user_id":{"type":"string","description":"Workspace user the key is minted for. Required."},"name":{"type":"string","minLength":1,"maxLength":200},"scopes":{"type":"array","items":{"type":"string"},"minItems":1},"rate_limit":{"type":"integer","minimum":1,"maximum":10000},"expires_at":{"type":["string","null"]},"confirm_wildcard":{"type":"boolean","description":"Acknowledge granting a wildcard (`*`) scope."}},"required":["user_id","name","scopes"],"additionalProperties":false},"AdminApiKeyResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"user_name":{"type":["string","null"]},"user_email":{"type":["string","null"]},"name":{"type":"string"},"scopes":{},"rate_limit":{"type":"integer"},"last_used_at":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"key_prefix":{"type":["string","null"]},"last_rotated_at":{"type":["string","null"]},"old_key_expires_at":{"type":["string","null"]}},"required":["id","user_id","user_name","user_email","name","rate_limit","last_used_at","expires_at","created_at","key_prefix"]},"AdminApiKeyUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"scopes":{"type":"array","items":{"type":"string"},"minItems":1},"rate_limit":{"type":"integer","minimum":1,"maximum":10000},"expires_at":{"type":["string","null"]},"confirm_wildcard":{"type":"boolean"}},"additionalProperties":false},"WorkspaceSubscription":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"stripe_subscription_id":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/SubscriptionStatus"},"plan_tier":{"$ref":"#/components/schemas/BilledPlanTier"},"quantity":{"type":["integer","null"]},"current_period_start":{"type":["string","null"]},"current_period_end":{"type":["string","null"]},"cancel_at_period_end":{"type":"boolean"},"canceled_at":{"type":["string","null"]},"trial_start":{"type":["string","null"]},"trial_end":{"type":["string","null"]}},"required":["id","stripe_subscription_id","status","plan_tier","quantity","current_period_start","current_period_end","cancel_at_period_end","canceled_at","trial_start","trial_end"]},"SubscriptionStatus":{"type":"string","enum":["active","trialing","past_due","canceled","incomplete","incomplete_expired","unpaid","paused"],"description":"Stripe subscription status, mirrored on our row."},"BilledPlanTier":{"type":"string","enum":["free","pro","team"]},"WorkspaceBillingView":{"type":"object","properties":{"plan":{"type":"string","enum":["free","pro"]},"seat_count":{"type":"integer","minimum":0},"base_quota":{"type":"integer","minimum":0},"earned_quota":{"type":"integer","minimum":0},"topup_balance":{"type":"integer","minimum":0},"consumed_this_month":{"type":"integer","minimum":0},"reset_at":{"type":"string"},"per_seat_cap_enabled":{"type":"boolean"},"per_seat_cap_amount":{"type":["integer","null"]},"active_bonuses":{"type":"array","items":{"$ref":"#/components/schemas/ActivationBonusEntry"}},"member_count":{"type":"integer","minimum":0},"member_limit":{"type":["integer","null"]},"trial_status":{"type":"string","enum":["active","ending_soon","ended","none"]},"trial_ends_at":{"type":["string","null"]},"auto_recharge":{"anyOf":[{"$ref":"#/components/schemas/AutoRechargeConfig"},{"type":"null"}]}},"required":["plan","seat_count","base_quota","earned_quota","topup_balance","consumed_this_month","reset_at","per_seat_cap_enabled","per_seat_cap_amount","active_bonuses","member_count","member_limit","trial_status","trial_ends_at","auto_recharge"]},"ActivationBonusEntry":{"type":"object","properties":{"type":{"type":"string"},"amount":{"type":"integer"},"source_user_id":{"type":["string","null"],"format":"uuid"},"source_resource_id":{"type":["string","null"]},"earned_at":{"type":"string"},"last_verified_at":{"type":"string"}},"required":["type","amount","source_user_id","source_resource_id","earned_at","last_verified_at"]},"AutoRechargeConfig":{"type":"object","properties":{"enabled":{"type":"boolean"},"threshold":{"anyOf":[{"type":"number","enum":[50]},{"type":"number","enum":[100]},{"type":"number","enum":[250]},{"type":"number","enum":[500]}]},"pack":{"type":"string","enum":["small","medium","large"]}},"required":["enabled","threshold","pack"]},"AdminBillingOverviewResponse":{"type":"object","properties":{"plan_tier":{"type":["string","null"]},"status":{"type":["string","null"]},"is_trial":{"type":"boolean"},"trial_days_remaining":{"type":["integer","null"]},"subscription":{"anyOf":[{"$ref":"#/components/schemas/WorkspaceSubscription"},{"type":"null"}]},"seats":{"type":["object","null"],"properties":{"current_seats":{"type":"integer"},"subscription_quantity":{"type":["integer","null"]},"breakdown":{}},"required":["current_seats","subscription_quantity"]},"invoices":{"type":"array","items":{}},"has_more_invoices":{"type":"boolean"},"billing_view":{"$ref":"#/components/schemas/WorkspaceBillingView"}},"required":["plan_tier","status","is_trial","trial_days_remaining","subscription","seats","invoices","has_more_invoices","billing_view"]},"PlanUpgradeResponse":{"type":"object","properties":{"mode":{"type":"string","enum":["checkout","switched"]},"url":{"type":"string","format":"uri"},"session_id":{"type":"string"},"subscription":{"$ref":"#/components/schemas/WorkspaceSubscription"}},"required":["mode"]},"PlanLookupKey":{"type":"string","enum":["pro_monthly","pro_annual"],"description":"Stripe price lookup_key. `pro_monthly` = $20/seat/month, `pro_annual` = $200/seat/year (~17% off monthly)."},"PlanCancelResponse":{"type":"object","properties":{"canceled":{"type":"boolean"},"cancel_at_period_end":{"type":"boolean"},"current_period_end":{"type":["integer","null"]},"plan_lookup_key":{"type":["string","null"]}},"required":["canceled","cancel_at_period_end","current_period_end","plan_lookup_key"]},"ReferralInviteEntry":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"invite_type":{"type":"string","enum":["friend","coworker","member","share_friend","external_grant"]},"status":{"type":"string","enum":["pending","accepted","verified","agent_created","expired","revoked"]},"action_grant_earned":{"type":"integer","minimum":0},"perpetual_email_verified_active":{"type":"boolean"},"perpetual_first_agent_active":{"type":"boolean"},"invited_at":{"type":"string"},"accepted_at":{"type":["string","null"]}},"required":["id","email","invite_type","status","action_grant_earned","perpetual_email_verified_active","perpetual_first_agent_active","invited_at","accepted_at"]},"ShareLinkStats":{"type":"object","properties":{"url":{"type":"string"},"clicks":{"type":"integer","minimum":0},"conversions":{"type":"integer","minimum":0}},"required":["url","clicks","conversions"]},"ReferralDashboardData":{"type":"object","properties":{"referral_slug":{"type":"string"},"referral_url":{"type":"string"},"total_friends_invited":{"type":"integer","minimum":0},"total_actions_earned":{"type":"integer","minimum":0},"your_invites":{"type":"array","items":{"$ref":"#/components/schemas/ReferralInviteEntry"}},"active_bonuses":{"type":"array","items":{"$ref":"#/components/schemas/ActivationBonusEntry"}},"share_links":{"type":"array","items":{"$ref":"#/components/schemas/ShareLinkStats"}}},"required":["referral_slug","referral_url","total_friends_invited","total_actions_earned","your_invites","active_bonuses","share_links"]},"UsageStatsResponse":{"type":"object","properties":{"users":{"type":"object","properties":{"total":{"type":"integer"},"humans":{"type":"integer"},"agents":{"type":"integer"}},"required":["total","humans","agents"]},"modules":{"type":"object","properties":{"documents":{"type":"integer"},"files":{"type":"integer"},"channels":{"type":"integer"},"messages":{"type":"integer"},"emails":{"type":"integer"},"tasks":{"type":"integer"},"contacts":{"type":"integer"},"deals":{"type":"integer"},"forms":{"type":"integer"},"events":{"type":"integer"},"wiki_spaces":{"type":"integer"},"wiki_pages":{"type":"integer"}},"required":["documents","files","channels","messages","emails","tasks","contacts","deals","forms","events","wiki_spaces","wiki_pages"]},"onboarding":{"type":"object","properties":{"has_custom_domain":{"type":"boolean"},"has_agent":{"type":"boolean"},"has_webhook":{"type":"boolean"}},"required":["has_custom_domain","has_agent","has_webhook"]}},"required":["users","modules","onboarding"]},"UsageTimeSeriesMetric":{"type":"object","properties":{"buckets":{"type":"array","items":{"$ref":"#/components/schemas/UsageTimeSeriesBucket"}},"total":{"type":"integer"},"previous_total":{"type":"integer"}},"required":["buckets","total","previous_total"]},"UsageTimeSeriesBucket":{"type":"object","properties":{"date":{"type":"string","description":"YYYY-MM-DD UTC, oldest first."},"count":{"type":"integer"}},"required":["date","count"]},"UsageTimeSeriesResponse":{"type":"object","properties":{"users":{"$ref":"#/components/schemas/UsageTimeSeriesMetric"},"documents":{"$ref":"#/components/schemas/UsageTimeSeriesMetric"},"messages":{"$ref":"#/components/schemas/UsageTimeSeriesMetric"},"emails":{"$ref":"#/components/schemas/UsageTimeSeriesMetric"}},"required":["users","documents","messages","emails"]},"Domain":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"kind":{"$ref":"#/components/schemas/DomainKind"},"status":{"$ref":"#/components/schemas/DomainStatusRead"},"spf_status":{"type":["string","null"]},"dkim_status":{"type":["string","null"]},"dmarc_status":{"type":["string","null"]},"verification_records":{"type":"array","items":{}},"last_checked_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"deliverabilityScore":{"type":"integer","minimum":0,"maximum":100},"emailStats":{"type":"object","properties":{"totalSent":{"type":"integer"},"last7Days":{"type":"integer"},"last30Days":{"type":"integer"}},"required":["totalSent","last7Days","last30Days"]},"missingRecords":{"type":"array","items":{"type":"string"}},"recommendationItems":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["SPF","DKIM","DMARC","MX","UNVERIFIED","NO_DOMAINS","OPTIMAL"]},"severity":{"type":"string","enum":["error","warning","info","success"]},"domain":{"type":"string"},"message":{"type":"string"}},"required":["kind","severity","message"]}},"workspaceId":{"type":"string","format":"uuid"},"domainType":{"type":"string","enum":["workspace","custom"]},"sesIdentityArn":{"type":["string","null"]},"region":{"type":["string","null"]},"verified":{"type":"boolean"},"verificationToken":{"type":["string","null"]},"dnsRecords":{"type":"array","items":{}},"records":{"type":"array","items":{}},"isDefault":{"type":["boolean","null"]},"mxVerified":{"type":"boolean"},"dkimVerified":{"type":"boolean"},"spfVerified":{"type":"boolean"},"dmarcVerified":{"type":"boolean"},"lastSetupError":{"type":["string","null"]},"lastSetupAttemptAt":{"type":["string","null"]},"lastCheckedAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","domain","kind","status","created_at","workspaceId","domainType","sesIdentityArn","region","verified","verificationToken","dnsRecords","records","isDefault","mxVerified","dkimVerified","spfVerified","dmarcVerified","lastSetupError","lastSetupAttemptAt","lastCheckedAt","createdAt","updatedAt"]},"DomainKind":{"type":"string","enum":["registered","custom"],"description":"`registered` = domain bought through us; `custom` = customer-owned."},"DomainStatusRead":{"type":"string","description":"Domain provisioning state. Current vocabulary: see DomainStatus. The underlying column is unconstrained text, so a caller must tolerate a value outside it."},"DomainsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Domain"}}},"required":["data"]},"DomainResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"kind":{"$ref":"#/components/schemas/DomainKind"},"status":{"$ref":"#/components/schemas/DomainStatusRead"},"spf_status":{"type":["string","null"]},"dkim_status":{"type":["string","null"]},"dmarc_status":{"type":["string","null"]},"verification_records":{"type":"array","items":{}},"last_checked_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"deliverabilityScore":{"type":"integer","minimum":0,"maximum":100},"emailStats":{"type":"object","properties":{"totalSent":{"type":"integer"},"last7Days":{"type":"integer"},"last30Days":{"type":"integer"}},"required":["totalSent","last7Days","last30Days"]},"missingRecords":{"type":"array","items":{"type":"string"}},"recommendationItems":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["SPF","DKIM","DMARC","MX","UNVERIFIED","NO_DOMAINS","OPTIMAL"]},"severity":{"type":"string","enum":["error","warning","info","success"]},"domain":{"type":"string"},"message":{"type":"string"}},"required":["kind","severity","message"]}},"workspaceId":{"type":"string","format":"uuid"},"domainType":{"type":"string","enum":["workspace","custom"]},"sesIdentityArn":{"type":["string","null"]},"region":{"type":["string","null"]},"verified":{"type":"boolean"},"verificationToken":{"type":["string","null"]},"dnsRecords":{"type":"array","items":{}},"records":{"type":"array","items":{}},"isDefault":{"type":["boolean","null"]},"mxVerified":{"type":"boolean"},"dkimVerified":{"type":"boolean"},"spfVerified":{"type":"boolean"},"dmarcVerified":{"type":"boolean"},"lastSetupError":{"type":["string","null"]},"lastSetupAttemptAt":{"type":["string","null"]},"lastCheckedAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","domain","kind","status","created_at","workspaceId","domainType","sesIdentityArn","region","verified","verificationToken","dnsRecords","records","isDefault","mxVerified","dkimVerified","spfVerified","dmarcVerified","lastSetupError","lastSetupAttemptAt","lastCheckedAt","createdAt","updatedAt"]},"DomainRegisterInput":{"type":"object","properties":{"domain":{"type":"string","minLength":1},"contact_email":{"type":"string","format":"email"}},"required":["domain"],"additionalProperties":false},"DomainCustomInput":{"type":"object","properties":{"domain":{"type":"string","minLength":1,"maxLength":253}},"required":["domain"],"additionalProperties":false},"DomainDeletionImpactMailboxAlias":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"address":{"type":"string"},"is_default":{"type":"boolean"}},"required":["id","address","is_default"]},"DomainDeletionImpactTeamDistributionList":{"type":"object","properties":{"team_id":{"type":"string","format":"uuid"},"team_name":{"type":"string"},"address":{"type":"string"}},"required":["team_id","team_name","address"]},"DomainDeletionImpactResponse":{"type":"object","properties":{"domain_id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"mailbox_aliases":{"type":"array","items":{"$ref":"#/components/schemas/DomainDeletionImpactMailboxAlias"}},"team_distribution_lists":{"type":"array","items":{"$ref":"#/components/schemas/DomainDeletionImpactTeamDistributionList"}}},"required":["domain_id","domain","mailbox_aliases","team_distribution_lists"]},"AdminTestEmailSendResponse":{"type":"object","properties":{"sent":{"type":"boolean"},"email_id":{"type":["string","null"]},"to":{"type":"string"},"subject":{"type":"string"},"event_type":{"type":"string"},"supported_types":{"type":"array","items":{"type":"string"}}},"required":["sent","email_id","to","subject","event_type","supported_types"]},"TestNotificationEmailInput":{"type":"object","properties":{"to":{"type":"string"},"template":{"type":"string"}},"additionalProperties":false},"AdminTestEmailPreviewResponse":{"type":"object","properties":{"html":{"type":"string"},"subject":{"type":"string"},"text":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"event_type":{"type":"string"},"subject":{"type":"string"}},"required":["event_type"]}},"total":{"type":"integer"},"has_more":{"type":"boolean"}}},"MailSuppression":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"type":{"type":"string","enum":["bounce","complaint"]},"reason":{"type":"string"},"subReason":{"type":["string","null"]},"firstSeenAt":{"type":"string"},"lastSeenAt":{"type":"string"},"messageId":{"type":["string","null"]}},"required":["id","email","type","reason","firstSeenAt","lastSeenAt"]},"MailSuppressionsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MailSuppression"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","total","has_more"]},"MailSuppressionResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"type":{"type":"string","enum":["bounce","complaint"]},"reason":{"type":"string"},"subReason":{"type":["string","null"]},"firstSeenAt":{"type":"string"},"lastSeenAt":{"type":"string"},"messageId":{"type":["string","null"]}},"required":["id","email","type","reason","firstSeenAt","lastSeenAt"]},"MailSuppressionCreateInput":{"type":"object","properties":{"email":{"type":"string","format":"email"},"type":{"type":"string","enum":["bounce","complaint"]},"reason":{"type":"string"}},"required":["email","type"],"additionalProperties":false},"Integration":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"provider":{"type":"string"},"config":{"type":"object","additionalProperties":{}},"status":{"type":"string","enum":["active","inactive","error"]},"installedBy":{"type":["string","null"],"format":"uuid"},"firstEventReceivedAt":{"type":["string","null"]},"lastEventReceivedAt":{"type":["string","null"]},"createdAt":{"type":["string","null"]},"updatedAt":{"type":["string","null"]},"hasCredentials":{"type":"boolean"}},"required":["id","workspaceId","provider","config","status","installedBy","firstEventReceivedAt","lastEventReceivedAt","hasCredentials"]},"IntegrationsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Integration"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data"]},"SlackChannel":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"is_private":{"type":"boolean"},"is_archived":{"type":"boolean"},"num_members":{"type":"integer"}},"required":["id","name"]},"SlackChannelsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SlackChannel"}}},"required":["data"]},"IntegrationResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"provider":{"type":"string"},"config":{"type":"object","additionalProperties":{}},"status":{"type":"string","enum":["active","inactive","error"]},"installedBy":{"type":["string","null"],"format":"uuid"},"firstEventReceivedAt":{"type":["string","null"]},"lastEventReceivedAt":{"type":["string","null"]},"createdAt":{"type":["string","null"]},"updatedAt":{"type":["string","null"]},"hasCredentials":{"type":"boolean"}},"required":["id","workspaceId","provider","config","status","installedBy","firstEventReceivedAt","lastEventReceivedAt","hasCredentials"]},"IntegrationUpdateInput":{"type":"object","properties":{"enabled":{"type":"boolean"},"config":{"type":"object","additionalProperties":{}},"status":{"type":"string","enum":["active","inactive","error"]}},"additionalProperties":false},"WorkspaceIntegrationsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceIntegrationSummary"}}},"required":["data"]},"WorkspaceIntegrationSummary":{"type":"object","properties":{"provider":{"type":"string","enum":["turnstile","stripe","google"]},"public_key":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"has_secret":{"type":"boolean"}},"required":["provider","public_key","updated_at","has_secret"]},"WorkspaceIntegrationUpsertInput":{"type":"object","properties":{"provider":{"type":"string","enum":["turnstile","stripe","google"]},"public_key":{"type":"string","minLength":1,"maxLength":500},"secret_key":{"type":"string","minLength":1,"maxLength":500}},"required":["provider","public_key","secret_key"]},"RegistrarConnectionListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RegistrarConnectionSummary"}}},"required":["data"]},"RegistrarConnectionSummary":{"type":"object","properties":{"provider":{"type":"string","enum":["cloudflare"]},"connected":{"type":"boolean"},"masked_hint":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["provider","connected","masked_hint","updated_at"]},"RegistrarConnectInput":{"type":"object","properties":{"provider":{"type":"string","enum":["cloudflare"]},"token":{"type":"string","minLength":1,"maxLength":1000}},"required":["provider","token"]},"RegistrarAutoConfigureResponse":{"type":"object","properties":{"written":{"type":"array","items":{"type":"string"}},"failed":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"reason":{"type":"string"}},"required":["name","type","reason"]}},"domain":{}},"required":["written","failed"]},"RegistrarAutoConfigureInput":{"type":"object","properties":{"domain_id":{"type":"string","format":"uuid"}},"required":["domain_id"]},"AccountReferralsResponse":{"type":"object","properties":{"referral_slug":{"type":["string","null"]},"referral_url":{"type":["string","null"]},"total_friends_invited":{"type":"number"},"total_actions_earned":{"type":"number"},"your_invites":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"invite_type":{"type":"string"},"status":{"type":"string"},"action_grant_earned":{"type":"number"},"perpetual_email_verified_active":{"type":"boolean"},"perpetual_first_agent_active":{"type":"boolean"},"invited_at":{"type":["string","null"]},"accepted_at":{"type":["string","null"]}},"required":["id","email","invite_type","status","action_grant_earned","perpetual_email_verified_active","perpetual_first_agent_active","invited_at","accepted_at"]}},"active_bonuses":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"amount":{"type":"number"},"source_user_id":{"type":["string","null"]},"source_resource_id":{"type":["string","null"]},"earned_at":{"type":["string","null"]},"last_verified_at":{"type":["string","null"]}},"required":["type","amount","source_user_id","source_resource_id","earned_at","last_verified_at"]}},"share_links":{"type":"array","items":{}}},"required":["referral_slug","referral_url","total_friends_invited","total_actions_earned","your_invites","active_bonuses","share_links"]},"DataExportResponse":{"type":"object","properties":{"exported_at":{"type":"string"},"format":{"type":"string","enum":["json","portable"]},"account":{"type":"object","additionalProperties":{}},"profile":{"type":"object","additionalProperties":{}},"documents":{"type":"array","items":{"type":"object","additionalProperties":{}}},"tasks":{"type":"array","items":{"type":"object","additionalProperties":{}}},"contacts":{"type":"array","items":{"type":"object","additionalProperties":{}}},"messages":{"type":"array","items":{"type":"object","additionalProperties":{}}},"emails":{"type":"array","items":{"type":"object","additionalProperties":{}}},"calendar_events":{"type":"array","items":{"type":"object","additionalProperties":{}}},"calendar_ics":{"type":"string"},"drive_files":{"type":"array","items":{"type":"object","additionalProperties":{}}},"wiki_pages":{"type":"array","items":{"type":"object","additionalProperties":{}}},"comments":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["exported_at","account","profile","documents","tasks","contacts","messages","emails","calendar_events","drive_files","wiki_pages","comments"]},"RotateReferralSlugResponse":{"type":"object","properties":{"old_slug":{"type":["string","null"]},"new_slug":{"type":"string"},"referral_url":{"type":"string"}},"required":["old_slug","new_slug","referral_url"]},"ActiveWorkspaceResponse":{"type":"object","properties":{"name":{"type":"string","description":"Active workspace name. Falls back to `Ambiguous` if the JWT has no workspaceId or the workspace row is missing."},"slug":{"type":"string","description":"Active workspace slug. Falls back to `ambiguous` when the workspace row is missing."},"logo_url":{"type":["string","null"],"description":"Workspace logo URL stored in `workspace_settings.workspace_logo_url`. Null when unset."}},"required":["name","slug","logo_url"]},"UpdateWorkspaceConflictResponse":{"type":"object","properties":{"error":{"type":"string","description":"Always `Workspace name has already been customized. Pass { force: true } to overwrite.`."},"current_name":{"type":["string","null"],"description":"The current customized workspace name. UI surfaces this so the user can confirm overwrite."}},"required":["error"]},"CheckSlugResponse":{"anyOf":[{"$ref":"#/components/schemas/CheckSlugAvailableResponse"},{"$ref":"#/components/schemas/CheckSlugUnavailableResponse"}],"description":"Availability decision. Always returns 200 — even malformed/reserved/taken slugs surface as `available: false` with an error message. The 400 status is only used when the `slug` query parameter is missing entirely."},"CheckSlugAvailableResponse":{"type":"object","properties":{"available":{"type":"boolean","enum":[true],"description":"Slug is well-formed AND not taken AND not reserved."}},"required":["available"]},"CheckSlugUnavailableResponse":{"type":"object","properties":{"available":{"type":"boolean","enum":[false],"description":"Slug is taken, reserved, or malformed."},"error":{"type":"string","description":"Human-readable reason. Stable substrings the UI matches against include 'at least 3', 'at most 48', 'lowercase letters, numbers, and hyphens', 'consecutive', 'hyphen', 'reserved', 'taken'."},"code":{"type":"string","description":"Machine-readable reason (e.g. `slug_too_short`, `slug_reserved`, `slug_taken`) so a caller branches on a stable token rather than matching `error` prose. Absent on the missing-parameter 400."},"suggestions":{"type":"array","items":{"type":"string"},"description":"Available alternative slugs (e.g. `acme-2`, `acme-team`). Only present when the slug was rejected because it's taken — not for reserved or malformed inputs."}},"required":["available","error"]},"WorkspaceListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Workspace ID (UUID)."},"name":{"type":"string","description":"Workspace display name."},"slug":{"type":"string","description":"Workspace URL slug."},"role":{"type":"string","description":"Role this account holds in the workspace (`owner`, `admin`, `member`, `guest`, or a custom role name)."},"workspace_email":{"type":["string","null"],"description":"Reserved for the derived workspace email — currently always null at this endpoint."},"joined_at":{"type":["string","null"],"format":"date-time","description":"ISO timestamp the user joined this workspace (`users.created_at`). Null on legacy rows pre-onboarding."},"is_active":{"type":"boolean","description":"True for the workspace this JWT currently scopes to. Exactly one row has this flag set per response."}},"required":["id","name","slug","role","workspace_email","joined_at","is_active"]},"WorkspaceListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceListItem"},"description":"All workspaces the authenticated account belongs to, ordered by `joined_at` ascending."},"total":{"type":"integer","description":"Length of `data`."},"has_more":{"type":"boolean","enum":[false],"description":"Always false. Workspace memberships per account are bounded; pagination is not currently implemented."},"active_workspace_id":{"type":["string","null"],"format":"uuid","description":"ID of the currently-active workspace from the JWT. Matches exactly one `data[*].id` (or null if the user somehow has no active workspace)."}},"required":["data","total","has_more","active_workspace_id"]},"RestoredWorkspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Workspace ID (UUID)."},"name":{"type":"string","description":"Restored workspace display name."},"slug":{"type":"string","description":"Restored workspace URL slug."}},"required":["id","name","slug"]},"RestoreWorkspaceResponse":{"type":"object","properties":{"restored":{"type":"boolean","description":"True when the workspace is no longer archived."},"workspace":{"$ref":"#/components/schemas/RestoredWorkspace"}},"required":["restored","workspace"]},"CreatedWorkspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Workspace ID (UUID)."},"name":{"type":"string","description":"Workspace display name (trimmed)."},"slug":{"type":"string","description":"Workspace URL slug."}},"required":["id","name","slug"],"description":"Newly-created workspace."},"CreatedWorkspaceAgentOnboarding":{"type":"object","properties":{"harness":{"type":["string","null"],"description":"The agent runtime the journey came from, or null when none was identified. Selects which connect instructions the flow opens with."}},"required":["harness"],"description":"Present only when this account signed up through the `intent=invite-agent` journey and has not yet completed the guided create-agent flow. **It carries no agent and no key** — nothing is provisioned here. It is the signal to open `/invite-agent` instead of `/invite-team`, so the person is guided rather than dropped on an empty workspace. Absent on every ordinary signup."},"CreateWorkspaceResponse":{"type":"object","properties":{"workspace":{"$ref":"#/components/schemas/CreatedWorkspace"},"user_id":{"type":"string","format":"uuid","description":"`users.id` of the founding user row inside the new workspace."},"username":{"type":["string","null"],"description":"Workspace email local-part (e.g. `ryan`). Null when no email domain is configured for the workspace."},"workspace_email":{"type":"string","description":"Founder's derived workspace email (`{username}@{domain}`)."},"domain":{"type":"string","description":"Workspace email subdomain (e.g. `acme.ambi.cc`)."},"token":{"type":"string","description":"Fresh JWT scoped to the new workspace. Replaces the registration_token (which is single-use)."},"agent_onboarding":{"$ref":"#/components/schemas/CreatedWorkspaceAgentOnboarding"}},"required":["workspace","user_id","username","workspace_email","domain","token"]},"CreateWorkspaceBody":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"emailLocalPart":{"type":"string"},"registration_token":{"type":"string"},"code":{"type":"string"}},"additionalProperties":false},"SwitchedWorkspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Workspace ID (UUID)."},"name":{"type":"string","description":"Target workspace display name."},"slug":{"type":"string","description":"Target workspace URL slug."}},"required":["id","name","slug"]},"SwitchWorkspaceResponse":{"type":"object","properties":{"token":{"type":"string","description":"Fresh JWT carrying the target workspace ID. Use as the `Authorization: Bearer` for all subsequent requests."},"workspace":{"$ref":"#/components/schemas/SwitchedWorkspace"}},"required":["token","workspace"]},"WebhookEventType":{"type":"object","properties":{"type":{"type":"string"},"description":{"type":"string"}},"required":["type","description"]},"WebhookEventTypesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventType"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"name":{"type":["string","null"]},"events":{"type":"array","items":{"type":"string"}},"description":{"type":["string","null"]},"active":{"type":"boolean"},"failure_count":{"type":"integer","minimum":0},"last_delivered_at":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","url","events","description","active","failure_count"]},"WebhookListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"WebhookWithSecret":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"secret":{"type":"string","description":"HMAC signing secret. Only returned at creation time."}},"required":["secret"]}]},"CreateWebhookBody":{"type":"object","properties":{"url":{"type":"string"},"name":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":"string"}},"additionalProperties":false},"UpdateWebhookBody":{"type":"object","properties":{"url":{"type":"string"},"name":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":"string"},"active":{}},"additionalProperties":false},"RotateSecretResponse":{"type":"object","properties":{"secret":{"type":"string"},"previous_secret_expires_at":{"type":"string","description":"ISO-8601. Old secret remains valid until this timestamp (24h grace)."}},"required":["secret","previous_secret_expires_at"]},"RevokePreviousSecretResponse":{"type":"object","properties":{"revoked":{"type":"boolean"}},"required":["revoked"]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"event_type":{"type":"string"},"payload":{"type":"object","additionalProperties":{}},"status_code":{"type":["integer","null"]},"success":{"type":"boolean"},"attempts":{"type":"integer","minimum":0},"delivered_at":{"type":["string","null"]}},"required":["id","event_type","payload","status_code","success","attempts"]},"WebhookDeliveryListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"TestPingResponse":{"type":"object","properties":{"success":{"type":"boolean"},"status_code":{"type":["integer","null"]},"attempts":{"type":"integer","minimum":0},"error":{"type":["string","null"]}},"required":["success","attempts"]},"Notification":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"recipientId":{"type":"string","format":"uuid"},"eventType":{"type":"string"},"payload":{"$ref":"#/components/schemas/NotificationPayload"},"read":{"type":"boolean"},"dismissedAt":{"type":["string","null"]},"snoozedUntil":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","recipientId","eventType","payload","read","dismissedAt","snoozedUntil","createdAt"]},"NotificationPayload":{"type":"object","properties":{"resourceId":{"type":"string"},"resourceType":{"type":"string"},"resourceUrl":{"type":"string"},"summary":{"type":"string"},"actor":{"$ref":"#/components/schemas/NotificationActor"},"data":{"type":"object","additionalProperties":{}},"deliveryChannels":{"type":"array","items":{"$ref":"#/components/schemas/NotificationDeliveryChannel"}}},"required":["resourceId","resourceType","resourceUrl","summary","actor"]},"NotificationActor":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":["string","null"]}},"required":["id","name"]},"NotificationDeliveryChannel":{"type":"string","enum":["in_app","email","push"]},"NotificationListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Notification"}},"has_more":{"type":"boolean"},"next_cursor":{"type":"string"},"unreadCount":{"type":"integer","minimum":0},"totalCount":{"type":"integer","minimum":0},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["data","has_more","unreadCount","totalCount","limit","offset"]},"NotificationMute":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"resourceType":{"type":["string","null"]},"resourceId":{"type":["string","null"]},"eventType":{"type":["string","null"]},"until":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","userId","resourceType","resourceId","eventType","until","createdAt"]},"MutesListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/NotificationMute"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"MuteResponse":{"type":"object","properties":{"mute":{"$ref":"#/components/schemas/NotificationMute"}},"required":["mute"]},"OkResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"MarkReadResult":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"was_unread":{"type":"boolean"}},"required":["ok","was_unread"]},"GenerateImageResponse":{"type":"object","properties":{"url":{"type":"string","description":"Generated image as a `data:` URL (base64-encoded). Embed directly into Docs/Slides without a separate Drive upload step."}},"required":["url"]},"BusinessCardFields":{"type":"object","properties":{"name":{"type":["string","null"],"description":"Person's full name, or null."},"title":{"type":["string","null"],"description":"Job title, or null."},"company":{"type":["string","null"],"description":"Company name, or null."},"email":{"type":["string","null"],"description":"Email address, or null."},"phone":{"type":["string","null"],"description":"Phone in the format printed on the card, or null."},"website":{"type":["string","null"],"description":"Website without protocol (e.g. `acme.com`), or null."},"address":{"type":["string","null"],"description":"Physical address joined into one line, or null."},"notes":{"type":["string","null"],"description":"Anything else printed on the card — social handles, fax, secondary phone, tagline. Null when nothing extra is present."}},"required":["name","title","company","email","phone","website","address","notes"]},"ScanBusinessCardResponse":{"type":"object","properties":{"fields":{"$ref":"#/components/schemas/BusinessCardFields"}},"required":["fields"]},"TranscribeAudioResponse":{"type":"object","properties":{"text":{"type":"string","description":"The cleaned transcript. Whisper artifacts (`[silence]`, `(inaudible)`, the silence-fallback `you`) are stripped before return; an empty-speech response surfaces as 422 `No speech detected` instead of an empty string here."},"duration":{"type":"number","description":"Audio duration in seconds, as reported by Whisper's `verbose_json` response. Used by the metering middleware to compute `ceil(duration / 60)` minutes for the per-minute action debit."},"language":{"type":"string","description":"Whisper's detected language (full English name, e.g. `english`, `spanish`). Absent when `language` was supplied on the request."}},"required":["text"]},"TranscribeAudioInput":{"type":"object","properties":{"audio":{"description":"Audio file to transcribe. Accepted formats: mp3, mp4, mpeg, mpga, m4a, wav, webm. Max 25 MB. Whisper hard-cap of 15 minutes per request applies (anti-abuse — files > 15 min return 413)."},"language":{"type":"string","description":"ISO-639-1 language code (e.g. `en`, `es`, `fr`). When provided, Whisper skips automatic detection and decodes against the named language — improves accuracy for short clips or accented speech."},"prompt":{"type":"string","description":"Optional decoder priming string. Whisper biases the transcript toward vocabulary in this string (proper nouns, jargon). Max 224 tokens — anything beyond is silently truncated upstream."}}},"UnreadChannelBadge":{"type":"object","properties":{"channelId":{"type":"string"},"badge":{"type":"integer","minimum":0},"mentions":{"type":"integer","minimum":0},"display":{"type":"string","enum":["count","dot","since_visit"]},"lastReadAt":{"type":["string","null"]},"isDm":{"type":"boolean"},"muted":{"type":"boolean"},"hasUnread":{"type":"boolean"}},"required":["channelId","badge","mentions","display","lastReadAt","isDm","muted","hasUnread"]},"UnreadCountsResponse":{"type":"object","properties":{"mail":{"type":"object","properties":{"inbox":{"type":"integer","minimum":0}},"required":["inbox"]},"chat":{"type":"object","properties":{"channels":{"type":"array","items":{"$ref":"#/components/schemas/UnreadChannelBadge"}},"dms":{"type":"array","items":{"$ref":"#/components/schemas/UnreadChannelBadge"}},"threads":{"type":"integer","minimum":0},"mentions":{"type":"integer","minimum":0},"reactions":{"type":"integer","minimum":0}},"required":["channels","dms","threads","mentions","reactions"]},"notifications":{"type":"object","properties":{"unread":{"type":"integer","minimum":0},"counted":{"type":"integer","minimum":0}},"required":["unread","counted"]},"total":{"type":"integer","minimum":0}},"required":["mail","chat","notifications","total"]},"WidgetSummaryResponse":{"type":"object","properties":{"generated_at":{"type":"string"},"user":{"type":["object","null"],"properties":{"id":{"type":"string"},"display_name":{"type":["string","null"]},"avatar_url":{"type":["string","null"]}},"required":["id","display_name","avatar_url"]},"unread":{"type":"object","properties":{"mail":{"type":"integer"},"chat":{"type":"integer"},"total":{"type":"integer"}},"required":["mail","chat","total"]},"tasks_today":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"priority":{"type":["string","null"]},"status":{"type":"string"},"due_date":{"type":["string","null"]},"task_status_id":{"type":["string","null"]},"task_status_name":{"type":["string","null"]},"task_status_category":{"type":["string","null"]}},"required":["id","title","priority","status","due_date","task_status_id","task_status_name","task_status_category"]}},"next_events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"start_at":{"type":["string","null"]},"end_at":{"type":["string","null"]},"location":{"type":["string","null"]},"all_day":{"type":"boolean"}},"required":["id","title","start_at","end_at","location","all_day"]}}},"required":["generated_at","user","unread","tasks_today","next_events"]},"PushSubscribeResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"PushUnsubscribeResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"PushVapidKeyResponse":{"type":"object","properties":{"public_key":{"type":"string","description":"VAPID public key (base64url, uncompressed P-256). Pass to `PushManager.subscribe({applicationServerKey})`."}},"required":["public_key"]},"ChatSidebarSection":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"name":{"type":"string"},"position":{"type":"integer"},"channelIds":{"type":"array","items":{"type":"string","format":"uuid"}},"createdAt":{"type":"string"}},"required":["id","workspaceId","userId","name","position","channelIds","createdAt"]},"ChatSidebarSectionListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChatSidebarSection"}}},"required":["data"]},"ChatSidebarCreateInput":{"type":"object","properties":{"name":{"type":"string"},"channelIds":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["name"],"additionalProperties":false},"ChatSidebarReorderInput":{"type":"object","properties":{"sectionIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1}},"required":["sectionIds"],"additionalProperties":false},"ChatSidebarUpdateInput":{"type":"object","properties":{"name":{"type":"string"},"channelIds":{"type":"array","items":{"type":"string","format":"uuid"}}},"additionalProperties":false},"ChatSidebarDeleteResponse":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"ChatDraft":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"channelId":{"type":["string","null"],"format":"uuid"},"threadParentId":{"type":["string","null"],"format":"uuid"},"tier":{"type":"string","enum":["inflight","saved"]},"content":{"type":"string"},"preview":{"type":"string"},"suggestedChannelId":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"firstSurfacedAt":{"type":["string","null"]}},"required":["id","workspaceId","userId","channelId","threadParentId","tier","content","preview","suggestedChannelId","createdAt","updatedAt","firstSurfacedAt"]},"ChatDraftListResponse":{"type":"object","properties":{"drafts":{"type":"array","items":{"$ref":"#/components/schemas/ChatDraft"}}},"required":["drafts"]},"ChatDraftUpsertResponse":{"anyOf":[{"$ref":"#/components/schemas/ChatDraft"},{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"]}]},"ChatDraftUpsertInput":{"type":"object","properties":{"channel_id":{"type":"string","format":"uuid"},"thread_parent_id":{"type":["string","null"],"format":"uuid"},"content":{"type":"string"},"preview":{"type":"string"},"first_surfaced_at":{"type":["string","null"]}},"required":["channel_id","content","preview"],"additionalProperties":false},"ChatDraftCreateInput":{"type":"object","properties":{"content":{"type":"string"},"preview":{"type":"string"},"suggested_channel_id":{"type":["string","null"],"format":"uuid"}},"required":["content","preview"],"additionalProperties":false},"ChatDraftUpdateInput":{"type":"object","properties":{"content":{"type":"string"},"preview":{"type":"string"},"suggested_channel_id":{"type":["string","null"],"format":"uuid"}},"additionalProperties":false},"PresenceHeartbeatResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]},"PresenceStatusResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PresenceStatusMap"},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"PresenceStatusMap":{"type":"object","additionalProperties":{"type":"boolean"}},"PresenceDetailedResponse":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PresenceDetailedEntry"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"PresenceDetailedEntry":{"type":"object","properties":{"status":{"type":"string","enum":["online","idle","offline"]},"lastActiveAt":{"type":["string","null"]}},"required":["status","lastActiveAt"]},"PresenceResolvedResponse":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PresenceResolvedEntry"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"PresenceResolvedEntry":{"type":"object","properties":{"kind":{"type":"string","enum":["human","agent"]},"state":{"type":"string","enum":["available","away","offline","dnd","working","standby","paused"]}},"required":["kind","state"]},"AssistantCapabilities":{"type":"object","properties":{"model":{"type":"string","description":"Active LLM model identifier (e.g. `gpt-5.4-mini`). Surfaced in the assistant header so users see what is answering them."}},"required":["model"]},"AssistantRecentActivityEntry":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tool_name":{"type":"string","description":"Assistant tool that produced the entry (e.g. `create_task`)."},"resource_type":{"type":["string","null"],"description":"Resource the tool created/modified (e.g. `task`, `document`). Null for tool calls without a resource (rare)."},"resource_id":{"type":["string","null"]},"resource_title":{"type":["string","null"]},"path":{"type":["string","null"],"description":"Router path the UI should navigate to on click (e.g. `/tasks`, `/docs/abc`). Null when the tool has no canonical destination."},"created_at":{"type":"string","description":"ISO 8601 timestamp."}},"required":["id","tool_name","resource_type","resource_id","resource_title","path","created_at"]},"AssistantRecentActivityResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AssistantRecentActivityEntry"}}},"required":["data"]},"AssistantToolCallResult":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"args":{"type":"object","additionalProperties":{}},"status":{"type":"string","enum":["success","error"]},"result":{},"error":{"type":"string"}},"required":["id","name","args","status"]},"AssistantSpearSections":{"type":"object","properties":{"scope":{"type":"string"},"plan":{"type":"string"},"execute":{"type":"string"},"assess":{"type":"string"},"resolve":{"type":"string"},"report":{"type":"string"}}},"AssistantInteractiveInput":{"type":"object","properties":{"type":{"type":"string","enum":["confirm","select"]},"options":{"type":"array","items":{"$ref":"#/components/schemas/AssistantInteractiveOption"}}},"required":["type","options"]},"AssistantInteractiveOption":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"},"description":{"type":"string"},"variant":{"type":"string","enum":["primary","secondary","destructive"]}},"required":["label","value"]},"AssistantThinkingLevel":{"type":"string","enum":["none","low","medium","high"]},"AssistantChatResponse":{"type":"object","properties":{"response":{"type":"string"},"toolCalls":{"type":"array","items":{"$ref":"#/components/schemas/AssistantToolCallResult"}},"spear":{"anyOf":[{"$ref":"#/components/schemas/AssistantSpearSections"},{"type":"null"}]},"interactiveInputs":{"$ref":"#/components/schemas/AssistantInteractiveInput"},"thinkingLevel":{"$ref":"#/components/schemas/AssistantThinkingLevel"},"reasoning":{"type":"string"},"status":{"type":"string","enum":["success","error"]},"error":{"type":"string"}},"required":["response","toolCalls","spear","status"]},"AssistantChatRequestBody":{"type":"object","properties":{"message":{},"context":{},"history":{},"attachments":{},"thinkingLevelOverride":{},"conversationId":{}},"additionalProperties":false},"AssistantMigrateConversationsResponse":{"type":"object","properties":{"migrated_count":{"type":"integer"},"id_map":{"type":"object","additionalProperties":{"type":"string"}}},"required":["migrated_count","id_map"]},"AssistantMigrateConversationsBody":{"type":"object","properties":{"conversations":{"type":"array","items":{"$ref":"#/components/schemas/AssistantMigrateConversationInput"}}},"required":["conversations"]},"AssistantMigrateConversationInput":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"pinned":{"type":"boolean"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/AssistantMigrateMessageInput"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","title","messages"]},"AssistantMigrateMessageInput":{"type":"object","properties":{"role":{"type":"string"},"content":{},"timeline":{},"thinkingLevel":{"type":"string"},"hasToolErrors":{"type":"boolean"},"createdAt":{"type":"string"}},"required":["role"]},"AssistantConversation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"pinned":{"type":"boolean"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","workspace_id","user_id","title","pinned","created_at","updated_at"]},"AssistantListConversationsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AssistantConversation"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["data","has_more","next_cursor"]},"AssistantConversationMessage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"conversation_id":{"type":"string","format":"uuid"},"role":{"type":"string"},"content":{},"timeline":{},"thinking_level":{"type":["string","null"]},"reasoning":{"type":["string","null"],"description":"Stored reasoning summary of the assistant turn, capped at 32,000 chars head-keep with a visible `...[truncated N chars]` marker. Owner-only — never present on the public share projection."},"has_tool_errors":{"type":"boolean"},"created_at":{"type":"string"}},"required":["id","conversation_id","role","thinking_level","has_tool_errors","created_at"]},"AssistantConversationWithMessages":{"allOf":[{"$ref":"#/components/schemas/AssistantConversation"},{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/AssistantConversationMessage"}}},"required":["messages"]}]},"AssistantCreateConversationBody":{"type":"object","properties":{"title":{"type":"string"}}},"AssistantUpdateConversationBody":{"type":"object","properties":{"title":{"type":"string"},"pinned":{"type":"boolean"},"lastSeenMessageCount":{"type":"integer","minimum":0}}},"AssistantShareConversationResponse":{"type":"object","properties":{"conversation_id":{"type":"string","format":"uuid"},"share_token":{"type":"string"},"share_url":{"type":"string"}},"required":["conversation_id","share_token","share_url"]},"CheckoutResponse":{"type":"object","properties":{"session_id":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["session_id","url"]},"PortalResponse":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]},"CancelSubscriptionResponse":{"type":"object","properties":{"canceled":{"type":"boolean"},"cancel_at_period_end":{"type":"boolean"},"current_period_end":{"type":["string","null"]},"plan_lookup_key":{"type":["string","null"]}},"required":["canceled","cancel_at_period_end","current_period_end","plan_lookup_key"]},"PlanTier":{"type":"string","enum":["free","pro"],"description":"Workspace billing tier. `free` is the default; `pro` is the paid Stripe plan."},"PlanDisplay":{"type":"object","properties":{"tier":{"$ref":"#/components/schemas/PlanTier"},"badge":{"type":["string","null"],"enum":["trial","past_due","canceling","canceled",null]},"access_until":{"type":["string","null"]},"renews_at":{"type":["string","null"]}},"required":["tier","badge","access_until","renews_at"]},"SubscriptionResponse":{"type":"object","properties":{"subscription":{"anyOf":[{"$ref":"#/components/schemas/WorkspaceSubscription"},{"type":"null"}]},"plan_tier":{"$ref":"#/components/schemas/PlanTier"},"status":{"$ref":"#/components/schemas/SubscriptionStatus"},"is_trial":{"type":"boolean"},"trial_days_remaining":{"type":["integer","null"]},"display":{"$ref":"#/components/schemas/PlanDisplay"}},"required":["subscription","plan_tier","status","is_trial","trial_days_remaining","display"]},"Plan":{"type":"object","properties":{"tier":{"$ref":"#/components/schemas/PlanTier"},"name":{"type":"string"},"description":{"type":"string"},"lookup_key":{"type":"string"},"price":{"type":["string","null"]},"price_per_seat_cents":{"type":"integer"},"currency":{"type":"string"},"features":{"type":"array","items":{"type":"string"}},"seat_limit":{"type":["integer","null"]},"document_limit":{"type":["integer","null"]},"storage_bytes_limit":{"type":["integer","null"]},"ai_token_limit":{"type":["integer","null"]}},"required":["tier","name","seat_limit","document_limit","storage_bytes_limit"],"additionalProperties":{}},"PlansListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Plan"}},"total":{"type":"integer"},"has_more":{"type":"boolean","enum":[false]}},"required":["data","total","has_more"]},"SeatBreakdown":{"type":"array","items":{"$ref":"#/components/schemas/SeatRoleCount"}},"SeatRoleCount":{"type":"object","properties":{"role":{"type":"string"},"count":{"type":"integer","minimum":0}},"required":["role","count"]},"SeatsResponse":{"type":"object","properties":{"current_seats":{"type":"integer"},"limited_count":{"type":"integer","minimum":0},"agent_count":{"type":"integer","minimum":0},"subscription_quantity":{"type":["integer","null"]},"plan_tier":{"$ref":"#/components/schemas/PlanTier"},"breakdown":{"$ref":"#/components/schemas/SeatBreakdown"}},"required":["current_seats","limited_count","agent_count","subscription_quantity","plan_tier","breakdown"]},"SeatsSyncResponse":{"type":"object","properties":{"synced":{"type":"boolean"},"quantity":{"type":"integer"},"reason":{"type":"string"}},"required":["synced"]},"UsageResponse":{"type":"object","properties":{"plan_tier":{"$ref":"#/components/schemas/PlanTier"},"limits":{"type":"object","properties":{"users":{"type":["integer","null"]},"agents":{"type":["integer","null"]},"documents":{"type":["integer","null"]},"storage_bytes":{"type":["integer","null"]}},"required":["users","agents","documents","storage_bytes"]},"usage":{"type":"object","properties":{"users":{"type":"integer"},"agents":{"type":"integer"},"documents":{"type":"integer"},"storage_bytes":{"type":"integer"}},"required":["users","agents","documents","storage_bytes"],"additionalProperties":{}}},"required":["plan_tier","limits","usage"],"additionalProperties":{}},"AiUsageResponse":{"type":"object","properties":{"plan_tier":{"$ref":"#/components/schemas/PlanTier"},"ai_actions":{"type":"object","properties":{"used":{"type":"integer"},"limit":{"type":["integer","null"]},"percent_used":{"type":"number"},"next_reset_at":{"type":"string"}},"required":["used","limit","percent_used"],"additionalProperties":{}}},"required":["plan_tier","ai_actions"],"additionalProperties":{}},"FeaturesResponse":{"type":"object","properties":{"plan_tier":{"$ref":"#/components/schemas/PlanTier"},"features":{"type":"object","additionalProperties":{"type":"boolean"}}},"required":["plan_tier","features"],"additionalProperties":{}},"Invoice":{"type":"object","properties":{"id":{"type":"string"},"number":{"type":["string","null"]},"status":{"type":["string","null"]},"amount_due":{"type":"integer"},"amount_paid":{"type":"integer"},"currency":{"type":"string"},"period_start":{"type":["integer","null"]},"period_end":{"type":["integer","null"]},"hosted_invoice_url":{"type":["string","null"]},"invoice_pdf":{"type":["string","null"]},"created":{"type":"integer"}},"required":["id","status","amount_due","amount_paid","currency","period_start","period_end","created"],"additionalProperties":{}},"InvoicesResponse":{"type":"object","properties":{"invoices":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}},"has_more":{"type":"boolean"}},"required":["invoices","has_more"]},"Discount":{"type":"object","properties":{"id":{"type":"string"},"coupon_id":{"type":"string"},"coupon_name":{"type":["string","null"]},"amount_off":{"type":["integer","null"]},"percent_off":{"type":["number","null"]},"currency":{"type":["string","null"]},"duration":{"$ref":"#/components/schemas/DiscountDuration"},"duration_in_months":{"type":["integer","null"]},"promotion_code":{"type":["string","null"]},"start":{"type":["integer","null"]},"end":{"type":["integer","null"]},"valid":{"type":"boolean"}},"required":["id","coupon_id","coupon_name","amount_off","percent_off","currency","duration","duration_in_months","promotion_code","start","end","valid"],"additionalProperties":{}},"DiscountDuration":{"type":"string","enum":["once","repeating","forever"],"description":"Stripe coupon duration model."},"DiscountResponse":{"type":"object","properties":{"discount":{"anyOf":[{"$ref":"#/components/schemas/Discount"},{"type":"null"}]}},"required":["discount"]},"RemoveDiscountResponse":{"type":"object","properties":{"removed":{"type":"boolean"}},"required":["removed"]},"EarnedBonusEntry":{"type":"object","properties":{"id":{"type":"string"},"bonus_type":{"type":"string"},"category":{"type":"string","enum":["perpetual","one_time"]},"amount":{"type":"integer"},"earned_at":{"type":"string"},"actor_name":{"type":"string"}},"required":["id","bonus_type","category","amount","earned_at"]},"EarnedBonusesResponse":{"type":"object","properties":{"bonuses":{"type":"array","items":{"$ref":"#/components/schemas/EarnedBonusEntry"}}},"required":["bonuses"]},"TopUpCheckoutResponse":{"type":"object","properties":{"session_id":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["session_id","url"]},"TopUpPack":{"type":"string","enum":["small","medium","large"],"description":"Top-up pack size — small (500 actions / $5), medium (2,500 / $20), large (10,000 / $50)."},"AutoRechargeGetResponse":{"type":"object","properties":{"config":{"anyOf":[{"$ref":"#/components/schemas/AutoRechargeConfig"},{"type":"null"}]}},"required":["config"]},"AutoRechargeUpdateResponse":{"type":"object","properties":{"config":{"$ref":"#/components/schemas/AutoRechargeConfig"}},"required":["config"]},"PerSeatCapConfig":{"type":"object","properties":{"enabled":{"type":"boolean"},"amount_per_seat":{"type":"integer","exclusiveMinimum":0}},"required":["enabled","amount_per_seat"]},"PerSeatCapGetResponse":{"type":"object","properties":{"config":{"anyOf":[{"$ref":"#/components/schemas/PerSeatCapConfig"},{"type":"null"}]}},"required":["config"]},"PerSeatCapUpdateResponse":{"type":"object","properties":{"config":{"$ref":"#/components/schemas/PerSeatCapConfig"}},"required":["config"]},"QuotaNotificationDismissResponse":{"type":"object","properties":{"dismissed_thresholds":{"type":"array","items":{"type":"integer"}}},"required":["dismissed_thresholds"]},"ActionsLedgerEntry":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"timestamp":{"type":"string"},"source":{"$ref":"#/components/schemas/ActionsLedgerSource"},"tool":{"type":"string"},"label":{"type":"string"},"llm_cost":{"type":"integer","minimum":0},"vendor_cost":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0},"duration_minutes":{"type":["integer","null"],"minimum":0},"turn_id":{"type":["string","null"]},"turn_label":{"type":["string","null"]},"caller_id":{"type":["string","null"]},"caller_label":{"type":["string","null"]}},"required":["id","timestamp","source","tool","label","llm_cost","vendor_cost","total","duration_minutes","turn_id","turn_label","caller_id","caller_label"]},"ActionsLedgerSource":{"type":"string","enum":["spear","coworker_microservice","coworker_byo","human_direct_ui"],"description":"Caller class — drives the metering dispatch matrix."},"ActionsLedgerResponse":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/ActionsLedgerEntry"}},"next_cursor":{"type":["string","null"]},"total":{"type":"integer","minimum":0}},"required":["entries","next_cursor","total"]},"VerifyForwardingInput":{"type":"object","properties":{"token":{"type":"string","minLength":16,"description":"Single-use verification token from the click-through link."}},"required":["token"],"additionalProperties":false},"SearchResultItem":{"type":"object","properties":{"module":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"},"subtitle":{"type":"string"}},"required":["module","id"],"additionalProperties":{}},"SearchResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SearchResultItem"}},"total":{"type":"integer"},"has_more":{"type":"boolean"},"query":{"type":"string"}},"required":["data","total","has_more","query"],"additionalProperties":{}},"SearchPreviewResponse":{"type":"object","properties":{"preview":{"description":"Per-module preview shape (see PRODUCT.md hover card spec)."}}},"CreatedInvite":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Invite row ID."},"email":{"type":"string","description":"Recipient email (empty for generic links)."},"role":{"type":"string","description":"Granted role (`admin` or `member`)."},"token":{"type":"string","description":"Invite token — embedded in the accept link sent via email."},"expires_at":{"type":"string","description":"ISO 8601 expiration — matches `INVITE_EXPIRY_DAYS`."}},"required":["id","email","role","token","expires_at"]},"CreateInvitesResponse":{"type":"object","properties":{"invites":{"type":"array","items":{"$ref":"#/components/schemas/CreatedInvite"},"description":"One row per invite created (1-N)."},"invite_url":{"type":"string","format":"uri","description":"Pre-built accept URL — present for generic invite links so the caller can copy/paste without rebuilding it."}},"required":["invites"]},"InviteContextCreatedResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"The invitation continuation cookie was set. No access has been accepted."}},"required":["success"]},"InviteContextInput":{"type":"object","properties":{"token":{"type":"string","minLength":1,"maxLength":256}},"required":["token"],"additionalProperties":false},"InviteContextResponse":{"allOf":[{"$ref":"#/components/schemas/InviteDetails"},{"type":"object","properties":{"resources":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"title":{"type":"string"},"role":{"type":"string"},"destination":{"type":["string","null"]}},"required":["id","type","title","role","destination"]}},"invite_id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["pending","accepted","expired","revoked","unavailable"]},"account":{"type":"object","properties":{"state":{"type":"string","enum":["signed_out","matching","mismatch","unverified"]},"email":{"type":"string"},"active_workspace_id":{"type":"string","format":"uuid"},"workspaces":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]}}},"required":["state","workspaces"]}},"required":["resources","invite_id","state","account"]}]},"InviteDetails":{"type":"object","properties":{"email":{"type":"string","description":"Email the invite was addressed to (empty for generic links)."},"role":{"type":"string","description":"Role the recipient will receive on accept."},"workspace_id":{"type":["string","null"],"format":"uuid","description":"Target workspace ID."},"workspace_name":{"type":"string","description":"Target workspace display name (defaults to `Ambiguous`)."},"workspace_slug":{"type":"string","description":"Target workspace slug (defaults to `ambiguous`)."},"inviter_name":{"type":"string","description":"Display name of the user who created the invite. Falls back to `A teammate` when the inviter row can't be resolved."},"expires_at":{"type":"string","description":"ISO 8601 expiration timestamp."},"invite_type":{"type":"string","description":"What accepting produces. `external_grant` binds a per-resource grant to one identity the accepter already owns and writes no `users` row here; every other value is an arrival into the workspace. The accept page cannot tell the two apart from the other fields — both carry a workspace and a role — so the outcome has to be stated."},"resources":{"type":"array","items":{"type":"object","properties":{"resource_type":{"type":"string","enum":["document","wiki_page","file","calendar","form"]},"resource_id":{"type":"string","format":"uuid"},"resource_title":{"type":["string","null"]},"resource_role":{"type":"string","enum":["viewer","commenter","editor","owner"]},"resource_path":{"type":["string","null"],"description":"In-app route this grant opens. Built server-side because `resource_type` cannot reach it: `document` covers docs, sheets and slides, which live on three routes."}},"required":["resource_type","resource_id","resource_title","resource_role","resource_path"]},"description":"Every resource an `external_grant` grants, oldest first. Legacy invitations can contain several resources; new document invitations each describe one share. Empty on a membership invite, which grants no single resource. `resource_role` is the share role on that resource, never the workspace `role` above."}},"required":["email","role","workspace_id","workspace_name","workspace_slug","inviter_name","invite_type"]},"AcceptedInviteMeta":{"type":"object","properties":{"invite_id":{"type":"string"},"invite_type":{"type":"string","enum":["coworker","member","friend","share_friend","external_grant"]},"workspace_id":{"type":["string","null"]},"accepter_account_id":{"type":["string","null"]},"accepter_user_id":{"type":"string"},"inviter_account_id":{"type":["string","null"]},"inviter_workspace_id":{"type":["string","null"]}},"required":["invite_id","invite_type","workspace_id","accepter_account_id","accepter_user_id","inviter_account_id","inviter_workspace_id"]},"AcceptInviteResponse":{"type":"object","properties":{"destination":{"type":"string","description":"Canonical accepted resource route, derived by the server."},"account_id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["human","agent"]},"role":{"type":"string"},"token":{"type":"string","description":"Freshly-issued JWT — replace any prior credential with this one to begin acting in the target workspace."},"user_id":{"type":"string","format":"uuid"},"email":{"type":"string"},"primary_email":{"type":"string","description":"Account-level primary email (login identity)."},"workspace_email":{"type":["string","null"],"description":"Per-workspace email (e.g. `alice@acme.ambi.cc`). Null until the workspace email is provisioned."},"display_name":{"type":"string"},"workspace_added":{"type":"boolean","description":"True when an EXISTING user was added to a new workspace; absent / false on first registration via invite."},"invite_meta":{"$ref":"#/components/schemas/AcceptedInviteMeta"},"workspaces":{"type":"array","items":{"type":"object","properties":{"workspaceId":{"type":"string","format":"uuid"},"displayName":{"type":["string","null"]},"role":{"type":["string","null"]}},"required":["workspaceId","displayName","role"]},"description":"All workspaces the user now belongs to after accepting (sorted in the order returned by the service)."}},"required":["token","user_id","primary_email","workspace_email","display_name","invite_meta"]},"InviteContextMutationInput":{"type":"object","properties":{"display_name":{"type":"string","description":"Display name to set on a newly-created account. Membership invites only — required when accepting one as a brand-new user, ignored when an authenticated user accepts a second-workspace invite, and never honored on an `external_grant`, which refuses an unauthenticated accept outright."},"password":{"type":"string","description":"Password for the new account. Membership invites only, on the same terms as `display_name` above."},"accept_as_workspace_id":{"type":"string","format":"uuid","description":"`external_grant` only: which of the accepter's own identities the grant binds to, named by the workspace that identity lives in. Sent only when the accepter chose — an account holding one identity has nothing to choose and omits it. Resolved against the accepting account's own rows, so it can never name another account's identity."},"expected_invite_id":{"type":"string","format":"uuid","description":"Reject if another tab replaced the invitation context."}},"required":["expected_invite_id"],"additionalProperties":false},"DeclineInviteResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"True — the invite token is invalidated and can no longer be accepted."}},"required":["success"]},"ActivityEntry":{"type":"object","properties":{"id":{"type":"integer"},"user_id":{"type":["string","null"]},"user_name":{"type":["string","null"]},"user_primary_email":{"type":["string","null"]},"user_avatar":{"type":["string","null"]},"action":{"type":"string"},"resource_type":{"type":["string","null"]},"resource_id":{"type":["string","null"]},"metadata":{},"created_at":{"type":["string","null"]}},"required":["id","user_id","user_name","user_primary_email","user_avatar","action","resource_type","resource_id","created_at"]},"ActivityListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ActivityEntry"}},"total":{"type":"integer"},"has_more":{"type":"boolean"}},"required":["data","total","has_more"]},"HomeVelocity":{"type":"object","properties":{"completed":{"type":"integer","description":"Tasks completed in the trailing window."},"updated":{"type":"integer","description":"Tasks with updates in the trailing window."},"opened":{"type":"integer","description":"Tasks newly opened in the trailing window."},"deltas":{"$ref":"#/components/schemas/HomeVelocityCounts"}},"required":["completed","updated","opened","deltas"]},"HomeVelocityCounts":{"type":"object","properties":{"completed":{"type":"integer"},"updated":{"type":"integer"},"opened":{"type":"integer"}},"required":["completed","updated","opened"],"description":"Current-window count minus the prior window of the same length (may be negative)."},"HomeDigestActor":{"type":"object","properties":{"actor":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"avatar_url":{"type":["string","null"]}},"required":["id","name","avatar_url"]},"actor_type":{"type":"string","enum":["human","agent"],"description":"Coworker rows carry the 'AI' badge on the surface; humans do not."},"counts_by_module":{"type":"array","items":{"$ref":"#/components/schemas/HomeDigestModuleCount"},"description":"Top modules the actor touched in the window, capped server-side."},"last_at":{"type":"string","description":"ISO-8601 timestamp of the actor's most recent activity in the window."}},"required":["actor","actor_type","counts_by_module","last_at"]},"HomeDigestModuleCount":{"type":"object","properties":{"module":{"type":"string"},"count":{"type":"integer"}},"required":["module","count"]},"HomeDigestResponse":{"type":"object","properties":{"velocity":{"$ref":"#/components/schemas/HomeVelocity"},"digest":{"type":"array","items":{"$ref":"#/components/schemas/HomeDigestActor"},"description":"Actor-aggregated activity, visibility-gated per viewer, most-recent first."}},"required":["velocity","digest"]},"ChangelogEntry":{"type":"object","properties":{"id":{"type":"string","description":"Stable slug for the entry (e.g. `2026-04-15-google-sso`)."},"published_at":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO 8601 date (no time) the entry was published."},"version":{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$","description":"Semver version this entry corresponds to. Bumped when any breaking change lands."},"title":{"type":"string","description":"Short headline for the entry."},"summary":{"type":"string","description":"Body of the entry — what changed, why, and any caveats agents need to know."},"breaking":{"type":"boolean","description":"True if the change removes/renames a path/field, can silently 200 with wrong data, or shifts auth/permissions."},"decision_id":{"type":["string","null"],"description":"Matching row in `agents/DECISIONS.md` (e.g. `D107`). Null if no formal decision was recorded."},"migration":{"type":["string","null"],"description":"Short migration note describing what callers must do. Null if no action required. Always present when `breaking` is true."},"areas":{"type":"array","items":{"type":"string"},"minItems":1,"description":"Module tags the entry applies to (e.g. `Identity`, `Mail`)."}},"required":["id","published_at","version","title","summary","breaking","decision_id","migration","areas"]},"ChangelogResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChangelogEntry"},"description":"Changelog entries, ordered newest-first by `published_at`."},"total":{"type":"integer","minimum":0,"description":"Total entry count."},"has_more":{"type":"boolean","enum":[false],"description":"Pagination flag — always false because the changelog is a static list, not a paginated query."},"breaking_count":{"type":"integer","minimum":0,"description":"Number of entries with `breaking: true`."}},"required":["data","total","has_more","breaking_count"]},"FeedbackResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Always `true` on the 200 path — the route returns 200 even when the downstream webhook fails so the UX surfaces a receipt id and the GCS screenshot fallback runs."},"feedback_id":{"type":"string","format":"uuid","description":"UUID receipt — surfaced to the user as a copyable id and used by triage to correlate the report across systems."}},"required":["success","feedback_id"]},"FeedbackErrorResponse":{"type":"object","properties":{"error":{"type":"string","description":"Stable string code. `Invalid input` for body-shape failures, `Invalid request body` for non-JSON, `Feedback reporting not available` when the webhook isn't configured (503 — surfaced via `c.json` escape hatch since 503 is outside the contract `ErrorCode` enum)."},"details":{"type":"array","items":{},"description":"Zod issue array on validation failures — for diagnostic UIs that want field-level error rendering."},"feedback_id":{"type":"string","format":"uuid","description":"Receipt id is included on the 400 paths too so an aborted submission still has a triage handle."}},"required":["error"]},"FeedbackBodyInput":{"type":"object","properties":{"description":{"type":"string"},"priority":{"type":"string"},"screenshotDataUrl":{"type":"string"},"attachments":{"type":"array","items":{"type":"object","additionalProperties":{}}},"context":{"type":"object","additionalProperties":{}}},"additionalProperties":false},"ProtectedResourceMetadata":{"type":"object","properties":{"resource":{"type":"string","format":"uri","description":"URL of the protected resource — `${API_URL}/mcp`."},"authorization_servers":{"type":"array","items":{"type":"string","format":"uri"},"description":"Authorization server URLs that issue tokens for this resource. The server itself is the only entry."},"scopes_supported":{"type":"array","items":{"type":"string"}},"bearer_methods_supported":{"type":"array","items":{"type":"string","enum":["header"]},"description":"Where the bearer token is accepted — only `header` (Authorization)."}},"required":["resource","authorization_servers","scopes_supported","bearer_methods_supported"]},"AuthorizationServerMetadata":{"type":"object","properties":{"issuer":{"type":"string","format":"uri"},"authorization_endpoint":{"type":"string","format":"uri"},"token_endpoint":{"type":"string","format":"uri"},"registration_endpoint":{"type":"string","format":"uri"},"revocation_endpoint":{"type":"string","format":"uri"},"response_types_supported":{"type":"array","items":{"type":"string","enum":["code"]}},"grant_types_supported":{"type":"array","items":{"type":"string","enum":["authorization_code"]}},"code_challenge_methods_supported":{"type":"array","items":{"type":"string","enum":["S256"]}},"token_endpoint_auth_methods_supported":{"type":"array","items":{"type":"string","enum":["none"]}},"scopes_supported":{"type":"array","items":{"type":"string"}},"service_documentation":{"type":"string","format":"uri"}},"required":["issuer","authorization_endpoint","token_endpoint","registration_endpoint","revocation_endpoint","response_types_supported","grant_types_supported","code_challenge_methods_supported","token_endpoint_auth_methods_supported","scopes_supported","service_documentation"]},"RegisterClientResponse":{"type":"object","properties":{"client_id":{"type":"string","description":"Newly issued client identifier."},"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string","format":"uri"}},"token_endpoint_auth_method":{"type":"string","enum":["none"]},"grant_types":{"type":"array","items":{"type":"string","enum":["authorization_code"]}},"response_types":{"type":"array","items":{"type":"string","enum":["code"]}}},"required":["client_id","client_name","redirect_uris","token_endpoint_auth_method","grant_types","response_types"]},"OAuthTokenResponse":{"type":"object","properties":{"access_token":{"type":"string","description":"Long-lived API key (`ak_*`) — use as a Bearer token."},"token_type":{"type":"string","enum":["Bearer"]}},"required":["access_token","token_type"]},"OAuthTokenError":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error"]},"OAuthRevokeResponse":{"type":"object","properties":{}},"Coworker":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"coworker_service_id":{"type":"string"},"status":{"$ref":"#/components/schemas/CoworkerStatus"},"display_name":{"type":"string"},"email":{"type":"string"},"workspace_email":{"type":["string","null"]},"avatar_url":{"type":["string","null"]},"persona":{"type":["string","null"]},"focus_areas":{"type":"array","items":{"type":"string"}},"enabled_skills":{"type":["array","null"],"items":{"$ref":"#/components/schemas/CoworkerSkill"},"description":"Skills this coworker is scoped to. Null = full workspace skill set."},"last_active_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"manager_user_id":{"type":["string","null"],"format":"uuid"},"manager_display_name":{"type":["string","null"]}},"required":["id","user_id","coworker_service_id","status","display_name","email","workspace_email","avatar_url","persona","last_active_at","created_at","manager_user_id","manager_display_name"]},"CoworkerStatus":{"type":"string","enum":["ACTIVE","PAUSED","ERROR"]},"CoworkerSkill":{"type":"string","enum":["calendar","chat","documents","drive","mail","sheets","tasks"]},"CoworkerSuccess":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/Coworker"},"api_key":{"type":"string"}},"required":["success"]},"CoworkerListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Coworker"}}},"required":["success","data"]},"CoworkerRunningExecution":{"type":"object","properties":{"coworker_id":{"type":"string","format":"uuid"},"task_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string"},"started_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"conversation_id":{"type":["string","null"],"format":"uuid"},"surface":{"type":["string","null"]},"thread_ref":{"type":["string","null"]},"conversation_status":{"type":["string","null"]},"fanout_depth":{"type":"integer"}},"required":["coworker_id","task_id","title","status","started_at","created_at","conversation_id","surface","thread_ref","conversation_status","fanout_depth"]},"CoworkerRunningExecutionsResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/CoworkerRunningExecution"}}},"required":["success","data"]},"CoworkerExecutionSurface":{"type":"string","enum":["chat","mention","mail","tasks","documents"]},"CoworkerDispatchResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"trigger_id":{"type":"string"}},"required":["success","trigger_id"]},"CoworkerProxyResponse":{"type":"object","properties":{"success":{"type":"boolean"},"status":{"type":"integer"},"data":{},"error":{"type":"string"}},"required":["success"],"additionalProperties":{}},"CoworkerPlaybookSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"coworker_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"objective":{"type":["string","null"]},"trigger_types":{"type":"array","items":{"type":"string"},"default":[]},"current_version_id":{"type":["string","null"],"format":"uuid"},"current_version":{"type":["integer","null"],"exclusiveMinimum":0},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]}},"required":["id","coworker_id","title","objective","current_version_id","current_version","created_at","updated_at"]},"CoworkerPlaybookListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/CoworkerPlaybookSummary"}}},"required":["success","data"]},"CoworkerPlaybookDetail":{"allOf":[{"$ref":"#/components/schemas/CoworkerPlaybookSummary"},{"type":"object","properties":{"current_version_detail":{"anyOf":[{"$ref":"#/components/schemas/CoworkerPlaybookVersion"},{"type":"null"}]}},"required":["current_version_detail"]}]},"CoworkerPlaybookVersion":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"playbook_id":{"type":"string","format":"uuid"},"version":{"type":"integer","exclusiveMinimum":0},"instructions":{"type":["string","null"]},"subtasks":{},"change_reason":{"type":["string","null"]},"created_at":{"type":["string","null"]}},"required":["id","playbook_id","version","instructions","change_reason","created_at"]},"CoworkerPlaybookResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/CoworkerPlaybookDetail"}},"required":["success","data"]},"CoworkerPlaybookVersionsListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/CoworkerPlaybookVersion"}}},"required":["success","data"]},"CoworkerPlaybookVersionResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/CoworkerPlaybookVersion"}},"required":["success","data"]},"AgentSubscriptions":{"type":"object","properties":{"mentions":{"type":"boolean","description":"Hear @mentions of this agent."},"dms":{"type":"boolean","description":"Hear direct messages sent to this agent."},"tasks_assigned":{"type":"boolean","description":"Hear tasks assigned to this agent."},"docs_shared":{"type":"boolean","description":"Hear docs/wiki shared with this agent."},"emails":{"type":"boolean","description":"Hear emails delivered to this agent's mailbox."},"watched_channel_ids":{"type":"array","items":{"type":"string"},"description":"Channel ids whose messages this agent hears (must be a member)."},"keywords":{"type":"array","items":{"type":"string"},"description":"Keywords that, when matched in an accessible message, this agent hears."}},"required":["mentions","dms","tasks_assigned","docs_shared","emails","watched_channel_ids","keywords"]},"AgentTransportStatus":{"type":"object","properties":{"connected":{"type":"boolean","description":"A live agent connection is currently registered for this agent."}},"required":["connected"]},"AgentApiKeyWithSecret":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"raw_key":{"type":"string","description":"The plaintext key. Returned once — the server sends Cache-Control: no-store."}},"required":["id","name","raw_key"]},"AgentManagerUpdated":{"type":"object","properties":{"manager_user_id":{"type":["string","null"],"format":"uuid"}},"required":["manager_user_id"]},"NotificationEventRow":{"type":"object","properties":{"id":{"type":"string"},"group":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"sinks":{"type":"array","items":{"type":"string"}},"values":{"$ref":"#/components/schemas/NotificationSinkValues"}},"required":["id","group","label","description","sinks","values"]},"NotificationSinkValues":{"type":"object","properties":{"live":{"type":"boolean"},"email":{"type":"boolean"},"browser_push":{"type":"boolean"},"coworker_dispatch":{"type":"boolean"}}},"NotificationSettingsResponse":{"type":"object","properties":{"identity":{"type":"string"},"sinks":{"type":"array","items":{"type":"string"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/NotificationEventRow"}},"sound":{"type":"boolean"},"keywords":{"type":"array","items":{"type":"string"}},"watched_channel_ids":{"type":"array","items":{"type":"string"}}},"required":["identity","sinks","events","sound","keywords","watched_channel_ids"]},"NotificationSettingsPatchInput":{"type":"object","properties":{"events":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"boolean"}},"description":"event-id → sink → enabled. Dynamic keys."},"sound":{"type":"boolean"},"keywords":{"type":"array","items":{"type":"string"}},"watched_channel_ids":{"type":"array","items":{"type":"string"}}},"additionalProperties":false},"Team":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"email_local_part":{"type":["string","null"]},"email_address":{"type":["string","null"]},"email_domain_id":{"type":["string","null"],"format":"uuid"},"available_email_domains":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"is_default":{"type":"boolean"}},"required":["id","domain","is_default"]}},"parent_team_id":{"type":["string","null"],"format":"uuid"},"parent_team_name":{"type":["string","null"]},"default_channels":{"type":"array","items":{"type":"string"}},"visibility":{"$ref":"#/components/schemas/TeamVisibility"},"join_policy":{"$ref":"#/components/schemas/TeamJoinPolicy"},"posting_policy":{"$ref":"#/components/schemas/TeamPostingPolicy"},"member_count":{"type":"integer"},"icon":{"type":["string","null"]},"color":{"type":["string","null"]},"created_by":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"last_active_at":{"type":["string","null"]},"is_starred":{"type":"boolean"},"is_member":{"type":"boolean"},"role":{"anyOf":[{"$ref":"#/components/schemas/TeamMemberRole"},{"type":"null"}]},"pending_request":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"created_at":{"type":["string","null"]}},"required":["id","created_at"]},"members":{"type":"array","items":{"$ref":"#/components/schemas/TeamMember"}}},"required":["id","name","slug","description","email_local_part","email_address","parent_team_id","parent_team_name","visibility","join_policy","posting_policy","member_count","icon","color","created_by","created_at","updated_at"]},"TeamVisibility":{"type":"string","enum":["public","private"],"description":"`public` = listed and joinable. `private` = members + admins only."},"TeamJoinPolicy":{"type":"string","enum":["open","request","invite"],"description":"How non-members can join. `open` = self-serve. `request` = request-to-join (creates a `TeamJoinRequest`). `invite` = invite required."},"TeamPostingPolicy":{"type":"string","enum":["open","members_only","admins_only"],"description":"Who may post to the team's email address. `open` = any sender. `members_only` = workspace members. `admins_only` = team admins."},"TeamMemberRole":{"type":"string","enum":["admin","member"],"description":"Role within one team. Workspace role is separate."},"TeamMember":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"email":{"type":["string","null"]},"role":{"$ref":"#/components/schemas/TeamMemberRole"},"added_at":{"type":["string","null"]}},"required":["user_id","display_name","email","role","added_at"]},"TeamListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Team"}}},"required":["data"]},"SearchableTeam":{"allOf":[{"$ref":"#/components/schemas/Team"},{"type":"object","properties":{"role":{"type":["string","null"],"enum":["admin","member",null]}},"required":["is_member","role"]}]},"SearchableTeamListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SearchableTeam"}}},"required":["data"]},"TeamMembersListResponse":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/TeamMember"}},"total":{"type":"integer","minimum":0}},"required":["members","total"]},"TeamMemberDetailResponse":{"type":"object","properties":{"team_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"email":{"type":["string","null"]},"role":{"$ref":"#/components/schemas/TeamMemberRole"},"added_at":{"type":["string","null"]}},"required":["team_id","user_id","display_name","email","role","added_at"]},"TeamSubscriptionStateResponse":{"type":"object","properties":{"team_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"email_delivery":{"type":"string","enum":["each","daily_digest","weekly_digest","none"]}},"required":["team_id","user_id","email_delivery"]},"TeamJoinResponse":{"type":"object","properties":{"status":{"type":"string","enum":["joined","pending"]},"team_id":{"type":"string","format":"uuid"},"team_name":{"type":"string"},"user_id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"email":{"type":["string","null"]},"role":{"$ref":"#/components/schemas/TeamMemberRole"},"request_id":{"type":"string","format":"uuid"},"requested_at":{"type":["string","null"]}},"required":["status","team_id","team_name","user_id"]},"TeamStarStateResponse":{"type":"object","properties":{"team_id":{"type":"string","format":"uuid"},"starred":{"type":"boolean"}},"required":["team_id","starred"]},"TeamJoinRequest":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"email":{"type":["string","null"]},"message":{"type":["string","null"]},"requested_at":{"type":["string","null"]}},"required":["id","user_id","display_name","email","message","requested_at"]},"TeamJoinRequestsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamJoinRequest"}}},"required":["data"]},"KFactorCohortMetrics":{"type":"object","properties":{"cohort":{"type":"string"},"cohort_size":{"type":"integer","minimum":0},"k1":{"type":"number"},"k2":{"type":"number"},"k3":{"type":"number"},"ktotal":{"type":"number"},"conversion_by_generation":{"type":"object","additionalProperties":{"type":"number"}},"computed_at":{"type":"string"}},"required":["cohort","cohort_size","k1","k2","k3","ktotal","conversion_by_generation","computed_at"]},"ModuleAvailabilityResponse":{"type":"object","properties":{"modules":{"type":"object","additionalProperties":{"type":"boolean"}}},"required":["modules"]},"AssessmentGridRun":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"startedAt":{"type":["string","null"]},"label":{"type":["string","null"]},"environment":{"type":["string","null"]},"agentKind":{"type":["string","null"]},"resultCount":{"type":"integer"},"caseCount":{"type":["integer","null"]}},"required":["id","startedAt","label","environment","agentKind","resultCount","caseCount"]},"AssessmentGridRunAggregate":{"type":"object","properties":{"passed":{"type":"integer"},"total":{"type":"integer"}},"required":["passed","total"]},"AssessmentGridNode":{"type":"object","properties":{"depth":{"type":"string","enum":["skillTree","level","branch","skill","test"]},"name":{"type":"string"},"caseCount":{"type":"integer"},"runs":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/AssessmentGridRunAggregate"}},"children":{"type":"array","items":{"$ref":"#/components/schemas/AssessmentGridNode"}},"caseId":{"type":"string","format":"uuid"},"results":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/AssessmentGridLeafResult"}}},"required":["depth","name","caseCount","runs"]},"AssessmentGridLeafResult":{"type":"object","properties":{"resultId":{"type":"string","format":"uuid"},"passed":{"type":"boolean"}},"required":["resultId","passed"]},"AssessmentGrid":{"type":"object","properties":{"runs":{"type":"array","items":{"$ref":"#/components/schemas/AssessmentGridRun"}},"tree":{"type":"object","properties":{"caseCount":{"type":"integer"},"runs":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/AssessmentGridRunAggregate"}},"trees":{"type":"array","items":{"$ref":"#/components/schemas/AssessmentGridNode"}}},"required":["caseCount","runs","trees"]}},"required":["runs","tree"]},"AssessmentTriggeringMessage":{"type":"object","properties":{"actorRef":{"type":"string"},"actorType":{"type":"string"},"name":{"type":"string"},"content":{"type":"string"},"subject":{"type":"string"},"to":{"type":"array","items":{"type":"string"}},"cc":{"type":"array","items":{"type":"string"}},"bcc":{"type":"array","items":{"type":"string"}}},"required":["content"]},"AssessmentResultDetail":{"type":"object","properties":{"result":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"runId":{"type":"string","format":"uuid"},"passed":{"type":"boolean"},"errored":{"type":"boolean"},"error":{"type":["string","null"]},"score":{"type":"number"},"judgeEvaluation":{"type":["string","null"]},"executionResult":{"type":["object","null"],"additionalProperties":{}},"environment":{"type":["string","null"]},"commitHash":{"type":["string","null"]},"executionTimeMs":{"type":["integer","null"]},"agentKind":{"type":"string"},"evalWorkspaceId":{"type":["string","null"],"format":"uuid"},"coworkerExecutionId":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":["string","null"]}},"required":["id","runId","passed","errored","error","score","judgeEvaluation","executionResult","environment","commitHash","executionTimeMs","agentKind","evalWorkspaceId","coworkerExecutionId","createdAt"]},"run":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["string","null"]},"startedAt":{"type":["string","null"]}},"required":["id","label","startedAt"]},"case":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"skillTree":{"type":"string"},"level":{"type":"integer"},"branch":{"type":["string","null"]},"skill":{"type":"string"},"testName":{"type":"string"},"status":{"type":"string","enum":["DRAFT","PUBLISHED","ARCHIVED"]},"currentVersionId":{"type":["string","null"],"format":"uuid"}},"required":["id","skillTree","level","branch","skill","testName","status","currentVersionId"]},"version":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"integer"},"triggeringMessage":{"$ref":"#/components/schemas/AssessmentTriggeringMessage"},"criteria":{"type":"string"},"fixtures":{"type":["object","null"],"additionalProperties":{}},"createdAt":{"type":["string","null"]}},"required":["id","version","triggeringMessage","criteria","fixtures","createdAt"]}},"required":["result","run","case","version"]},"AssessmentResultSibling":{"type":"object","properties":{"resultId":{"type":"string","format":"uuid"},"runId":{"type":"string","format":"uuid"},"runLabel":{"type":["string","null"]},"runStartedAt":{"type":["string","null"]},"environment":{"type":["string","null"]},"passed":{"type":"boolean"},"errored":{"type":"boolean"},"score":{"type":"number"},"createdAt":{"type":["string","null"]}},"required":["resultId","runId","runLabel","runStartedAt","environment","passed","errored","score","createdAt"]},"AssessmentResultSiblings":{"type":"object","properties":{"caseId":{"type":"string","format":"uuid"},"siblings":{"type":"array","items":{"$ref":"#/components/schemas/AssessmentResultSibling"}}},"required":["caseId","siblings"]},"AssessmentCasePatchResult":{"type":"object","properties":{"case":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"skillTree":{"type":"string"},"level":{"type":"integer"},"branch":{"type":["string","null"]},"skill":{"type":"string"},"testName":{"type":"string"},"status":{"type":"string","enum":["DRAFT","PUBLISHED","ARCHIVED"]},"currentVersionId":{"type":["string","null"],"format":"uuid"}},"required":["id","skillTree","level","branch","skill","testName","status","currentVersionId"]},"version":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"integer"},"triggeringMessage":{"$ref":"#/components/schemas/AssessmentTriggeringMessage"},"criteria":{"type":"string"},"fixtures":{"type":["object","null"],"additionalProperties":{}},"createdAt":{"type":["string","null"]}},"required":["id","version","triggeringMessage","criteria","fixtures","createdAt"]}},"required":["case","version"]},"AssessmentCasePatch":{"type":"object","properties":{"testName":{"type":"string","minLength":1},"branch":{"type":["string","null"]},"status":{"type":"string","enum":["DRAFT","PUBLISHED","ARCHIVED"]},"triggeringMessage":{"type":"object","properties":{"actorRef":{"type":"string"},"actorType":{"type":"string"},"name":{"type":"string"},"content":{"type":"string"},"subject":{"type":"string"},"to":{"type":"array","items":{"type":"string"}},"cc":{"type":"array","items":{"type":"string"}},"bcc":{"type":"array","items":{"type":"string"}}},"required":["content"],"additionalProperties":false},"criteria":{"type":"string","minLength":1},"fixtures":{"type":["object","null"],"additionalProperties":{}}},"additionalProperties":false},"AnalyticsExportBody":{"type":"string"},"AnalyticsDashboardShareTile":{"type":"object","properties":{"tile":{"type":"object","additionalProperties":{}},"report":{"type":"object","additionalProperties":{}},"result":{"type":"object","additionalProperties":{}},"error":{"type":"string","description":"invalid_report_reference | report_not_found | invalid_report_spec — set instead of `result` when the tile could not be executed."}},"required":["tile"]},"AnalyticsDashboardShareStatus":{"type":"object","properties":{"dashboard":{"type":"object","additionalProperties":{}},"read_only":{"type":"boolean"},"tiles":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsDashboardShareTile"}}},"required":["dashboard","read_only","tiles"]},"AnalyticsUsersResponse":{"type":"object","properties":{"users":{"type":"array","items":{"type":"object","additionalProperties":{}}},"data":{"type":"array","items":{"type":"object","additionalProperties":{}}},"total":{"type":"integer"},"has_more":{"type":"boolean"},"limit":{"type":"integer"},"offset":{"type":"integer"},"source":{"type":"string","enum":["direct","materialized_view"],"description":"Which read served this page. Set by `analytics_users_list` only."},"error":{"type":"string","enum":["materialized_view_not_ready"],"description":"Set by `analytics_users_aggregates` when the materialized view is missing or unpopulated; the page is empty rather than an error status."}},"required":["users","data","total","has_more","limit","offset"]},"AnalyticsTimelineSession":{"type":"object","properties":{"session_id":{"type":"integer"},"started_at":{"type":"string"},"ended_at":{"type":"string"},"event_count":{"type":"integer"}},"required":["session_id","started_at","ended_at","event_count"]},"AnalyticsUserTimelineResponse":{"type":"object","properties":{"user":{"type":["object","null"],"additionalProperties":{}},"identity_chain":{"type":"array","items":{"type":"string"}},"identity_chain_truncated":{"type":"boolean"},"flagged_for_triage":{"type":"boolean"},"events":{"type":"array","items":{"type":"object","additionalProperties":{}}},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsTimelineSession"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["user","identity_chain","identity_chain_truncated","flagged_for_triage","events","sessions","total","limit","offset"]},"AnalyticsDeletionHistoryResponse":{"type":"object","properties":{"deletions":{"type":"array","items":{"type":"object","additionalProperties":{}}},"data":{"type":"array","items":{"type":"object","additionalProperties":{}}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["deletions","data","total","limit","offset"]},"ZoomStatusResponse":{"type":"object","properties":{"enabled":{"type":"boolean"},"connected":{"type":"boolean"},"zoom_email":{"type":["string","null"]}},"required":["enabled","connected","zoom_email"]},"ZoomAuthUrlResponse":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"ZoomDisconnectResponse":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"ZoomMeetingResponse":{"type":"object","properties":{"join_url":{"type":"string"},"meeting_id":{"type":"string"},"topic":{"type":["string","null"]},"password":{"type":["string","null"]}},"required":["join_url","meeting_id","topic","password"]},"ZoomMeetingCreateBody":{"type":"object","properties":{"topic":{"type":"string","maxLength":200}}},"OnboardingAgent":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"`users.id` of the provisioned agent."},"username":{"type":"string","description":"The agent's workspace email local-part, derived from the name."},"display_name":{"type":"string","description":"The agent's display name, normalized."},"workspace_email":{"type":"string","description":"The agent's inbound address inside this workspace's domain."}},"required":["id","username","display_name","workspace_email"]},"OnboardingAgentResponse":{"type":"object","properties":{"agent":{"$ref":"#/components/schemas/OnboardingAgent"},"api_key":{"type":"string","description":"The agent's API key (`ak_…`). **Returned exactly once, here** — never retrievable again; rotate the key to get a new one."},"harness":{"type":["string","null"],"description":"Echo of the harness the journey carried, so the completion screen can open the right connect instructions without a second read."}},"required":["agent","api_key","harness"]},"IdentityApiKeysListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdminApiKey"}}},"required":["data"]},"IdentityApiKeyWithSecretResponse":{"type":"object","properties":{"key":{"$ref":"#/components/schemas/AdminApiKey"},"raw_key":{"type":"string","description":"Plaintext API key. Only returned at create and rotate time."}},"required":["key","raw_key"]},"IdentityApiKeyResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"user_name":{"type":["string","null"]},"user_email":{"type":["string","null"]},"name":{"type":"string"},"scopes":{},"rate_limit":{"type":"integer"},"last_used_at":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"key_prefix":{"type":["string","null"]},"last_rotated_at":{"type":["string","null"]},"old_key_expires_at":{"type":["string","null"]}},"required":["id","user_id","user_name","user_email","name","rate_limit","last_used_at","expires_at","created_at","key_prefix"]},"AutomationsStatsResponse":{"type":"object","properties":{"range_days":{"type":"integer"},"total_runs":{"type":"integer"},"success_runs":{"type":"integer"},"failed_runs":{"type":"integer"},"status_breakdown":{"type":"object","additionalProperties":{"type":"integer"}},"failures_by_workflow":{"type":"array","items":{"type":"object","properties":{"automation_id":{"type":"string"},"name":{"type":"string"},"failure_count":{"type":"integer"},"error_types":{"type":"array","items":{"type":"string"}}},"required":["automation_id","name","failure_count","error_types"]}},"runs_per_day":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"count":{"type":"integer"}},"required":["date","count"]}},"heatmap":{"type":"array","items":{"type":"object","properties":{"hour":{"type":"integer"},"dow":{"type":"integer"},"count":{"type":"integer"}},"required":["hour","dow","count"]}},"quota":{"type":"object","properties":{"active_workflows":{"type":"integer"},"max_active_workflows":{"type":"integer"},"runs_last_hour":{"type":"integer"},"max_runs_per_hour":{"type":"integer"}},"required":["active_workflows","max_active_workflows","runs_last_hour","max_runs_per_hour"]}},"required":["range_days","total_runs","success_runs","failed_runs","status_breakdown","failures_by_workflow","runs_per_day","heatmap","quota"]},"AutomationRunStatus":{"type":"string","enum":["success","filtered","failed","suspended","cancelled","depth_exceeded"],"description":"Terminal status when the dispatch returns. `suspended` means a delay or until-event node parked the run; the scheduler will resume it asynchronously and the final status will appear on `GET /api/automations/runs/:runId` (Rock 5 item 28)."},"AutomationRunResponse":{"type":"object","properties":{"run_id":{"type":"string","format":"uuid","description":"`workflow_runs.id` of the dispatched run."},"status":{"$ref":"#/components/schemas/AutomationRunStatus"}},"required":["run_id","status"]},"AutomationVisibility":{"type":"string","enum":["private","workspace","public_link"],"description":"Workflow visibility. `private` (default): only the owner + `shared_with` viewers can see it. `workspace`: every member of the workspace can read it (edit still gated by `shared_with`). `public_link` is reserved for future read-only sharing — the engine treats it as `workspace` for v1."},"AutomationShareEntry":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"role":{"type":"string","enum":["viewer","editor"]}},"required":["userId","role"]},"AutomationWorkflow":{"type":"object","properties":{"nodes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Node id, unique within the workflow."},"name":{"type":"string","description":"Human-readable node name; doubles as the JSONLogic var prefix."},"type":{"type":"string","description":"Node primitive (`manualTrigger`, `webhook`, `filter`, `branch`, `delay`, `loop`, `code`, …) or registry-action type (`task.create`, `email.send`, …)."},"position":{"type":"array","items":{"type":"number"},"description":"Canvas position [x, y]. Optional; defaults to [0, 0]."},"parameters":{"type":"object","additionalProperties":{},"default":{},"description":"Per-node configuration. Shape is node-type-specific."}},"required":["id","name","type"],"additionalProperties":{}},"description":"List of DAG nodes."},"connections":{"type":"object","additionalProperties":{},"description":"Adjacency map keyed by node `name` (n8n convention). Values describe outgoing edges per port."}},"required":["nodes","connections"],"additionalProperties":{},"description":"Workflow JSONB. n8n-shaped: `nodes` array + `connections` adjacency keyed by node name. Inner shape is enforced by the dispatcher, not at the API layer."},"AutomationNodeTypeWarning":{"type":"object","properties":{"node_id":{"type":"string","description":"Id of the unrecognized workflow node."},"node_name":{"type":"string","description":"Human-readable name of the unrecognized workflow node."},"type":{"type":"string","description":"Unrecognized node type preserved on the workflow."},"did_you_mean":{"type":"array","items":{"type":"string"},"description":"Likely registered operationIds or n8n alias keys, nearest first."}},"required":["node_id","node_name","type"]},"AutomationSaveResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"owner_id":{"type":"string","format":"uuid"},"owner_display_name":{"type":["string","null"]},"name":{"type":"string"},"description":{"type":["string","null"]},"active":{"type":"boolean"},"visibility":{"$ref":"#/components/schemas/AutomationVisibility"},"shared_with":{"type":"array","items":{"$ref":"#/components/schemas/AutomationShareEntry"}},"workflow":{"$ref":"#/components/schemas/AutomationWorkflow"},"workflow_version":{"type":"integer","exclusiveMinimum":0},"tags":{"type":"array","items":{"type":"string"}},"created_at":{"type":"string"},"updated_at":{"type":"string"},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/AutomationNodeTypeWarning"},"description":"Advisory warnings for unrecognized node types. Omitted when none are found."}},"required":["id","workspace_id","owner_id","owner_display_name","name","description","active","visibility","shared_with","workflow","workflow_version","tags","created_at","updated_at"],"description":"A saved workflow with optional advisory node-type warnings."},"AutomationCreateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"Human-readable workflow name. Required."},"description":{"type":"string","maxLength":2000,"description":"Optional long-form description; surfaced in the UI catalog."},"workflow":{"allOf":[{"$ref":"#/components/schemas/AutomationWorkflow"},{"description":"Initial workflow JSONB. `workflow_version` starts at 1; subsequent PATCHes write `automation_workflow_versions` rows + bump the version."}]},"active":{"type":"boolean","description":"Whether the workflow is enabled to fire on triggers. Defaults to `false` (draft) on create — call POST `/:id/enable` to activate (item 26)."},"visibility":{"allOf":[{"$ref":"#/components/schemas/AutomationVisibility"},{"description":"Defaults to `private`."}]},"shared_with":{"type":"array","items":{"$ref":"#/components/schemas/AutomationShareEntry"},"description":"Per-user share grants. Defaults to `[]`."},"tags":{"type":"array","items":{"type":"string"},"description":"Free-form tag strings; usable as a list-filter (`?tag=foo`)."}},"required":["name","workflow"]},"Automation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"owner_id":{"type":"string","format":"uuid"},"owner_display_name":{"type":["string","null"]},"name":{"type":"string"},"description":{"type":["string","null"]},"active":{"type":"boolean"},"visibility":{"$ref":"#/components/schemas/AutomationVisibility"},"shared_with":{"type":"array","items":{"$ref":"#/components/schemas/AutomationShareEntry"}},"workflow":{"$ref":"#/components/schemas/AutomationWorkflow"},"workflow_version":{"type":"integer","exclusiveMinimum":0},"tags":{"type":"array","items":{"type":"string"}},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","workspace_id","owner_id","owner_display_name","name","description","active","visibility","shared_with","workflow","workflow_version","tags","created_at","updated_at"],"description":"A workflow row. `workflow_version` is the live cursor; immutable snapshots live in `automation_workflow_versions`. Returned by every CRUD route."},"AutomationListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Automation"}},"total":{"type":"integer","minimum":0,"description":"Count of rows in this page."},"has_more":{"type":"boolean","description":"True if a subsequent page exists. Set when the underlying query returned `limit + 1` hint rows."}},"required":["data","total","has_more"]},"NodeTypeSummary":{"type":"object","properties":{"type":{"type":"string","description":"Stable identifier used in `workflow.nodes[].type`. Primitives are hand-coded names (`webhook`, `filter`, `delay`); actions are the underlying route's `operationId` verbatim (e.g., `create_task`, `crm_deal_stage_move`, `automations_invoke`)."},"label":{"type":"string","description":"Human-readable label rendered in the UI palette. Display only — never used as identity. For primitives this is hand-coded; for actions it's derived mechanically from the operationId + tag via `formatActionLabel()` (e.g., `tasks_create` + `Tasks` → 'Create task')."},"category":{"$ref":"#/components/schemas/NodeTypeCategory"},"module":{"type":"string","description":"Group key used for the palette tree. For primitives, equals the literal type string (`webhook`, `filter`, etc.). For actions, the lowercased OpenAPI tag (e.g., `tasks` for routes tagged `Tasks`)."},"description":{"type":"string","description":"One-line description of what the node does. Primitives are documented inline; action descriptions come from the route's OpenAPI `description` field, truncated at 200 chars."},"deferred":{"type":"boolean","description":"True when the node is registered but not yet implemented — the engine recognizes the type but emits `{status: 'failed', error: '<type> deferred to v1.1'}`. Set on no node type at HEAD (the `code` primitive now executes in the WASM isolate)."},"n8n_aliases":{"type":"array","items":{"type":"string"},"description":"Inbound n8n-nodes-base type strings that route to this node-type via the alias table (Pat4). Surfaced by the catalog so the UI palette can label imported workflows. Populated by Rock 7 item 36 once the alias table is loaded; absent until then."}},"required":["type","label","category","module","description"]},"NodeTypeCategory":{"type":"string","enum":["trigger","control","action"],"description":"`trigger` is one of the five trigger primitives (webhook / scheduleTrigger / manualTrigger / event / email); `control` is one of the five DAG-control primitives (filter / branch / delay / loop / code); `action` is a registry-derived node that wraps an HTTP route with `x-tool.expose: ['automations']`."},"NodeTypeListResponse":{"type":"object","properties":{"primitives":{"type":"array","items":{"$ref":"#/components/schemas/NodeTypeSummary"},"description":"The ten hand-coded primitives, ordered triggers first (webhook, scheduleTrigger, manualTrigger, event, email) then DAG control (filter, branch, delay, loop, code)."},"actions":{"type":"array","items":{"$ref":"#/components/schemas/NodeTypeSummary"},"description":"Registry-derived actions, sorted by `type`. Empty until at least one route is registered with `x-tool.expose: ['automations']`. Adding a new action route makes the action appear here on next server boot — no automations-module code changes needed (Pat2)."}},"required":["primitives","actions"],"description":"Unified node-type catalog. UI palette reads this live to render the node-picker tree. Per Pat2 the palette groups action entries by their `module` field (lowercased OpenAPI tag)."},"NodeOutput":{"type":"object","properties":{"id":{"type":"string","description":"Stable handle id used by edges as the `sourceHandle`."},"label":{"type":"string","description":"Human-readable label rendered next to the port in the canvas."}},"required":["id","label"],"description":"One declared output port on a node type. Multi-output primitives (currently only `branch`) ship at least the `default` fallthrough port; runtime fan-out beyond the static list is signalled by `outputs_from_parameters`."},"NodeTypeDetail":{"type":"object","properties":{"type":{"type":"string"},"label":{"type":"string"},"category":{"$ref":"#/components/schemas/NodeTypeCategory"},"module":{"type":"string"},"description":{"type":"string"},"deferred":{"type":"boolean"},"n8n_aliases":{"type":"array","items":{"type":"string"}},"operation_id":{"type":["string","null"],"description":"For actions, equals `type` — the route's operationId is the identity (e.g., `create_task`). NULL for primitives — they aren't backed by a registered route. Kept as a separate field so primitive-vs-action discrimination is one-shot (`operation_id === null` ⇒ primitive)."},"http_method":{"type":["string","null"],"description":"HTTP method of the underlying route for actions. NULL for primitives."},"http_path":{"type":["string","null"],"description":"Path template of the underlying route for actions, e.g., `/api/tasks` or `/api/automations/{id}/run`. NULL for primitives."},"input_schema":{"type":["object","null"],"additionalProperties":{},"description":"JSON Schema (draft-07-ish, converted from zod) describing valid `node.parameters` shape for this type. For actions, this is the route's request body schema. For primitives, this is the hand-coded parameter shape (e.g., the filter's `{predicate: <JSONLogic>}` or the delay's `{wakeAt | duration_ms}`). NULL when no schema is available — the dispatcher will accept any parameters but the UI cannot render a typed form."},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/NodeOutput"},"description":"Static output ports a node-type declares at design time. Populated for primitives that fan out at runtime — currently `branch` ships `[{id:'default', label:'Default'}]` as the no-match fallthrough. Absent for single-output primitives and actions, where the implicit single `main` output is the contract."},"outputs_from_parameters":{"type":"object","properties":{"source":{"type":"string","enum":["cases"]}},"required":["source"],"description":"Runtime-derived output hint. When set, consumers expand outputs beyond the static `outputs` list by walking `node.parameters.<source>`. Today only `{ source: 'cases' }` is emitted, by `branch` — `parameters.cases[].then` names the per-case output ports."}},"required":["type","label","category","module","description","operation_id","http_method","http_path","input_schema"],"description":"Full record for a single node type, including the parameter input schema. Returned by `GET /api/automations/node-types/:type`."},"AutomationImportSummary":{"type":"object","properties":{"clean":{"type":"integer","minimum":0,"description":"Count of `={{ ... }}` parameter expressions that translated cleanly to JSONLogic (Tier A)."},"code_fallback":{"type":"integer","minimum":0,"description":"Count of expressions that fell back to a `code` node body (Tier B). The `code` primitive executes that body in the WASM isolate, so a Tier-B fallback runs rather than failing."},"unsupported":{"type":"integer","minimum":0,"description":"Count of expressions flagged as unsupported (Tier C — banned identifiers like `$workflow`, `process`, `require`, etc.). The user must rewrite these by hand before enabling."}},"required":["clean","code_fallback","unsupported"],"description":"Aggregate counts of expression-translation outcomes across the imported workflow."},"AutomationImportUnsupportedNode":{"type":"object","properties":{"nodeId":{"type":"string","description":"`node.id` from the imported n8n workflow."},"n8nType":{"type":"string","description":"Original `node.type` string from the imported file (e.g., `n8n-nodes-base.slack`)."},"suggestion":{"type":"string","description":"Curated user-facing suggestion for replacing the unsupported node. Falls through to a generic suggestion when no curated copy exists for the type."}},"required":["nodeId","n8nType","suggestion"]},"AutomationImportUnsupportedExpression":{"type":"object","properties":{"nodeId":{"type":"string","description":"`node.id` from the imported n8n workflow."},"parameter":{"type":"string","description":"Dotted path to the `parameters.*` field that contained the banned-identifier expression."},"originalJs":{"type":"string","description":"Verbatim original `={{ ... }}` expression body, preserved for the review pane."},"reason":{"type":"string","description":"Human-readable reason the expression was flagged unsupported (e.g., `banned identifier: $workflow`)."}},"required":["nodeId","parameter","originalJs","reason"]},"AutomationImportTierBPending":{"type":"object","properties":{"nodeId":{"type":"string","description":"`node.id` from the imported n8n workflow."},"parameter":{"type":"string","description":"Dotted path to the `parameters.*` field that contained the non-trivial JS expression."},"originalJs":{"type":"string","description":"Verbatim original `={{ ... }}` expression body. Will be wrapped in a `code` node body once the `code` primitive ships in v1.1."}},"required":["nodeId","parameter","originalJs"]},"AutomationImportResponse":{"type":"object","properties":{"automation_id":{"type":"string","format":"uuid","description":"`automations.id` of the freshly-inserted draft row (always created with `active=false`)."},"translation_summary":{"$ref":"#/components/schemas/AutomationImportSummary"},"unsupported_nodes":{"type":"array","items":{"$ref":"#/components/schemas/AutomationImportUnsupportedNode"},"description":"Nodes whose `type` resolved to the `unsupported` sentinel via `N8N_NODE_TYPE_ALIASES`. The dispatcher fails loudly when these are reached at runtime — operators see them in the review pane and replace before enabling."},"unsupported_expressions":{"type":"array","items":{"$ref":"#/components/schemas/AutomationImportUnsupportedExpression"},"description":"Tier-C expressions (banned identifiers) — must be rewritten by hand."},"tier_b_pending":{"type":"array","items":{"$ref":"#/components/schemas/AutomationImportTierBPending"},"description":"Tier-B expressions surfaced for review because they translated to a `code` node body rather than to JSONLogic. Stored verbatim on the workflow JSONB so they round-trip back to n8n via `automations_export?format=n8n`."}},"required":["automation_id","translation_summary","unsupported_nodes","unsupported_expressions","tier_b_pending"],"description":"Body of a successful `POST /api/automations/import?source=n8n` response. Carries the import-review pane data: which expressions translated cleanly, which fell back to `code`, which were flagged unsupported."},"AutomationImportInput":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"The n8n workflow JSON file to import (multipart `file` field)."}},"additionalProperties":false},"FormatterSetResponse":{"type":"object","properties":{"values":{"type":"object","additionalProperties":{},"description":"The resolved values, returned verbatim so downstream nodes can reference them via `{var: \"<NodeName>.values.<key>\"}` JSONLogic expressions."}},"required":["values"]},"AutomationHttpRequestResponse":{"type":"object","properties":{"status":{"type":"integer","minimum":100,"maximum":599},"headers":{"type":"object","additionalProperties":{"type":"string"}},"body":{}},"required":["status","headers"],"description":"Outbound response status, headers, and content-type-aware body for downstream nodes."},"AutomationTriggerSource":{"type":"string","enum":["manual","event","webhook","schedule","email","test"],"description":"Origin of a workflow run. `manual` is the operator-initiated run from /api/automations/:id/run. `event` / `webhook` / `schedule` / `email` are the four production trigger primitives. `test` is the dry-run path (Rock 5 item 27)."},"WorkflowRun":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"`workflow_runs.id`."},"automation_id":{"type":"string","format":"uuid","description":"Parent workflow id."},"workspace_id":{"type":"string","format":"uuid"},"status":{"allOf":[{"$ref":"#/components/schemas/AutomationRunStatus"},{"description":"Terminal status of an automation run. `success` is the happy path; `filtered` means a trigger or filter rejected the payload before any action ran; `failed` carries an error message; `suspended` is a delay/until_event mid-run park awaiting scheduler resume; `cancelled` is operator-initiated; `depth_exceeded` short-circuits when nested workflows exceed the spec P16 cap of 3."}]},"trigger_source":{"$ref":"#/components/schemas/AutomationTriggerSource"},"depth":{"type":"integer","minimum":0,"description":"`_automation_depth` envelope value at dispatch (spec P16)."},"workflow_version_at_dispatch":{"type":"integer","exclusiveMinimum":0,"description":"`automations.workflow_version` snapshot at dispatch time. Re-running a historic run uses this version's snapshot from `automation_workflow_versions` instead of the current `workflow`."},"step_outputs":{"type":"object","additionalProperties":{},"description":"Per-node outputs (truncated to 4 KB per node before persist)."},"trigger_payload":{"type":"object","additionalProperties":{},"description":"Dispatch payload (truncated to 64 KB)."},"error":{"type":["string","null"],"description":"Populated only on failed/depth_exceeded statuses."},"meta":{"type":"object","additionalProperties":{},"description":"Run-metadata envelope. v1 keys: `parentRunId` (set by retry), `cancelledBy` + `cancelledAt` (set by cancel)."},"started_at":{"type":"string"},"finished_at":{"type":["string","null"],"description":"NULL while suspended/running; set on terminal status."}},"required":["id","automation_id","workspace_id","status","trigger_source","depth","workflow_version_at_dispatch","step_outputs","trigger_payload","error","meta","started_at","finished_at"],"description":"A single workflow run row."},"WorkflowRunCancelResponse":{"type":"object","properties":{"run":{"allOf":[{"$ref":"#/components/schemas/WorkflowRun"},{"description":"The cancelled run row, with `meta.cancelledBy`/`meta.cancelledAt` recorded and any matching scheduler row consumed."}]}},"required":["run"]},"WorkflowRunRetryResponse":{"type":"object","properties":{"run":{"allOf":[{"$ref":"#/components/schemas/WorkflowRun"},{"description":"The newly dispatched retry run. Lineage to the parent is recorded on `meta.parentRunId`."}]}},"required":["run"]},"AutomationRotateKeyResponse":{"type":"object","properties":{"automation":{"allOf":[{"$ref":"#/components/schemas/Automation"},{"description":"The workflow with its webhook node's `parameters.ingestKeyHash` updated."}]},"ingest_key":{"type":"string","description":"The newly generated plaintext ingest key. Returned exactly ONCE, never persisted in plaintext. Use it to update Sentry / Stripe / GitHub webhook URLs that point at this workflow."},"webhook_url":{"type":"string","description":"The full webhook URL with the new key — convenience for copy-paste into external sender configs. Path is `/api/automations/webhook/:ingestKey`; the host is omitted so the caller resolves it against their environment."}},"required":["automation","ingest_key","webhook_url"]},"WorkflowRunListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowRun"}},"total":{"type":"integer","minimum":0,"description":"Count of rows in this page."},"has_more":{"type":"boolean","description":"True if a subsequent page exists. Set when the underlying query returned `limit + 1` hint rows."}},"required":["data","total","has_more"]},"WorkflowRunHeatmapBucket":{"type":"object","properties":{"hour":{"type":"string","description":"UTC hour bucket (`date_trunc('hour', started_at)`) as ISO 8601."},"count":{"type":"integer","minimum":0,"description":"Run count for this hour. Empty hours are absent from the array."}},"required":["hour","count"]},"WorkflowRunHeatmapResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowRunHeatmapBucket"}}},"required":["data"]},"AutomationWorkflowVersion":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"`automation_workflow_versions.id`."},"automation_id":{"type":"string","format":"uuid","description":"Parent workflow id."},"version":{"type":"integer","exclusiveMinimum":0,"description":"Monotonically-increasing version number. v1 is seeded on create; every subsequent PATCH-with-workflow-change appends a new row at the next integer."},"workflow":{"allOf":[{"$ref":"#/components/schemas/AutomationWorkflow"},{"description":"Immutable snapshot of the workflow JSONB at this version — the exact bytes that were stored on `automations.workflow` at the time. Restore copies this back verbatim."}]},"edited_by":{"type":["string","null"],"format":"uuid","description":"User who created this version row. May be NULL if the user has been removed (FK is ON DELETE SET NULL — history rows survive editor removal for audit-trail integrity)."},"edit_summary":{"type":["string","null"],"description":"Optional human note recorded on the version row when the workflow changed. NULL on rows where the editor didn't supply a summary."},"created_at":{"type":"string"}},"required":["id","automation_id","version","workflow","edited_by","edit_summary","created_at"],"description":"An immutable workflow snapshot. Append-only; never mutated or deleted (apart from cascade on parent automation delete)."},"AutomationWorkflowVersionListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AutomationWorkflowVersion"},"description":"Versions newest-first (DESC by `version`)."},"total":{"type":"integer","minimum":0,"description":"Count of rows in this page."},"has_more":{"type":"boolean","description":"True if a subsequent page exists. Set when the underlying query returned `limit + 1` hint rows."}},"required":["data","total","has_more"]},"AutomationWorkflowVersionRestoreResponse":{"type":"object","properties":{"automation":{"allOf":[{"$ref":"#/components/schemas/Automation"},{"description":"The parent workflow with `workflow` byte-restored from the historical version and `workflow_version` bumped to the new top-of-history value."}]},"version":{"allOf":[{"$ref":"#/components/schemas/AutomationWorkflowVersion"},{"description":"The newly-appended version row carrying the byte-identical snapshot. Its `version` number is the new top-of-history (NOT the source version's number) — restore is non-destructive and preserves the prior history."}]}},"required":["automation","version"]},"AutomationExportNativeResponse":{"type":"object","properties":{"automation_id":{"type":"string","format":"uuid"},"name":{"type":"string"},"format":{"type":"string","enum":["native","n8n"],"description":"Which document this body carries. `native` is the workflow JSONB verbatim; `n8n` is the translated n8n-shaped document — check `X-Automations-Lossy-Translation` for round-trip fidelity."},"workflow_version":{"type":"integer","exclusiveMinimum":0,"description":"`automations.workflow_version` at export time. Recorded so the consumer can detect drift when re-importing. Present on both formats."},"workflow":{"allOf":[{"$ref":"#/components/schemas/AutomationWorkflow"},{"description":"The workflow document. On `format=native` these are the raw JSONB bytes of `Automation.workflow` — no translation, no truncation. On `format=n8n` the nodes carry reversed `={{ ... }}` parameters."}]},"exported_at":{"type":"string","description":"ISO 8601 timestamp of the export. Useful for change-tracking."}},"required":["automation_id","name","format","workflow_version","workflow","exported_at"],"description":"Body of a successful `GET /api/automations/:id/export` response, either format. Native-format export carries the workflow JSONB verbatim — re-importing produces a byte-identical row."},"AutomationPermissionEntry":{"type":"object","properties":{"type":{"type":"string","enum":["user"]},"user_id":{"type":"string","format":"uuid"},"role":{"type":"string"},"display_name":{"type":["string","null"]},"primary_email":{"type":["string","null"]},"username":{"type":["string","null"]}},"required":["type","user_id","role"],"additionalProperties":{}},"AutomationPermissionsListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AutomationPermissionEntry"}},"total":{"type":"integer","minimum":0},"has_more":{"type":"boolean","enum":[false]},"pending":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}},"maxItems":0,"default":[]}},"required":["data","total","has_more"]},"AutomationSetPermissionResponse":{"type":"object","properties":{"document_id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"role":{"type":"string"}},"required":["document_id","user_id","role"]},"AutomationVisibilityResponse":{"type":"object","properties":{"visibility":{"type":"string"}},"required":["visibility"]},"AutomationUpdateInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":["string","null"],"maxLength":2000},"workflow":{"allOf":[{"$ref":"#/components/schemas/AutomationWorkflow"},{"description":"If provided, the engine writes a new row to `automation_workflow_versions` AND increments `automations.workflow_version` per spec P21."}]},"active":{"type":"boolean","description":"Direct toggle. The dedicated `_enable`/`_disable` lifecycle routes (item 26) are sugar over this same field."},"visibility":{"$ref":"#/components/schemas/AutomationVisibility"},"shared_with":{"type":"array","items":{"$ref":"#/components/schemas/AutomationShareEntry"}},"tags":{"type":"array","items":{"type":"string"}},"edit_summary":{"type":"string","maxLength":500,"description":"Optional human note recorded on the version row when the `workflow` field changes."}},"description":"Partial update. Only fields explicitly present in the body are written; omitted fields keep their prior value. If `workflow` is included, a new immutable version row is created."},"AutomationsWellKnownIpsResponse":{"type":"object","properties":{"ips":{"type":"array","items":{"type":"string"},"description":"CIDR ranges (IPv4 + IPv6) the workspace's outbound HTTP traffic may originate from. Best-effort — Cloud Run egress is not strictly static, so allowlist consumers should periodically re-fetch this list."},"region":{"type":"string","description":"GCP region the runtime currently deploys to. Today: `us-west1`. v1.1 may add additional regions; the response will list every active region's egress range."},"source":{"type":"string","description":"Upstream source the IP list is derived from. Today: `https://www.gstatic.com/ipranges/cloud.json` filtered to the active region. Consumers can fetch this URL directly for the freshest possible list."},"note":{"type":"string","description":"Disclaimer about the best-effort nature of the list. v1 publishes a representative subset of the GCP us-west1 ranges; v1.1 adds a static-egress NAT and tightens the disclaimer."},"last_verified":{"type":"string","description":"ISO 8601 date the published list was last manually verified against the upstream source. Stale dates are a signal to re-fetch upstream rather than trust this response."}},"required":["ips","region","source","note","last_verified"],"description":"Public response of `GET /.well-known/automations-ips`. No auth required — corporate firewalls fetch this without credentials to populate their allowlists for inbound webhook senders that Ambiguous routes through (Slack, Sentry, etc.)."},"SignRetentionResponse":{"type":"object","properties":{"retention_days":{"type":["integer","null"],"description":"null means indefinite retention — no document is ever purge-eligible."}},"required":["retention_days"]},"SignPurgeQueueEntry":{"type":"object","properties":{"document_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string","description":"The terminal status the document was queued in — completed, voided, or expired."},"purge_queued_at":{"type":"string","description":"When the retention period elapsed and the document entered the queue."},"purge_after":{"type":"string","description":"When the sealed PDF is deleted. Restorable until this instant (LEGAL.md L8)."}},"required":["document_id","title","status","purge_queued_at","purge_after"]},"SignPurgeQueueResponse":{"type":"object","properties":{"queued":{"type":"array","items":{"$ref":"#/components/schemas/SignPurgeQueueEntry"}}},"required":["queued"]},"SignTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":["string","null"]},"source_pdf_file_id":{"type":["string","null"],"format":"uuid"},"fields":{"type":"array","items":{"$ref":"#/components/schemas/SignTemplateField"}},"signer_roles":{"type":"array","items":{"$ref":"#/components/schemas/SignTemplateSignerRole"}},"use_count":{"type":"number"},"created_at":{"type":"string"}},"required":["id","title","description","source_pdf_file_id","fields","signer_roles","use_count","created_at"]},"SignTemplateField":{"type":"object","properties":{"type":{"type":"string","enum":["signature","initial","text","date","checkbox","number","file"]},"page":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"required":{"type":"boolean"},"defaultValue":{"type":"string"},"signerRole":{"type":"string"}},"required":["type","page","x","y","w","h","required","signerRole"]},"SignTemplateSignerRole":{"type":"object","properties":{"role":{"type":"string"},"label":{"type":"string"},"orderIndex":{"type":"number"}},"required":["role","label","orderIndex"]},"SignTemplateListResponse":{"type":"object","properties":{"templates":{"type":"array","items":{"$ref":"#/components/schemas/SignTemplate"}}},"required":["templates"]},"SignTemplateWrappedResponse":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/SignTemplate"}},"required":["template"]},"SignDocumentWithSigners":{"allOf":[{"$ref":"#/components/schemas/SignDocument"},{"type":"object","properties":{"signers":{"type":"array","items":{"$ref":"#/components/schemas/SignSigner"}},"fields":{"type":"array","items":{"$ref":"#/components/schemas/SignField"}}},"required":["signers","fields"]}]},"SignSigner":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"document_id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["signer","cc"]},"status":{"type":"string","enum":["pending","sent","viewed","consented","signed","declined","notified"]},"order_index":{"type":"number"},"signer_user_id":{"type":["string","null"],"format":"uuid"},"sent_at":{"type":["string","null"]},"viewed_at":{"type":["string","null"]},"signed_at":{"type":["string","null"]},"declined_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","document_id","email","name","role","status","order_index","signer_user_id","sent_at","viewed_at","signed_at","declined_at","created_at"]},"SignField":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"document_id":{"type":"string","format":"uuid"},"signer_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["signature","initial","text","date","checkbox","number","file"]},"page":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"required":{"type":"boolean"},"default_value":{"type":["string","null"]},"value":{"type":["string","null"]}},"required":["id","document_id","signer_id","type","page","x","y","w","h","required","default_value","value"]},"SignDocument":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string","enum":["draft","preview_pending","out","completed","voided","expired"]},"source_type":{"type":"string","enum":["pdf","doc"]},"source_doc_id":{"type":["string","null"],"format":"uuid"},"source_pdf_file_id":{"type":["string","null"],"format":"uuid"},"rendered_pdf_file_id":{"type":["string","null"],"format":"uuid"},"completed_pdf_file_id":{"type":["string","null"],"format":"uuid"},"completed_pdf_hash":{"type":["string","null"]},"signer_ordering":{"type":"string","enum":["parallel","sequential"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]},"owner_id":{"type":["string","null"],"format":"uuid"},"confirmed_by":{"type":["string","null"],"format":"uuid"},"confirmed_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"voided_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","workspace_id","title","status","source_type","source_doc_id","source_pdf_file_id","rendered_pdf_file_id","completed_pdf_file_id","completed_pdf_hash","signer_ordering","expires_at","message","owner_id","confirmed_by","confirmed_at","completed_at","voided_at","created_at","updated_at"]},"SignDocumentWrappedResponse":{"type":"object","properties":{"document":{"$ref":"#/components/schemas/SignDocumentWithSigners"}},"required":["document"]},"SignDocumentListResponse":{"type":"object","properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/SignDocument"}},"total":{"type":"number"}},"required":["documents","total"]},"SignDocumentRetentionResponse":{"type":"object","properties":{"document_id":{"type":"string","format":"uuid"},"retention_days":{"type":["integer","null"],"description":"This document's override. null defers to the workspace period."},"workspace_retention_days":{"type":["integer","null"],"description":"The workspace period this override supersedes."},"purge_eligible_at":{"type":["string","null"],"description":"When this document enters the purge queue. null means indefinite — it is not terminal, or no period resolves."}},"required":["document_id","retention_days","workspace_retention_days","purge_eligible_at"]},"SignRestoreFromPurgeResponse":{"type":"object","properties":{"document_id":{"type":"string","format":"uuid"},"purge_queued_at":{"type":["string","null"]},"purge_after":{"type":["string","null"]}},"required":["document_id","purge_queued_at","purge_after"]},"SignSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"SignSignerWrappedResponse":{"type":"object","properties":{"signer":{"$ref":"#/components/schemas/SignSigner"}},"required":["signer"]},"SignSignersListResponse":{"type":"object","properties":{"signers":{"type":"array","items":{"$ref":"#/components/schemas/SignSigner"}}},"required":["signers"]},"SignFieldWrappedResponse":{"type":"object","properties":{"field":{"$ref":"#/components/schemas/SignField"}},"required":["field"]},"SignPrepareResponse":{"type":"object","properties":{"document":{"$ref":"#/components/schemas/SignDocument"},"rendered_pdf_drive_file_id":{"type":"string","format":"uuid"}},"required":["document","rendered_pdf_drive_file_id"]},"SignConfirmResponse":{"type":"object","properties":{"document":{"$ref":"#/components/schemas/SignDocument"},"signers_notified":{"type":"number"}},"required":["document","signers_notified"]},"SignVoidResponse":{"type":"object","properties":{"document":{"$ref":"#/components/schemas/SignDocument"}},"required":["document"]},"SignVerifyResponse":{"type":"object","properties":{"valid":{"type":"boolean"},"signature_valid":{"type":"boolean"},"hash_valid":{"type":"boolean"},"signed_by":{"type":["string","null"]},"completed_at":{"type":["string","null"]}},"required":["valid","signature_valid","hash_valid","signed_by","completed_at"]},"SignReferenceItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string","enum":["draft","preview_pending","out","completed","voided","expired"]},"created_at":{"type":"string"}},"required":["id","title","status","created_at"]},"SignReferencesResponse":{"type":"object","properties":{"references":{"type":"array","items":{"$ref":"#/components/schemas/SignReferenceItem"}}},"required":["references"]},"VerifyPasswordResponse":{"type":"object","properties":{"valid":{"type":"boolean","enum":[true],"description":"Always `true` on 200. Wrong-password attempts return 401, never `valid: false`."}},"required":["valid"]},"PublicDocument":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","description":"Document family (`doc`, `sheet`, `slide`)."},"title":{"type":"string"},"content":{"description":"Authoring format for the document (ProseMirror JSON for docs/wiki, JSON for sheets/slides). Shape varies by `type`."},"visibility":{"type":"string","enum":["link","public"]},"link_permission":{"type":"string","enum":["viewer","commenter","editor"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"owner":{"type":["object","null"],"properties":{"display_name":{"type":"string","description":"Display name of the resource owner."}},"required":["display_name"],"description":"Owner display info (null when the owner row can't be resolved)."}},"required":["id","type","title","visibility","link_permission","created_at","updated_at","owner"]},"PublicLinkPasswordError":{"type":"object","properties":{"error":{"type":"string","description":"`This link is password-protected` when no `X-Link-Password` header was sent, `Incorrect password` when one was and it did not verify."},"code":{"type":"string","enum":["password_required"]},"details":{"type":"object","properties":{"password_required":{"type":"boolean","enum":[true]}},"required":["password_required"]}},"required":["error","code","details"]},"PublicWikiPage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["wiki"]},"title":{"type":"string"},"slug":{"type":"string"},"icon":{"type":["string","null"]},"cover_image":{"type":["string","null"]},"content":{"type":["string","null"],"description":"Page Markdown content."},"visibility":{"type":"string","enum":["link","public"]},"space":{"type":"object","properties":{"id":{"type":["string","null"],"format":"uuid"},"name":{"type":["string","null"]},"slug":{"type":["string","null"]}},"required":["id","name","slug"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"owner":{"type":["object","null"],"properties":{"display_name":{"type":"string","description":"Display name of the resource owner."}},"required":["display_name"],"description":"Owner display info (null when the owner row can't be resolved)."}},"required":["id","type","title","slug","icon","cover_image","content","visibility","space","created_at","updated_at","owner"]},"PublicDriveBinaryBody":{"type":"string"},"PublicFile":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":["integer","null"]},"visibility":{"type":"string","enum":["link","public"]},"download_url":{"type":"string","description":"Server-relative URL to fetch the binary content (`/api/drive/:id/content`)."},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"owner":{"type":["object","null"],"properties":{"display_name":{"type":"string","description":"Display name of the resource owner."}},"required":["display_name"],"description":"Owner display info (null when the owner row can't be resolved)."},"workspace_name":{"type":["string","null"],"description":"Name of the owning workspace, for the viewer's breadcrumb."},"path":{"type":["array","null"],"items":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]},"description":"Folder names from root to the file's parent, for the viewer's breadcrumb. `null` when the file sits at the root."}},"required":["id","name","mime_type","size_bytes","visibility","download_url","created_at","updated_at","owner","workspace_name","path"]},"PublicSlides":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"data":{"description":"Full slide deck JSON: `{ slides, settings, masterSlides }`. Shape matches authenticated GET /api/slides/:id/data response."},"slide_count":{"type":"integer"},"visibility":{"type":"string","enum":["link","public"]},"link_permission":{"type":"string","enum":["viewer","commenter","editor"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"owner":{"type":["object","null"],"properties":{"display_name":{"type":"string","description":"Display name of the resource owner."}},"required":["display_name"],"description":"Owner display info (null when the owner row can't be resolved)."}},"required":["id","title","slide_count","visibility","link_permission","created_at","updated_at","owner"]},"AssistantSharedConversationMessage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"role":{"type":"string"},"content":{},"created_at":{"type":"string"}},"required":["id","role","created_at"]},"AssistantSharedConversation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/AssistantSharedConversationMessage"}}},"required":["id","title","created_at","updated_at","messages"]},"FullBooking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"link_title":{"type":"string"},"guest_name":{"type":"string"},"guest_email":{"type":"string"},"start_at":{"type":"string"},"end_at":{"type":"string"},"status":{"type":"string","enum":["confirmed","cancelled"]},"cancel_token":{"type":"string"},"notes":{"type":["string","null"]}},"required":["id","guest_name","guest_email","start_at","end_at","status","cancel_token","notes"]},"FullBookingResponse":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/FullBooking"}},"required":["booking"]},"CancelledBooking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["cancelled"]},"cancelled_at":{"type":["string","null"]},"cancel_reason":{"type":["string","null"]}},"required":["id","status","cancelled_at","cancel_reason"]},"CancelBookingResponse":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/CancelledBooking"}},"required":["booking"]},"PublicSchedulerLink":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"location":{"type":["string","null"]},"duration_minutes":{"type":"integer","exclusiveMinimum":0},"timezone":{"type":"string"},"brand_color":{"type":["string","null"]},"min_notice_minutes":{"type":"integer"},"max_advance_days":{"type":"integer"},"owner_name":{"type":["string","null"]},"owner_avatar_url":{"type":["string","null"]},"owner_username":{"type":["string","null"]},"workspace_slug":{"type":["string","null"]}},"required":["id","slug","title","description","location","duration_minutes","timezone","brand_color","min_notice_minutes","max_advance_days","owner_name","owner_avatar_url","owner_username","workspace_slug"]},"PublicSchedulerLinkResponse":{"type":"object","properties":{"link":{"$ref":"#/components/schemas/PublicSchedulerLink"}},"required":["link"]},"SchedulerSlot":{"type":"object","properties":{"start":{"type":"string","description":"ISO 8601 start timestamp."},"end":{"type":"string","description":"ISO 8601 end timestamp."}},"required":["start","end"]},"SchedulerSlotsResponse":{"type":"object","properties":{"date":{"type":"string"},"slots":{"type":"array","items":{"$ref":"#/components/schemas/SchedulerSlot"}}},"required":["date","slots"]},"Booking":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"guest_name":{"type":"string"},"guest_email":{"type":"string"},"start_at":{"type":"string"},"end_at":{"type":"string"},"status":{"type":"string","enum":["confirmed","cancelled"]},"cancel_token":{"type":"string"},"link_title":{"type":"string"}},"required":["id","guest_name","guest_email","start_at","end_at","status","cancel_token"]},"BookingResponse":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/Booking"}},"required":["booking"]}},"parameters":{},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT or API Key","description":"JWT (humans) or API key with `ak_` prefix (agents). Both via `Authorization: Bearer <token>`."}}},"paths":{"/api/auth/signup-agent":{"post":{"operationId":"auth_signup_agent","tags":["Auth"],"description":"Agent-initiated signup. Atomically creates a provisional workspace + agent user + API key, and emails `human_email` a claim link so they can take ownership (or merge the workspace into one they already run). The agent is usable immediately via the returned `api_key`. Admin features (invites, provisioning more agents, billing upgrades) are gated on the provisional workspace until the human claims. Never 409s on existing `human_email` — existing-account detection happens at claim time, not here. See `agents/modules/IDENTITY.md` Agent self-bootstrap mechanics.","x-cli":{"command":"auth signup","output":{"format":"object"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupAgentInput"}}}},"responses":{"201":{"description":"Agent provisioned; provisional workspace created; claim email sent to human","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupAgentResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Browser pairing code not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Requested slug exhausted alternatives","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Browser pairing code expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/agent-pairings":{"post":{"operationId":"agent_pairing_create","tags":["Auth"],"description":"Create a short-lived browser/agent pairing. The private browser credential is returned only as an HttpOnly cookie; the JSON body contains the human-typeable code.","responses":{"201":{"description":"Pairing created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentPairingCreateResponse"}}}},"429":{"description":"Pairing creation rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/agent-pairings/status":{"get":{"operationId":"agent_pairing_status","tags":["Auth"],"description":"Read minimal pairing state using the private HttpOnly browser cookie. The short code is not accepted as status authority.","responses":{"200":{"description":"Minimal pairing state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentPairingStatusResponse"}}}},"400":{"description":"Pairing request invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Pairing browser credential missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Pairing session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Pairing state conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Pairing session expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Pairing status rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/agent-pairings/handoff":{"post":{"operationId":"agent_pairing_handoff","tags":["Auth"],"description":"Exchange a ready browser pairing for a separate one-time URL handoff. Responds only with a same-origin redirect.","responses":{"303":{"description":"Redirect to the one-time app handoff consumer"},"400":{"description":"Pairing request invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Pairing browser credential missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Pairing session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Pairing is not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Pairing session expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Pairing handoff rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/agent-claim/handoff/{handoff}":{"get":{"operationId":"agent_claim_handoff_consume","tags":["Auth"],"description":"Atomically consume the URL handoff, establish an HttpOnly claim context, and immediately redirect to a token-free URL.","parameters":[{"schema":{"type":"string","minLength":32,"maxLength":128},"required":true,"name":"handoff","in":"path"}],"responses":{"303":{"description":"Clean claim signup URL"}}}},"/api/public/agent-claim/context":{"get":{"operationId":"agent_claim_context","tags":["Auth"],"description":"Read the focused claim/signup context from its HttpOnly cookie. No email claim token or secret is returned.","responses":{"200":{"description":"Claim context","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimContextResponse"}}}},"400":{"description":"Claim request invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Claim context missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Claim context not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Claim state conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Claim context expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Claim context rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/agent-claim/resend":{"post":{"operationId":"agent_claim_resend_email","tags":["Auth"],"description":"Retry the existing invitation email using the HttpOnly claim context. The email claim token is never returned to the browser.","responses":{"200":{"description":"Invitation email sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimResendResponse"}}}},"400":{"description":"Claim request invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Claim context missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Claim context not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Invitation already resolved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Claim context expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Invitation email retry rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Invitation email unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/agent-claim/current":{"post":{"operationId":"agent_claim_current_identity","tags":["Auth"],"description":"Select the currently authenticated human account as the claim candidate without changing ownership or the active product session.","responses":{"200":{"description":"Candidate identity and authorized merge targets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimIdentityResponse"}}}},"400":{"description":"Claim request invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Human account required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Claim context not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Invitation resolved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Claim context expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Claim identity rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/agent-claim/google":{"post":{"operationId":"agent_claim_google_identity","tags":["Auth"],"description":"Select a verified Google identity as a claim candidate. The existing browser session is not replaced before final confirmation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id_token":{"type":"string","minLength":1}},"required":["id_token"],"additionalProperties":false}}}},"responses":{"200":{"description":"Candidate identity and authorized merge targets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimIdentityResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Google identity invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Account suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Claim context not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Invitation resolved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Claim context expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Claim identity rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/agent-claim/complete":{"post":{"operationId":"agent_claim_complete","tags":["Auth"],"description":"Atomically claim the provisional workspace or merge its agent into an authorized existing workspace, then establish the selected account session.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"candidate_token":{"type":"string","minLength":1},"action":{"type":"string","enum":["claim","merge"]},"target_workspace_id":{"type":"string","format":"uuid"},"confirm_email_mismatch":{"type":"boolean"}},"required":["candidate_token","action"],"additionalProperties":false}}}},"responses":{"200":{"description":"Claim completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimCompleteResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Candidate identity invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Email mismatch or merge authorization not confirmed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Claim context or account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Invitation already resolved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Claim context expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Claim completion rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/claim/{token}":{"get":{"operationId":"claim_token_state","tags":["Auth"],"description":"Peek at a claim token's lifecycle state. Returns `pending` (awaiting action), `used` (already claimed or merged), or `invalid` (unknown token). Powers the claim page's branch rendering.","parameters":[{"schema":{"type":"string"},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"Token state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimTokenStateResponse"}}}}}}},"/api/auth/claim-workspace":{"post":{"operationId":"auth_claim_workspace","tags":["Auth"],"description":"Claim a provisional workspace created via agent self-bootstrap. Possession of the claim token is authority; no separate session auth required. If no account exists for the token's `human_email`, pass `password` to create one inline — the token arrived in the claimant's inbox, which is itself proof of email ownership, so no verification step is needed. Returns a session JWT bound to the new owner membership.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The claim token from the email link — single-use, possession proves control of `human_email`."},"password":{"type":"string","minLength":8,"description":"Required when no account exists for `human_email`; sets the new human account's password. Ignored if an account already exists (the human signs in via the normal flow if they aren't already)."},"display_name":{"type":"string","minLength":1,"description":"Optional display name for the new account. Defaults to the local part of `human_email`."},"workspace_name":{"type":"string","minLength":1,"maxLength":100,"description":"Optional new workspace display name. When provided, the workspace is renamed atomically with the claim. Omit to keep the auto-derived name from the agent signup."},"workspace_slug":{"type":"string","minLength":3,"maxLength":48,"description":"Optional new workspace slug. When provided, the workspace slug AND its default email domain (`{slug}.{WORKSPACE_EMAIL_DOMAIN}`) are updated atomically with the claim. 3-48 lowercase alphanumeric + hyphens; no leading/trailing/consecutive hyphens; must contain at least one letter; reserved slugs rejected. On collision, returns 409 with suggested alternatives. Omit to keep the auto-derived slug — any URL the agent already shared continues to work."}},"required":["token"],"additionalProperties":false}}}},"responses":{"200":{"description":"Workspace claimed; claimant is now owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimWorkspaceResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Invalid claim token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Claim token already used OR workspace_slug taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimWorkspaceConflict"}}}}}}},"/api/auth/apple":{"post":{"operationId":"post_apple","tags":["Auth"],"description":"Sign in or register with an Apple-issued identity token through the same account and session path used by Google SSO.","x-cli":{"hidden":true,"command":"auth apple"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id_token":{"type":"string","description":"Apple-issued identity token (JWT). Verified server-side against Apple's signing keys, issuer, expiry, and configured audience."},"display_name":{"type":"string","minLength":1,"description":"Name Apple returns only on the first authorization. Used when present; otherwise the verified email local-part is used."},"referred_by_slug":{"type":"string","pattern":"^[a-z0-9-]{3,64}$","description":"Optional referral slug, consumed only when the verified Apple identity creates a new account."},"referral_source":{"type":"string","enum":["invite_link","friend_invite","share_friend","shared_doc","shared_form","shared_booking","shared_wiki"],"description":"Optional referral source. Defaults to `invite_link` when a referral slug is present."}},"required":["id_token"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppleSignInResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/register":{"post":{"operationId":"auth_register","tags":["Auth"],"description":"Register a new human account. Returns either a registration token (proceed to workspace setup) or a verification-pending response when email verification is enabled. Agents must be provisioned via POST /api/admin/users/provision-agent.","x-cli":{"command":"auth register","output":{"successMessage":"Account registered"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Login email for the new account. Lowercased + dedup-checked against `accounts.external_email`."},"password":{"type":"string","minLength":8,"description":"Plaintext password. Must be at least 8 characters; hashed server-side with bcrypt."},"display_name":{"type":"string","minLength":1,"description":"Human-readable name shown across the workspace UI and outbound email From: headers."},"type":{"type":"string","enum":["human","agent"],"description":"Optional. Public registration accepts only humans; agents must be provisioned via POST /api/admin/users/provision-agent (returns 403 otherwise)."},"referred_by_slug":{"type":"string","pattern":"^[a-z0-9-]{3,64}$","description":"Optional. The `?ref=:slug` value captured at the landing-page click and persisted in localStorage. Resolved server-side to the inviter's account ID; written to `accounts.referred_by_account_id` + `referral_attributions`. Self-referral is silently dropped. Per spec Pat *Referral attribution*."},"referral_source":{"type":"string","enum":["invite_link","friend_invite","share_friend","shared_doc","shared_form","shared_booking","shared_wiki"],"description":"Optional. Source tag for the attribution row. Defaults to `invite_link` when omitted but `referred_by_slug` is present."},"signup_source":{"type":"string","description":"Optional. The `?from=lp-{base}` landing page. Becomes the `signup_source` property on `Account Created`. Silently ignored unless it is one of the six legal `/lp` bases."},"signup_domain":{"type":"string","description":"Optional. The money page's `?domain=` hero input. Stored only when it is a bare RFC-1123 hostname of at most 253 chars; silently discarded otherwise and never echoed back."},"signup_variant":{"type":"string","description":"Optional. The guide step-2 gate's `?v=` variant, stored alongside `signup_source` so a guide signup keeps its landing variant without depending on the attribution cookie."},"signup_intent":{"type":"string","description":"Optional. The `?intent=` journey the click came from. `invite-agent` is the only value this app answers to; anything else is silently discarded. When present and the signup completes, onboarding opens the guided create-agent flow once the workspace exists instead of dropping the person on an empty workspace. Pinned by the cross-repo handoff contract `specs/handoffs/invite-your-ai.md`."},"signup_harness":{"type":"string","description":"Optional. The `?harness=` agent runtime the click came from, one of `claude-code · openclaw · hermes · nanoclaw · grok-bot · cursor · codex`. Personalisation only — an unknown value is dropped and the intent survives, so the flow still opens, just unnamed. Never echoed into a page."},"tos_consent":{"type":"boolean","description":"Must be `true` for human registration to indicate the user has accepted the Terms of Service and Privacy Policy. Registration is rejected with 400 if absent or false. Not required for agent-type requests (which are rejected with 403 regardless)."}},"required":["email","display_name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/merge-workspace":{"post":{"operationId":"auth_merge_workspace","tags":["Auth"],"description":"Merge a provisional workspace into an existing one the caller owns or admins. Moves the agent user + all workspace-scoped content to the target via UPDATE ... SET workspace_id = :target. The agent's API key keeps working. The provisional workspace is deleted afterward.","x-cli":{"hidden":true,"command":"auth merge-workspace","confirm":true,"output":{"successMessage":"Workspace merged"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The claim token from the email link — single-use."},"target_workspace_id":{"type":"string","format":"uuid","description":"ID of an existing workspace the caller owns or admins — the agent + all content will be moved here."}},"required":["token","target_workspace_id"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MergeWorkspaceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/google":{"post":{"operationId":"post_google","tags":["Auth"],"description":"Sign in (or register) with a Google-issued ID token. Three branches: brand-new account → registration_token; existing multi-workspace account → workspace picker; otherwise authenticated.","x-cli":{"hidden":true,"command":"auth google"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id_token":{"type":"string","description":"Google-issued ID token (JWT). Verified server-side against Google's signing keys + Workspace audience claim."},"referred_by_slug":{"type":"string","pattern":"^[a-z0-9-]{3,64}$","description":"Optional. Same semantics as `RegisterInput.referred_by_slug` but resolved only on the brand-new-account branch (existing-account sign-in is not a signup and earns no attribution)."},"referral_source":{"type":"string","enum":["invite_link","friend_invite","share_friend","shared_doc","shared_form","shared_booking","shared_wiki"],"description":"Optional. Source tag for the attribution row. Defaults to `invite_link` when omitted but `referred_by_slug` is present."},"signup_source":{"type":"string","description":"Optional. The `?from=lp-{base}` landing page. Becomes the `signup_source` property on `Account Created`. Silently ignored unless it is one of the six legal `/lp` bases."},"signup_domain":{"type":"string","description":"Optional. The money page's `?domain=` hero input. Stored only when it is a bare RFC-1123 hostname of at most 253 chars; silently discarded otherwise and never echoed back."},"signup_variant":{"type":"string","description":"Optional. The guide step-2 gate's `?v=` variant, stored alongside `signup_source` so a guide signup keeps its landing variant without depending on the attribution cookie."},"signup_intent":{"type":"string","description":"Optional. The `?intent=` journey the click came from. `invite-agent` is the only value this app answers to; anything else is silently discarded. When present and the signup completes, onboarding opens the guided create-agent flow once the workspace exists instead of dropping the person on an empty workspace. Pinned by the cross-repo handoff contract `specs/handoffs/invite-your-ai.md`."},"signup_harness":{"type":"string","description":"Optional. The `?harness=` agent runtime the click came from, one of `claude-code · openclaw · hermes · nanoclaw · grok-bot · cursor · codex`. Personalisation only — an unknown value is dropped and the intent survives, so the flow still opens, just unnamed. Never echoed into a page."}},"required":["id_token"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleSignInResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/login":{"post":{"operationId":"post_login","tags":["Auth"],"description":"Sign in with email + password. Returns either a workspace picker (multi-workspace account) or an authenticated response (token + user). Email verification gate fires before either branch when REQUIRE_EMAIL_VERIFICATION is enabled.","x-cli":{"command":"auth login","output":{"successMessage":"Logged in"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Login email."},"password":{"type":"string","description":"Plaintext password. Compared against bcrypt-hashed `accounts.password_hash`."}},"required":["email","password"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginVerificationRequiredResponse"}}}}}}},"/api/auth/select-workspace":{"post":{"operationId":"post_select_workspace","tags":["Auth"],"description":"Pick one workspace after the /login workspace_picker branch and exchange the (account_id, workspace_id) pair for a fresh JWT scoped to that workspace.","x-cli":{"command":"auth select-workspace","output":{"successMessage":"Workspace selected"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":"string","format":"uuid","description":"Account ID returned by the `/login` workspace_picker branch."},"workspace_id":{"type":"string","format":"uuid","description":"Workspace ID the user clicked."},"picker_session_token":{"type":"string","description":"Short-lived JWT from the workspace_picker response. Alternative to passing via Authorization header."}},"required":["account_id","workspace_id"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AuthenticatedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginVerificationRequiredResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/verify-email":{"post":{"operationId":"post_verify_email","tags":["Auth"],"description":"Exchange an email-verification token for a registration token. When needs_workspace_setup is true the frontend calls POST /api/workspaces to create the user's first workspace; when false the account already belongs to a workspace and the frontend continues to sign-in.","x-cli":{"hidden":true,"command":"auth verify-email"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Email-verification token from the link in the verification email. Single-use; expires after 24h."}},"required":["token"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VerifyEmailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/resend-verification":{"post":{"operationId":"post_resend_verification","tags":["Auth"],"description":"Resend the email-verification link. Always returns 200 to prevent email enumeration.","x-cli":{"hidden":true,"command":"auth resend-verification"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email to (potentially) resend a verification link to. Endpoint always returns 200 to prevent email-enumeration attacks."}},"required":["email"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/send-phone-verification":{"post":{"operationId":"post_send_phone_verification","tags":["Auth"],"description":"Send a 6-digit SMS verification code to the supplied phone number. Authenticated. The code's sha-256 hash is stored on accounts.phone_verification_token with a 10-minute expiry.","x-cli":{"hidden":true,"command":"auth send-phone-verification"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","minLength":7,"maxLength":20,"description":"Phone number in E.164 format (or an accepted superset). Twilio normalizes; we store the verified value."}},"required":["phone"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/verify-phone":{"post":{"operationId":"post_verify_phone","tags":["Auth"],"description":"Verify a 6-digit SMS code against the stored hash. On success flips accounts.phone_verified and emits user.phone_verified for the activation ladder.","x-cli":{"hidden":true,"command":"auth verify-phone"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":6,"maxLength":6,"description":"6-digit SMS verification code received via Twilio."}},"required":["code"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VerifyPhoneResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/forgot-password":{"post":{"operationId":"post_forgot_password","tags":["Auth"],"description":"Send a password-reset link. Always returns 200 to prevent email enumeration.","x-cli":{"command":"auth forgot-password","output":{"successMessage":"If the email exists, a reset link has been sent"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email to (potentially) send a password-reset link to. Endpoint always returns 200 to prevent email-enumeration attacks."}},"required":["email"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/find-workspaces":{"post":{"operationId":"post_find_workspaces","tags":["Auth"],"description":"Email a list of workspaces associated with this email. Always returns 200 to prevent email enumeration.","x-cli":{"command":"auth find-workspaces","output":{"successMessage":"If the email has workspaces, a list has been sent"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email to (potentially) send a password-reset link to. Endpoint always returns 200 to prevent email-enumeration attacks."}},"required":["email"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/reset-password":{"post":{"operationId":"post_reset_password","tags":["Auth"],"description":"Exchange a password-reset token + new password for a fresh authenticated session. Behaves like /login afterwards (workspace_picker | authenticated).","x-cli":{"command":"auth reset-password","output":{"successMessage":"Password reset successful"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Password-reset token from the link in the reset email. Single-use; expires after 1h."},"new_password":{"type":"string","minLength":8,"description":"New plaintext password. Must be at least 8 characters."}},"required":["token"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/change-password":{"post":{"operationId":"post_change_password","tags":["Auth"],"description":"Change the authenticated user's password. Requires the current password for verification.","x-cli":{"command":"auth change-password","output":{"successMessage":"Password changed"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"current_password":{"type":"string","description":"Current plaintext password. Verified before the new one is stored."},"new_password":{"type":"string","minLength":8,"description":"New plaintext password. Must be at least 8 characters."}},"required":["current_password"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/reconsent":{"post":{"operationId":"post_reconsent","tags":["Auth"],"description":"Accept an updated Terms of Service. Required when consent_version in the login response is outdated.","x-cli":{"hidden":true,"command":"auth reconsent"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tos_consent":{"type":"boolean","enum":[true],"description":"Must be true to accept the updated Terms of Service."}},"required":["tos_consent"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ReconsentResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/verify-external-email":{"post":{"operationId":"post_verify_external_email","tags":["Auth"],"description":"Public endpoint — exchange a verification token for confirmation that the external email is now verified.","x-cli":{"hidden":true,"command":"auth verify-external-email"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"Verification token from the link in the verification email."}},"required":["token"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VerifyExternalEmailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/native/code":{"post":{"operationId":"auth_native_code","tags":["Auth"],"description":"Mint a one-time, PKCE-bound code for the authenticated user so a native client (desktop / CLI / mobile) can finish a browser-handoff login. Requires a session JWT — the user has just authenticated first-party in the system browser. The native client trades the code at POST /api/auth/native/exchange.","x-cli":{"hidden":true,"command":"auth native-code"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code_challenge":{"type":"string","minLength":43,"maxLength":128,"description":"PKCE S256 challenge: base64url(SHA-256(code_verifier)). The verifier never leaves the native client, so a code intercepted from a custom-scheme deep link is useless without it."},"client":{"type":"string","enum":["desktop","cli","mobile"],"description":"Originating native client, for audit/telemetry only."}},"required":["code_challenge"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NativeCodeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/native/exchange":{"post":{"operationId":"auth_native_exchange","tags":["Auth"],"description":"Exchange a one-time native-auth code (with its PKCE verifier) for the session JWT. Public; single-use; expires 60s after creation. First-party authentication — not the OAuth token endpoint (/oauth/token). Supersedes POST /api/auth/cli/exchange.","x-cli":{"hidden":true,"command":"auth native-exchange"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"One-time code delivered to the native client via its deep-link / loopback callback."},"code_verifier":{"type":"string","minLength":43,"maxLength":128,"description":"PKCE verifier. Required when the code was minted with a code_challenge; omitted for legacy CLI codes."}},"required":["code"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NativeExchangeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/cli":{"get":{"operationId":"get_cli","tags":["Auth"],"description":"CLI auth — render a self-contained HTML login form. The form posts to POST /api/auth/cli and on success redirects to the CLI's local callback URL with a one-time code.","x-cli":{"hidden":true,"command":"auth cli-form"},"parameters":[{"schema":{"type":"string","description":"Local CLI callback port (1024-65535). Used to redirect with the one-time code."},"required":false,"description":"Local CLI callback port (1024-65535). Used to redirect with the one-time code.","name":"port","in":"query"},{"schema":{"type":"string","description":"Opaque CLI-generated UUID-format state token. Echoed back via the redirect to defeat CSRF."},"required":false,"description":"Opaque CLI-generated UUID-format state token. Echoed back via the redirect to defeat CSRF.","name":"state","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthBinaryBody"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"post_cli","tags":["Auth"],"description":"JSON-based CLI login. With port + state returns a redirect URL containing a one-time code; without them returns the auth JWT directly. Multi-workspace accounts are rejected here (use the web app to pick a workspace first).","x-cli":{"hidden":true,"command":"auth cli-login"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string"},"port":{"anyOf":[{"type":"string"},{"type":"number"}],"description":"Local CLI callback port. When provided with `state`, the response is a redirect URL with a one-time code instead of a token."},"state":{"type":"string","description":"Opaque CLI state token. Echoed via the redirect."}},"required":["email","password"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliLoginResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/cli/exchange":{"post":{"operationId":"post_cli_exchange","tags":["Auth"],"description":"DEPRECATED — use POST /api/auth/native/exchange. Retained as a back-compat alias for shipped CLI versions. Exchange a one-time code (from the /cli redirect) for the real auth JWT. Single-use; expires 60s after creation.","x-cli":{"hidden":true,"command":"auth cli-exchange"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"One-time UUID code received via the local callback URL. Single-use; expires after 60 seconds."}},"required":["code"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CliExchangeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users":{"get":{"operationId":"users_list","tags":["Identity"],"description":"List users in the active workspace. Powers @mention pickers, assignee dropdowns, etc. Filterable by q (matches display_name + username, case-insensitive). Limit defaults to 50, hard cap 100. Member-accessible — use this to resolve a name to a user_id when assigning tasks or @mentioning people; the admin list_users tool is admin-gated and 403s for members/coworkers.","x-tool":{"expose":["assistant","mcp","coworker"]},"x-cli":{"command":"users list"},"parameters":[{"schema":{"type":"string","description":"Substring filter against `display_name` and `username` (case-insensitive)."},"required":false,"description":"Substring filter against `display_name` and `username` (case-insensitive).","name":"q","in":"query"},{"schema":{"type":"string","description":"Max rows to return. Default 50, hard cap 100."},"required":false,"description":"Max rows to return. Default 50, hard cap 100.","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkspaceUsersListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/me":{"get":{"operationId":"auth_whoami","tags":["Identity"],"description":"Return the current authenticated user's profile (works with both JWT and API-key auth). needs_workspace_setup: true indicates the account has no workspace yet.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"auth whoami","hidden":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UserProfile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"auth_update_profile","tags":["Identity"],"description":"Update the current user's profile (display_name, avatar_url, meeting_url, has_seen_welcome_modal, has_dismissed_onboarding, analytics_opt_out, primary_external_email_id). Returns the same shape as GET /users/me.","x-cli":{"command":"auth update-profile"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"display_name":{"type":"string","minLength":1,"description":"New display name. Trimmed; rejected if empty after trim."},"avatar_url":{"type":["string","null"],"description":"New avatar proxy URL or null to clear. See `POST /users/me/avatar` for upload."},"has_seen_welcome_modal":{"type":"boolean","description":"Mark onboarding modal as seen."},"has_dismissed_onboarding":{"type":"boolean","description":"Permanently dismiss the Get Started onboarding checklist."},"analytics_opt_out":{"type":"boolean","description":"Opt out of non-essential analytics and data processing (Art. 21 GDPR). Effective within one request cycle."},"primary_external_email_id":{"type":["string","null"],"format":"uuid","description":"Set the primary external email (must be verified + owned by this user) or null to clear."},"meeting_url":{"type":["string","null"],"description":"Personal meeting URL (Zoom, Google Meet, etc.) or null to clear."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UserProfile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_own_account","tags":["Identity"],"description":"Delete the authenticated user's own account. Requires password confirmation. Workspace owners must transfer ownership first.","x-cli":{"command":"auth delete-account","confirm":true,"output":{"successMessage":"Account deleted"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string","description":"Current plaintext password. Verified before account deletion proceeds."}},"required":["password"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/me/send-as":{"put":{"operationId":"put_users_me_send_as","tags":["Identity"],"description":"Set or clear the user's custom-domain send-as email (e.g. ryan@pokermethod.com). Pass custom_email: null to clear.","x-cli":{"command":"auth set-send-as","output":{"successMessage":"Send-as email updated"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"custom_email":{"type":["string","null"],"description":"Verified custom-domain email or null to clear. Server validates that the user owns the domain."}},"required":["custom_email"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Compact profile shape returned by `/send-as`, `/avatar` upload, and `/avatar` delete. Excludes workspace + role + external-email fields."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/me/avatar":{"post":{"operationId":"post_users_me_avatar","tags":["Identity"],"description":"Upload a new avatar image (multipart 'file' field, max 5MB, image/jpeg|png|gif|webp). Auto-resized to 256×256 (JPEG/PNG/WebP) when sharp is available; GIFs uploaded as-is.","x-cli":{"command":"auth upload-avatar","output":{"successMessage":"Avatar uploaded"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Compact profile shape returned by `/send-as`, `/avatar` upload, and `/avatar` delete. Excludes workspace + role + external-email fields."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_users_me_avatar","tags":["Identity"],"description":"Remove the user's avatar URL. Existing GCS object is left in place (small storage cost).","x-cli":{"command":"auth delete-avatar","output":{"successMessage":"Avatar removed"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Compact profile shape returned by `/send-as`, `/avatar` upload, and `/avatar` delete. Excludes workspace + role + external-email fields."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/me/push-token":{"post":{"operationId":"post_users_me_push_token","tags":["Identity"],"description":"Register an APNs/FCM push token for this device, or remove it (omit token or pass null).","x-cli":{"hidden":true,"command":"auth push-token"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":["string","null"],"description":"APNs / FCM device token. Pass null or omit to remove the token."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/me/emails":{"get":{"operationId":"get_users_me_emails","tags":["Identity"],"description":"List the current user's external emails (verified + pending). Includes the login email as a synthetic always-verified row.","x-cli":{"command":"auth emails list","output":{"format":"table","columns":["id","email","verified"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalEmailsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"post_users_me_emails","tags":["Identity"],"description":"Add a new external email and send a verification link. The email becomes usable as a Send as alias once the user clicks the link.","x-cli":{"command":"auth emails add","output":{"successMessage":"Verification email sent to {email}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email to verify and register as an alias for this user. Triggers a verification email; pending until the user clicks the link."}},"required":["email"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalEmail"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/me/emails/{id}/resend":{"post":{"operationId":"post_users_me_emails_id_resend","tags":["Identity"],"description":"Resend the verification link for a pending external email.","x-cli":{"command":"auth emails resend","output":{"successMessage":"Verification email resent"}},"parameters":[{"schema":{"type":"string","description":"External email row ID."},"required":true,"description":"External email row ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/me/emails/{id}":{"delete":{"operationId":"delete_users_me_emails_id","tags":["Identity"],"description":"Remove an external email from the current user. The login email row cannot be removed.","x-cli":{"command":"auth emails delete","confirm":true,"output":{"successMessage":"External email removed"}},"parameters":[{"schema":{"type":"string","description":"External email row ID."},"required":true,"description":"External email row ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/notification-preferences":{"get":{"operationId":"get_users_notification_preferences","tags":["Identity"],"description":"Return the user's notification preferences, merged with defaults so newly-added keys always render.","x-cli":{"command":"auth notifications get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NotificationPreferencesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"patch_users_notification_preferences","tags":["Identity"],"description":"Partial update of notification preferences. Unknown keys → 400. Non-boolean values → 400.","x-cli":{"command":"auth notifications update"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email_on_comment_added":{"type":"boolean","description":"Send transactional email when someone comments on a doc/task/etc. owned by this user. Default: true."},"email_on_mention":{"type":"boolean","description":"Send email when this user is @mentioned in a comment or message. Default: true."},"email_on_task_assigned":{"type":"boolean","description":"Send email when a task is assigned to this user. Default: true."},"email_on_document_shared":{"type":"boolean","description":"Send email when a document, sheet, slide, wiki page, file, or calendar is shared with this user. Default: true."},"email_on_deal_won":{"type":"boolean","description":"Send email when a deal owned by this user is marked won. Default: true."},"email_on_deal_lost":{"type":"boolean","description":"Send email when a deal owned by this user is marked lost. Default: true."},"sound_on_new_notification":{"type":"boolean","description":"Client-only UX cue. Play a chime when a new notification arrives in this browser tab. Default: false."},"browser_push_on_new_notification":{"type":"boolean","description":"Client-only UX cue. Show an OS-level browser push notification. Default: false."},"tab_title_unread_count":{"type":"boolean","description":"Client-only UX cue. Update the tab title with `(N) Ambiguous` when the tab has unread notifications. Default: false."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NotificationPreferencesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/{id}/avatar":{"get":{"operationId":"get_users_id_avatar","tags":["Identity"],"description":"Public avatar proxy. Streams the user's avatar image from GCS so it renders inline in emails + presigned-URL-incompatible contexts (D071). Returns 204 when no avatar exists.","x-cli":{"hidden":true,"command":"auth avatar-proxy"},"parameters":[{"schema":{"type":"string","description":"User ID."},"required":true,"description":"User ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthBinaryBody"}}}}}}},"/api/auth/picker-workspaces":{"post":{"tags":["Auth"],"summary":"Fetch workspace details for the picker UI (requires picker session token)","operationId":"post_api_auth_picker_workspaces","responses":{"200":{"description":"Workspace details"},"401":{"description":"Invalid or missing token"},"403":{"description":"Token/account mismatch"}}}},"/api/auth/google/callback":{"get":{"operationId":"auth_google_callback","tags":["Auth"],"description":"OAuth 2.0 redirect target for native desktop Google sign-in. Exchanges the code for an id_token and bounces back to the login page to complete the session + native handoff.","x-cli":{"hidden":true,"command":"auth google-callback"},"responses":{"302":{"description":"Redirect to the login page (id_token in fragment) or an error"}}}},"/api/auth/logout":{"post":{"tags":["Auth"],"summary":"Logout — revoke the current JWT","operationId":"post_api_auth_logout","responses":{"200":{"description":"Token revoked"}}}},"/api/documents":{"get":{"operationId":"list_documents","tags":["Documents"],"description":"List the current user's documents. Optionally filter by type. Returns an array of documents with id, type, title, owner, and timestamps.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs list","output":{"columns":["id","type","title","updated_at"]}},"parameters":[{"schema":{"type":"string","enum":["doc","sheet","slide"],"description":"Filter by document type."},"required":false,"description":"Filter by document type.","name":"type","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Pass 'true' to return only starred documents."},"required":false,"description":"Pass 'true' to return only starred documents.","name":"starred","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"Alias for `limit`."},"required":false,"description":"Alias for `limit`.","name":"max_results","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_document","tags":["Documents"],"description":"Create a new document, spreadsheet, or presentation in the workspace. For docs, content should be Markdown. For sheets, content should be JSON. For slides, content should be Marp-flavored Markdown.","x-tool":{"expose":["all"]},"x-cli":{"command":"docs create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDocumentInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/dictionary":{"get":{"operationId":"get_document_dictionary","tags":["Documents"],"description":"Look up word definitions through a first-party dictionary proxy (the browser CSP blocks the external API directly). Returns the upstream dictionary entries for `word`, or an empty list when none are found.","x-cli":{"command":"docs dictionary"},"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"word","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentDictionaryResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/shared-with-me":{"get":{"operationId":"documents_shared_with_me","tags":["Documents"],"description":"Documents shared with the calling account through an explicit permission grant, across every workspace and every identity the account owns. Excludes documents the account owns. Each row names the workspace that shared it and the role the grant carries.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs shared-with-me","output":{"columns":["id","type","title","updated_at"]}},"parameters":[{"schema":{"type":"string","enum":["doc","sheet","slide"],"description":"Filter by document type."},"required":false,"description":"Filter by document type.","name":"type","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentsSharedWithMeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/trash":{"get":{"operationId":"documents_trash_list","tags":["Documents"],"description":"List trashed (soft-deleted) documents owned by the caller. Optional `?type=` filter.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs trash list"},"parameters":[{"schema":{"type":"string","enum":["doc","sheet","slide"],"description":"Filter by document type."},"required":false,"description":"Filter by document type.","name":"type","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/completions":{"post":{"operationId":"documents_completions","tags":["Documents"],"description":"Inline AI completions for the doc editor (ghost text). Streams `delta`, `done`, `error` SSE events.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs completions"},"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/restore":{"post":{"operationId":"documents_restore","tags":["Documents"],"description":"Restore a trashed document.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs restore"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/permanent":{"delete":{"operationId":"documents_permanent_delete","tags":["Documents"],"description":"Permanently delete a trashed document. Irreversible.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs permanent-delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/duplicate":{"post":{"operationId":"documents_duplicate","tags":["Documents"],"description":"Make a copy. Title becomes 'Copy of <orig>'. Visibility resets to restricted; labels/pin/star are NOT inherited. Requires viewer access on the source.","x-tool":{"expose":["all"]},"x-cli":{"command":"docs duplicate"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/export":{"post":{"operationId":"export_document","tags":["Documents"],"description":"Export a document, sheet, or slide to one of its supported standard formats. Sheets support xlsx, csv, tsv, and ods. Returns the file bytes with Content-Type and Content-Disposition attachment headers.","x-tool":{"expose":["all"],"annotations":{"readOnly":true}},"x-cli":{"command":"docs export","output":{"format":"raw"}},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentExportInput"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}":{"get":{"operationId":"get_document","tags":["Documents"],"description":"Get a single document by ID, including its full content and comments. If the user is currently viewing a document, use the document ID from the page context.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_document","tags":["Documents"],"description":"Edit an existing document inline. Read the document first (get_document), modify the content, then pass the full updated text — content replaces the entire body. Do NOT create a new document to edit; version history preserves prior states. Accepts Markdown or ProseMirror JSON (HTML tolerated but lossy — drops listed in `import_warnings`). Provide only the fields you want to change.","x-tool":{"expose":["all"]},"x-cli":{"command":"docs update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDocumentInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"documents_delete","tags":["Documents"],"description":"Soft-delete a document (move to trash). Owner only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/thumbnail":{"get":{"operationId":"documents_thumbnail","tags":["Documents"],"description":"Content-derived SVG thumbnail for doc/sheet/slide cards. Cached privately for 60 seconds.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"docs thumbnail"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/pin":{"patch":{"operationId":"documents_pin","tags":["Documents"],"description":"Toggle pinned state. Editor permission required (workspace-wide pin, not per-user).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs pin"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/star":{"post":{"operationId":"documents_star","tags":["Documents"],"description":"Toggle starred state. Viewer permission is sufficient. Body `{starred: bool}` is optional — omit to toggle.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs star"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StarInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/headers-footers":{"get":{"operationId":"get_document_headers_footers","tags":["Documents"],"description":"Get the headers and footers from a document. Returns default_header, first_page_header, default_footer, and first_page_footer as ProseMirror JSON nodes (or null if not set). Headers and footers appear on every page of exported documents (.docx, .pdf).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs headers-footers get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/HeadersFootersResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_document_headers_footers","tags":["Documents"],"description":"Set headers and footers on a document. Each field accepts a plain text string (auto-wrapped in a paragraph), a ProseMirror JSON node, or null to remove. Omit a field to leave unchanged. A document can have at most one default header, one first-page header, one default footer, and one first-page footer.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs headers-footers set"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeadersFootersInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/HeadersFootersResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/footnotes":{"get":{"operationId":"get_document_footnotes","tags":["Documents"],"description":"Get the footnotes from a document. Returns an array of footnotes, each with a footnoteId, body content (PM JSON), and the positions of inline references (footnoteRef nodes) in the body text.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs footnotes get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FootnotesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_document_footnotes","tags":["Documents"],"description":"Set footnote body content on a document. Replaces all existing footnoteBody nodes. Each footnote must have a footnoteId and either a text string (auto-wrapped in a paragraph) or a content array (PM JSON). To add inline footnote references in the body text, use update_document with PM JSON content containing footnoteRef nodes with matching footnoteIds.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs footnotes set"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FootnotesInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FootnotesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/page-style":{"get":{"operationId":"get_document_page_style","tags":["Documents"],"description":"Get the page-level formatting for a document: margins (in PT), page size (letter/A4/legal or custom {width, height} in PT), and orientation (portrait/landscape). Empty object means default formatting.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs page-style get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PageStyleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_document_page_style","tags":["Documents"],"description":"Set page-level formatting for a document: margins (PT), page size (letter/A4/legal or {width, height} in PT), orientation (portrait/landscape). 72 PT = 1 inch. These settings control export output (.docx, .pdf). Pass an empty object to reset to defaults.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs page-style update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageStyleInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PageStyleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/permissions":{"get":{"operationId":"documents_permissions_list","tags":["Documents"],"description":"List sharers (users + teams) plus pending invites for external recipients.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs permissions list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PermissionsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"documents_permissions_set","tags":["Documents"],"description":"Grant a permission to one principal: a user (`user_id`) or a team (`team_id`). Exactly one must be provided. Owner only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs permissions set"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPermissionInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SetPermissionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/permissions/{principalId}":{"delete":{"operationId":"documents_permission_remove","tags":["Documents"],"description":"Remove a permission. Use `?type=user|team` to target the right principal type.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs permissions remove"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"principalId","in":"path"},{"schema":{"type":"string","enum":["user","team"],"description":"Principal type; defaults to user."},"required":false,"description":"Principal type; defaults to user.","name":"type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/share-invite":{"post":{"operationId":"documents_share_invite","tags":["Documents"],"description":"Invite an external email to share the document. Creates a `pending_shares` row that's applied when the invitee accepts. Owner only.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"docs share-invite"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareInviteInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ShareInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/pending-shares/{pendingId}":{"delete":{"operationId":"documents_pending_share_revoke","tags":["Documents"],"description":"Revoke a pending invite that hasn't been accepted yet. Idempotent (returns ok regardless).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs pending-shares revoke"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"pendingId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RevokePendingShareResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/visibility":{"patch":{"operationId":"documents_visibility_update","tags":["Documents"],"description":"Toggle public-link visibility. Setting visibility to `restricted` or `workspace` clears any link expiry + password. Owner only.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"docs visibility"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisibilityInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VisibilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/revoke-link":{"post":{"operationId":"documents_revoke_link","tags":["Documents"],"description":"Revoke the public link — sets visibility to restricted, clears expiry, clears password. Owner only.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"docs revoke-link"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RevokeLinkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/transfer-ownership":{"post":{"operationId":"documents_transfer_ownership","tags":["Documents"],"description":"Transfer document ownership to another workspace member. The caller must be the current owner. The previous owner becomes an editor.","x-tool":{"expose":["all"]},"x-cli":{"command":"docs transfer-ownership"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentTransferOwnershipInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"new_owner_id":{"type":"string","format":"uuid"},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["success","new_owner_id"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/comments":{"get":{"operationId":"documents_comments_list","tags":["Documents"],"description":"List threaded comments. Response includes per-user `unread_count` (comments by other users since the requester's last `mark-read`, not resolved).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs comments list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CommentsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"documents_comments_create","tags":["Documents"],"description":"Add a threaded comment. Commenter permission required. `parent_id` makes it a reply; `anchor` carries CRDT-stable position info.","x-tool":{"expose":["all"]},"x-cli":{"command":"docs comments add"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCommentInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Comment"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/comments/mark-read":{"post":{"operationId":"documents_comments_mark_read","tags":["Documents"],"description":"Advance the requester's last-seen marker so the unread badge clears. Idempotent.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs comments mark-read"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MarkReadResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/comments/{commentId}":{"patch":{"operationId":"documents_comment_resolve","tags":["Documents"],"description":"Resolve or unresolve a comment. Editor permission required.","x-tool":{"expose":["all"]},"x-cli":{"command":"docs comments resolve"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"commentId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCommentInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Comment"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"documents_comment_delete","tags":["Documents"],"description":"Delete a comment. Author or document owner only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs comments delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"commentId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/comments/{commentId}/reactions":{"post":{"operationId":"documents_comment_reaction_add","tags":["Documents"],"description":"Add an emoji reaction to a comment. Idempotent per (user, emoji). Returns the comment's updated reaction aggregate.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs comments react"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"commentId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentReactionInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CommentReactionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/comments/{commentId}/reactions/{emoji}":{"delete":{"operationId":"documents_comment_reaction_remove","tags":["Documents"],"description":"Remove the caller's emoji reaction from a comment. Returns the comment's updated reaction aggregate.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs comments unreact"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"commentId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"emoji","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CommentReactionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/versions":{"get":{"operationId":"documents_versions_list","tags":["Documents"],"description":"List version snapshots, newest-first, cursor-paginated (default 50 per page). Walk via `next_cursor` until `has_more` is false.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs versions list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VersionsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"documents_versions_create","tags":["Documents"],"description":"Create a manual snapshot (forces past the 5-minute throttle).","x-tool":{"expose":["all"]},"x-cli":{"command":"docs versions create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVersionInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentVersion"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/versions/{versionId}":{"get":{"operationId":"documents_version_get","tags":["Documents"],"description":"Get a version's metadata + serialized content snapshot.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs versions get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"versionId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VersionDetail"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{document_id}/versions/{version_id}":{"patch":{"operationId":"rename_document_version","tags":["Documents"],"description":"Rename a version snapshot of a document. Useful for labeling meaningful versions (e.g., \"Pre-launch draft\", \"Board approved\"). Requires editor permission.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs versions update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"document_id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"version_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVersionInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentVersion"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_document_version","tags":["Documents"],"description":"Delete a version snapshot of a document. At least one version must always remain — returns an error if attempting to delete the last version. Requires editor permission.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs versions delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"document_id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"version_id","in":"path"}],"responses":{"204":{"description":"No content"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/versions/{versionId}/revert":{"post":{"operationId":"documents_version_revert","tags":["Documents"],"description":"Revert the document to a prior version. Force-snapshots current state first.","x-tool":{"expose":["all"]},"x-cli":{"command":"docs versions revert"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"versionId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"snapshot_id":{"type":["string","null"]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["success","snapshot_id"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/named-ranges":{"post":{"operationId":"docs_create_named_range","tags":["Documents"],"description":"Create a named range (template placeholder) on a document. Named ranges anchor to ProseMirror node positions and are used for template-based document generation. Use replace_named_range_content to fill a named range with content. Name must be alphanumeric + underscore, must not start with a digit (e.g., party_name, companyAddress).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs named-ranges create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNamedRangeInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentNamedRange"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"docs_list_named_ranges","tags":["Documents"],"description":"List all named ranges (template placeholders) defined on a document. Returns each range's name and its anchored node positions.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs named-ranges list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DocumentNamedRangesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/named-ranges/{name}":{"delete":{"operationId":"docs_delete_named_range","tags":["Documents"],"description":"Delete a named range (template placeholder) from a document by name. Names are unique per document.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs named-ranges delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"name","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]},"name":{"type":"string"},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["deleted","name"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/named-ranges/{name}/replace":{"post":{"operationId":"replace_named_range_content","tags":["Documents"],"description":"Replace all content within a named range with new content. Used for template-based document generation — define named ranges as placeholders, then call this to fill each one. The named range must have positional anchors (startNodeId/endNodeId). Content can be Markdown text or PM JSON. Returns 409 if the anchored nodes no longer exist (stale range after CRDT edits).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs named-ranges replace"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"name","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceNamedRangeInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ReplaceNamedRangeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/page-breaks":{"post":{"operationId":"insert_page_break","tags":["Documents"],"description":"Insert a page break into a document at a given position. Forces subsequent content to start on the next page in exported .docx and .pdf files. The page break is inserted as a block node between paragraphs.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs page-breaks insert"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsertPageBreakInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/InsertPageBreakResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/section-breaks":{"post":{"operationId":"insert_section_break","tags":["Documents"],"description":"Insert a section break into a document at a given position. Section breaks divide the document into sections that can have different formatting. A 'next_page' section break forces content to the next page (like a page break but marks a new section). A 'continuous' section break starts a new section on the same page.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs section-breaks insert"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsertSectionBreakInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/InsertSectionBreakResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/page-numbers":{"post":{"operationId":"insert_page_number","tags":["Documents"],"description":"Insert a page number placeholder into a document. The placeholder renders as the current page number in exported .docx and .pdf files. Commonly used inside headers or footers (e.g., 'Page X') but can also appear inline in the body text. The placeholder is inserted as an inline node within a paragraph.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs page-numbers insert"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsertPageNumberInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/InsertPageNumberResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/pinned-header-rows":{"post":{"operationId":"set_pinned_header_rows","tags":["Documents"],"description":"Set the number of pinned (repeating) header rows on a table in a document. Pinned header rows repeat on every printed page when the table spans multiple pages in exported .docx and .pdf files. Set to 0 to clear the pinned header rows attribute.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"docs pinned-header-rows set"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPinnedHeaderRowsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SetPinnedHeaderRowsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels":{"get":{"operationId":"list_channels","tags":["Chat"],"description":"List the user's chat channels. Returns channels with id, name, type (public/private/dm), description, member count, and creator info. Use this when the user asks to see their channels, find a specific channel by name, or when you need a channel ID to send a message.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels list","output":{"columns":["id","name","type","member_count"]}},"parameters":[{"schema":{"type":"string","description":"Pass '1' or 'true' to include archived channels."},"required":false,"description":"Pass '1' or 'true' to include archived channels.","name":"include_archived","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"chat_channel_create","tags":["Chat"],"description":"Create channel","x-tool":{"expose":["all"]},"x-cli":{"command":"chat channels create","output":{"successMessage":"Channel created: {id} — {name}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelMutationResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/mark-all-read":{"post":{"operationId":"mark_all_channels_read","tags":["Chat"],"description":"Mark all channels as read for the current user. Advances the read cursor in every channel the user is a member of to the latest message, clearing all unread badges at once. Use this when the user wants to dismiss all chat unreads (e.g. returning from vacation).","x-tool":{"expose":["all"]},"x-cli":{"command":"chat channels mark-all-read","output":{"format":"none","successMessage":"All channels marked as read."}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/last-messages":{"get":{"operationId":"chat_channel_last_messages","tags":["Chat"],"description":"Batch-fetch the latest message preview for multiple channels in one request. Pass `ids` as a comma-separated list of channel IDs (max 100). Returns one entry per channel the caller can read, each carrying its `channel_id`. Replaces per-channel `GET /messages?limit=1` calls so a DMs/channels list renders previews without an N+1 request fan-out.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat last-messages","output":{"columns":["channel_id","user_name","content","created_at"]}},"parameters":[{"schema":{"type":"string","description":"Comma-separated channel IDs (max 100) to fetch the latest message preview for."},"required":true,"description":"Comma-separated channel IDs (max 100) to fetch the latest message preview for.","name":"ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelLastMessagesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/messages/search":{"get":{"operationId":"search_chat_messages","tags":["Chat"],"description":"Full-text search messages across the user's accessible channels. Use this to find historical messages by keyword, phrase, or topic. Results include channel context (name and type) for each match.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat messages search","output":{"columns":["id","content","channel_name","author","created_at"]}},"parameters":[{"schema":{"type":"string","description":"Search text. Empty/missing returns no results."},"required":false,"description":"Search text. Empty/missing returns no results.","name":"q","in":"query"},{"schema":{"type":"string","description":"Restrict the search to one channel."},"required":false,"description":"Restrict the search to one channel.","name":"channel_id","in":"query"},{"schema":{"type":"string","description":"Max results (default 25, cap 50)."},"required":false,"description":"Max results (default 25, cap 50).","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelSearchResultsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/thread-activity/ack":{"post":{"operationId":"ack_thread_activity","tags":["Chat"],"description":"Acknowledge the Threads inbox on view-enter. Upserts thread_reads.last_read_at = now() for every subscribed thread that currently has an unread reply, so the projector recomputes chat.threads to 0 durably (the sidebar \"Threads\" badge clears and stays cleared across re-fetch). Does not move per-thread \"New\" watermarks in an open view.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat threads ack"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/thread-activity":{"get":{"operationId":"chat_thread_activity_list","tags":["Chat"],"description":"List thread-activity inbox for the current user. Row 5.1 (D204): powers the sidebar \"Threads\" inbox entry. Returns threads the user is involved in (authored parent OR replied), ordered by most recent reply desc, with `unread_reply_count` computed from `thread_reads.last_read_at`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat threads activity","output":{"columns":["thread_id","channel_name","last_reply_at","unread_reply_count"]}},"parameters":[{"schema":{"type":"string","description":"Max threads to return (default 30, cap 100)."},"required":false,"description":"Max threads to return (default 30, cap 100).","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ThreadActivityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/mentions-activity/ack":{"post":{"operationId":"ack_mentions_activity","tags":["Chat"],"description":"Acknowledge the Mentions & reactions inbox after it has been displayed. Marks the caller's unread chat mention notifications read and stamps users.mentions_acked_at, so the projector recomputes both chat.mentions and chat.reactions to 0 durably (the sidebar \"Mentions & reactions\" item un-bolds and stays cleared across re-fetch). Per-channel read cursors are untouched, so channel message unread counts are unaffected; a reaction that arrives after the ack re-bolds the item.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat mentions ack"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/saved-messages":{"get":{"operationId":"list_saved_messages","tags":["Chat"],"description":"List all messages the current user has saved (bookmarked) across all channels. Returns messages with saved_at timestamp, channel name, and channel type. Saved messages are private to the current user (unlike pinned messages, which are shared with the channel).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat saved list","output":{"columns":["id","content","channel_name","saved_at"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SavedMessagesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/scheduled-messages":{"get":{"operationId":"list_scheduled_messages","tags":["Chat"],"description":"List all pending scheduled messages for the current user across all channels. Returns each scheduled message with channel name/type and the scheduled_at timestamp. Use this to review what's queued to send later, or before updating/cancelling a scheduled message.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat scheduled list","output":{"columns":["id","content","channel_name","scheduled_at"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScheduledMessagesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/scheduled-messages/{message_id}":{"patch":{"operationId":"update_scheduled_message","tags":["Chat"],"description":"Edit the content or scheduled send time of a pending scheduled message before it's sent. Fails if the message has already been sent or cancelled. Use this when the user wants to fix a typo in a scheduled message or reschedule it.","x-tool":{"expose":["all"]},"x-cli":{"command":"chat scheduled update"},"parameters":[{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledMessageUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScheduledMessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"cancel_scheduled_message","tags":["Chat"],"description":"Cancel a pending scheduled message so it's never sent. Use this when the user says 'never mind' or changes their plan before the scheduled time.","x-tool":{"expose":["all"]},"x-cli":{"command":"chat scheduled cancel","confirm":true,"output":{"format":"none","successMessage":"Scheduled message {message_id} cancelled."}},"parameters":[{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/scheduled-messages/{message_id}/send-now":{"post":{"operationId":"send_scheduled_message_now","tags":["Chat"],"description":"Deliver a pending scheduled message immediately instead of waiting for its scheduled time. Flips the message to sent and fans it out to the channel right now. Fails if the message has already been sent or cancelled. Use this when the user wants to send a queued message without waiting.","x-tool":{"expose":["all"],"annotations":{"destructive":true}},"x-cli":{"command":"chat scheduled send-now"},"parameters":[{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScheduledMessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/emoji":{"get":{"operationId":"list_custom_emojis","tags":["Chat"],"description":"List all custom emojis uploaded to the current workspace. Returns each emoji with id, name (without colons), image URL, and creator info. Use this to discover what custom emojis are available before referring to them by name.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat emoji list","output":{"columns":["id","name","uploaded_by"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomEmojisListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"chat_emoji_create","tags":["Chat"],"description":"Upload custom emoji (multipart)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat emoji upload","output":{"successMessage":"Custom emoji created: :{name}:"}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomEmojiResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/emoji/fetch-url":{"post":{"operationId":"chat_emoji_fetch_url","tags":["Chat"],"description":"Fetch an image by URL for use as a custom emoji, returning the raw image bytes. Only http(s) URLs are allowed, internal/private addresses are blocked, and the image must be PNG, GIF, JPEG, or WebP under 256KB. Workspace-admin only.","x-tool":{"expose":[]},"x-cli":{"command":"chat emoji fetch-url","hidden":true,"output":{"format":"raw"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmojiFetchUrlInput"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/emoji/{id}/image":{"get":{"operationId":"chat_emoji_image","tags":["Chat"],"description":"Serve custom emoji image from GCS","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat emoji image","hidden":true,"output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/emoji/{emoji_id}":{"delete":{"operationId":"delete_custom_emoji","tags":["Chat"],"description":"Delete a custom emoji from the workspace. Use this when the user asks to remove or clean up a custom emoji. This does not remove existing reactions or messages that used the emoji — it only stops new usage.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat emoji delete","confirm":true,"output":{"format":"none","successMessage":"Custom emoji {emoji_id} deleted."}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"emoji_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/unfurl":{"post":{"operationId":"unfurl_link","tags":["Chat"],"description":"Fetch OpenGraph / link-preview metadata for a URL (title, description, image, site name, favicon). Useful for generating rich previews of shared links, or inspecting what a URL would look like when shared in chat. Only http(s) URLs are allowed, and internal/private addresses are blocked.","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true,"openWorld":true}},"x-cli":{"command":"chat unfurl"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnfurlInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UnfurlResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/status":{"get":{"operationId":"get_user_status","tags":["Chat"],"description":"Get the current user's active chat status (emoji + text) and DND-until timestamp. Use this before setting or clearing the status to know the current state.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat status get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UserStatusResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_user_status","tags":["Chat"],"description":"Set the current user's chat status — an emoji, short text (<=100 chars), and optional auto-clear timestamp. All fields are optional; pass null to clear a single field. Use this when the user says things like 'set my status to lunch until 1pm' or 'I'm on vacation'.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat status set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSetInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UserStatusResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"clear_user_status","tags":["Chat"],"description":"Clear the current user's status (emoji + text + expiresAt). Does NOT change DND — use set_user_dnd with until=null to clear DND separately.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat status clear","output":{"format":"none","successMessage":"Status cleared."}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UserStatusResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/dnd":{"put":{"operationId":"set_user_dnd","tags":["Chat"],"description":"Enable or disable Do-Not-Disturb for the current user. Pass an ISO-8601 timestamp in the future to snooze notifications until that time, or pass null to disable DND immediately. Use this when the user says 'mute me for an hour', 'DND until 5pm', or 'turn off DND'.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat dnd set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DndSetInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UserStatusResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/statuses":{"get":{"operationId":"list_user_statuses","tags":["Chat"],"description":"List active chat statuses (emoji + text + DND) for users in the workspace. Only returns users who currently have a non-null status or active DND. Useful for 'who's on vacation?', 'is anyone in meetings?', or similar presence queries.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat status list","output":{"columns":["userId","statusEmoji","statusText","dndUntil"]}},"parameters":[{"schema":{"type":"string","description":"Comma-separated user IDs to filter; omit for all users with an active status."},"required":false,"description":"Comma-separated user IDs to filter; omit for all users with an active status.","name":"user_ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/StatusesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/keywords":{"get":{"operationId":"get_notification_keywords","tags":["Chat"],"description":"Get the current user's notification keywords. The user receives a mention-style notification whenever any of these words appears in a message they can read.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat keywords get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatKeywordsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_notification_keywords","tags":["Chat"],"description":"Replace the current user's notification keyword list. Keywords are case-insensitive, whole-word, and capped at 20 entries (each up to 50 characters). Duplicates/empties are dropped. Use this when the user says 'alert me whenever someone mentions X' or 'stop notifying me about Y'.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat keywords set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeywordsSetInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatKeywordsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/archive":{"post":{"operationId":"chat_channel_archive","tags":["Chat"],"description":"Archive a channel (admin-only, not DMs). Archived channels stay queryable (history preserved) but are hidden from the default sidebar and reject writes (new messages, edits, reactions, pins, invites). Use unarchive to restore.","x-tool":{"expose":["all"]},"x-cli":{"command":"chat channels archive","confirm":true,"output":{"successMessage":"Channel {id} archived."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/unarchive":{"post":{"operationId":"chat_channel_unarchive","tags":["Chat"],"description":"Restore a previously archived channel.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels unarchive","output":{"successMessage":"Channel {id} unarchived."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/mute":{"post":{"operationId":"chat_channel_mute","tags":["Chat"],"description":"Mute a channel for the calling user only. Body (optional): { \"until\": \"2026-04-19T08:00:00Z\" }   ← timed mute (8h, 24h, etc.) { \"until\": null } / no body            ← indefinite mute { \"duration_ms\": 3600000 }             ← convenience: now + N ms Per-user — does not affect other channel members....","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels mute","output":{"successMessage":"Channel {id} muted."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMuteInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/unmute":{"post":{"operationId":"chat_channel_unmute","tags":["Chat"],"description":"Unmute a channel for the calling user. Idempotent: returns 200 even if the channel wasn't muted.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels unmute","output":{"format":"none","successMessage":"Channel {id} unmuted."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/star":{"post":{"operationId":"chat_channel_star","tags":["Chat"],"description":"Star a channel for the calling user. Starred channels surface in the sidebar 'Starred' section. Idempotent: re-starring an already-starred channel returns success.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels star","output":{"format":"none","successMessage":"Channel {id} starred."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"chat_channel_unstar","tags":["Chat"],"description":"Unstar a channel for the calling user. Idempotent: returns success even if the channel wasn't starred.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels unstar","output":{"format":"none","successMessage":"Channel {id} unstarred."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/notification-preference":{"patch":{"operationId":"chat_channel_notification_preference","tags":["Chat"],"description":"Update the calling user's notification preference for this channel. Controls how unread activity surfaces in the channel list: `unread_only` (default — bold the channel name when there are unread top-level messages), `all_messages` (numeric badge), `mentions_only` (badge only when @mentioned), `nothing` (no visual). Per-user — does not affect other channel members.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels notification-preference"},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelNotificationPreferenceInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelNotificationPreferenceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/join":{"post":{"operationId":"chat_channel_join","tags":["Chat"],"description":"Self-join a public channel (no body required)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels join","output":{"successMessage":"Joined channel {id}."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelDetailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/leave":{"post":{"operationId":"chat_channel_leave","tags":["Chat"],"description":"Leave a channel","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels leave","output":{"format":"none","successMessage":"Left channel {id}."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/read":{"post":{"operationId":"mark_channel_read","tags":["Chat"],"description":"Mark a channel as read up to a specific message. This clears the unread badge for the current user. Use this after the user has finished catching up on a channel, or programmatically to dismiss unread counts after the assistant reports on recent messages.","x-tool":{"expose":["all"]},"x-cli":{"command":"chat channels mark-read","output":{"format":"none","successMessage":"Channel {channel_id} marked as read."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelReadInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelReadCursorResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/unread":{"post":{"operationId":"mark_channel_unread","tags":["Chat"],"description":"Mark a channel as unread starting from a specific message. Moves the calling user's read cursor back to just before that message, so the channel shows an unread badge and the message becomes the unread boundary. Use this when the user wants to revisit a conversation later.","x-tool":{"expose":["all"]},"x-cli":{"command":"chat channels mark-unread","output":{"format":"none","successMessage":"Channel {channel_id} marked as unread."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelReadInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/read-receipts":{"get":{"operationId":"get_channel_read_receipts","tags":["Chat"],"description":"Get per-member read positions for a channel — who has read up to which message. Useful for reporting on whether an announcement has been seen by everyone.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels read-receipts","output":{"format":"table","columns":["user_id","display_name","last_read_message_id","last_read_at"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ReadReceiptsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/pins":{"get":{"operationId":"list_pinned_messages","tags":["Chat"],"description":"List all pinned messages in a channel. Pinned messages are highlighted by members for ongoing reference (announcements, canonical links, etc.). Returns messages in newest-pin-first order.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat pins list","output":{"columns":["id","content","pinned_by","pinned_at"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PinnedMessagesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/saved-ids":{"get":{"operationId":"chat_saved_ids_list","tags":["Chat"],"description":"Get saved message IDs for a channel (for UI bookmarked state)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat saved ids","hidden":true},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SavedMessageIdsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/members":{"post":{"operationId":"chat_channel_members_add","tags":["Chat"],"description":"Add member(s) or a group","x-tool":{"expose":["all"]},"x-cli":{"command":"chat members add","output":{"successMessage":"Member(s) added to channel {id}."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMembersAddInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelMembersAddResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/members/{userId}":{"delete":{"operationId":"chat_channel_member_remove","tags":["Chat"],"description":"Remove member","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat members remove","confirm":true,"output":{"format":"none","successMessage":"Member {userId} removed from channel {id}."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"userId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/members/{user_id}":{"patch":{"operationId":"update_channel_member_role","tags":["Chat"],"description":"Change a channel member's role to 'admin' or 'member'. Requires channel admin privileges. Use this when the user asks to promote or demote a member in a channel.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat members update-role","output":{"format":"none","successMessage":"Role updated for {user_id} in channel {channel_id}."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"user_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMemberUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/groups/{groupId}":{"delete":{"operationId":"chat_channel_group_remove","tags":["Chat"],"description":"Remove a group from channel (clean up fan-out rows)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat members remove-group","confirm":true,"output":{"format":"none","successMessage":"Group {groupId} removed from channel {id}."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"groupId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/messages":{"get":{"operationId":"get_channel_messages","tags":["Chat"],"description":"Get recent messages from a chat channel. Returns messages with id, content (Markdown), author info, reactions, thread reply count, and timestamps. Use this when the user asks to read messages, catch up on a channel, or find a specific conversation. If the user is currently viewing a channel, use the channel ID from the page context. Messages are returned in reverse chronological order (newest first).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat messages list","output":{"columns":["id","content","author","created_at"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"type":"string","description":"Max messages to return (default 50, cap 100)."},"required":false,"description":"Max messages to return (default 50, cap 100).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Offset for legacy pagination."},"required":false,"description":"Offset for legacy pagination.","name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Message ID — return messages older than this message."},"required":false,"description":"Message ID — return messages older than this message.","name":"before","in":"query"},{"schema":{"type":"string","description":"Message ID — return the page of messages *newer* than this message (the forward twin of `before`), oldest-of-the-page first in the same newest-first envelope. Reports `has_more_newer`. Ignored when `around` is also set. An ID outside this channel is ignored and the newest page is returned."},"required":false,"description":"Message ID — return the page of messages *newer* than this message (the forward twin of `before`), oldest-of-the-page first in the same newest-first envelope. Reports `has_more_newer`. Ignored when `around` is also set. An ID outside this channel is ignored and the newest page is returned.","name":"after","in":"query"},{"schema":{"type":"string","description":"ISO timestamp — return messages created before this instant."},"required":false,"description":"ISO timestamp — return messages created before this instant.","name":"before_date","in":"query"},{"schema":{"type":"string","description":"Message ID — return a window centred on this message (roughly half the limit on each side) instead of the newest page. Takes precedence over cursor/before/before_date. An ID outside this channel is ignored and the newest page is returned."},"required":false,"description":"Message ID — return a window centred on this message (roughly half the limit on each side) instead of the newest page. Takes precedence over cursor/before/before_date. An ID outside this channel is ignored and the newest page is returned.","name":"around","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Pass 'true' to include soft-deleted messages (rendered as tombstones)."},"required":false,"description":"Pass 'true' to include soft-deleted messages (rendered as tombstones).","name":"show_deleted","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelMessagesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"send_message","tags":["Chat"],"description":"Send a message in a chat channel. The content is written in Markdown and supports @mentions, code blocks, links, and other rich formatting. Use this when the user asks to send a chat message, post in a channel, reply in a thread, or communicate with a teammate via chat. If the user is currently viewing a channel, use the channel ID from the page context. To reply in a thread, provide the thread_id of the parent message.","x-tool":{"expose":["all"],"annotations":{"destructive":true}},"x-cli":{"command":"chat messages send","output":{"successMessage":"Message sent to channel {channel_id}."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMessageCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelMessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/messages/{message_id}":{"get":{"operationId":"chat_message_get","tags":["Chat"],"description":"Get a single message by ID. Used for permalink resolution when the message is a thread reply not present in the main timeline.","x-cli":{"command":"chat messages get"},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelMessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"chat_message_update","tags":["Chat"],"description":"Edit message or pin/unpin","x-tool":{"expose":["all"]},"x-cli":{"command":"chat messages update"},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMessageUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelMessageUpdateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/messages/{msgId}":{"delete":{"operationId":"chat_message_delete","tags":["Chat"],"description":"Delete message","x-tool":{"expose":["all"]},"x-cli":{"command":"chat messages delete","confirm":true,"output":{"format":"none","successMessage":"Message {msgId} deleted."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"msgId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/messages/bulk-delete":{"post":{"operationId":"bulk_delete_messages","tags":["Chat"],"description":"Soft-delete up to 100 messages in a channel. Deletes only the IDs the caller may delete (own messages, or any message when the caller is a channel admin); every other ID returns in `rejected`. Emits one bulk `message.deleted` event, never one per message.","x-tool":{"expose":["all"],"annotations":{"destructive":true}},"x-cli":{"command":"chat messages bulk-delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelBulkDeleteInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelBulkDeleteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/messages/{message_id}/readers":{"get":{"operationId":"get_message_readers","tags":["Chat"],"description":"List the users who have read a specific message (i.e. whose read-cursor is at or past this message). Use this to check whether a message (e.g. an important announcement) has been seen by specific people.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat messages readers","output":{"format":"table","columns":["user_id","display_name","read_at"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MessageReadersResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/messages/{message_id}/save":{"post":{"operationId":"save_message","tags":["Chat"],"description":"Save (bookmark) a chat message for the current user to revisit later. Idempotent — saving an already-saved message is a no-op. Use this when the user asks to bookmark a message or remind themselves of something.","x-tool":{"expose":["all"]},"x-cli":{"command":"chat saved save","output":{"format":"none","successMessage":"Message {message_id} saved."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"unsave_message","tags":["Chat"],"description":"Remove a saved (bookmarked) message from the user's saved list. The message itself is untouched; only the personal bookmark is deleted.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat saved unsave","output":{"format":"none","successMessage":"Message {message_id} unsaved."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/messages/{message_id}/remind":{"post":{"operationId":"set_reminder","tags":["Chat"],"description":"Set a reminder on a chat message. Auto-saves the message if not already saved. The reminder fires a notification at the specified time. Accepts ISO 8601 datetime string; must be in the future.","x-tool":{"expose":["all"]},"x-cli":{"command":"chat remind set","output":{"format":"none","successMessage":"Reminder set for {remind_at}."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatReminderSetInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatReminderSetResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"clear_reminder","tags":["Chat"],"description":"Clear a pending reminder on a saved message. The message stays saved; only the reminder is removed.","x-tool":{"expose":["all"]},"x-cli":{"command":"chat remind clear","output":{"format":"none","successMessage":"Reminder cleared."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"snooze_reminder","tags":["Chat"],"description":"Re-snooze an existing saved message by updating its remind_at time. Resets reminded to false so the scheduler picks it up again. Accepts ISO 8601 datetime string; must be in the future.","x-tool":{"expose":["all"]},"x-cli":{"command":"chat remind snooze","output":{"format":"none","successMessage":"Reminder snoozed until {remind_at}."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatReminderSetInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatReminderSnoozeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/messages/{msgId}/reactions":{"post":{"operationId":"chat_message_reaction_add","tags":["Chat"],"description":"Add reaction","x-tool":{"expose":["all"]},"x-cli":{"command":"chat reactions add"},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"msgId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatReactionInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelMessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/messages/{msgId}/reactions/{emoji}":{"delete":{"operationId":"chat_message_reaction_remove","tags":["Chat"],"description":"Remove reaction","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat reactions remove"},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"msgId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"emoji","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelMessageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/messages/{msgId}/thread":{"get":{"operationId":"chat_thread_get","tags":["Chat"],"description":"Get thread replies","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat threads get","output":{"format":"table","columns":["id","content","author","created_at"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"msgId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ThreadResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/messages/{message_id}/thread/read":{"post":{"operationId":"mark_thread_read","tags":["Chat"],"description":"Mark a thread as fully read up to the latest reply. Use this after the user has finished catching up on a thread, or when you want to programmatically dismiss unread reply counts for a specific thread.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat threads mark-read","output":{"format":"none","successMessage":"Thread {message_id} marked as read."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{channel_id}/messages/{message_id}/thread/unread":{"post":{"operationId":"mark_thread_unread","tags":["Chat"],"description":"Mark a thread as unread so it reappears in the threads inbox with an unread badge. Use this when the user wants to come back to a thread later.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat threads mark-unread","output":{"format":"none","successMessage":"Thread {message_id} marked as unread."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"channel_id","in":"path"},{"schema":{"$ref":"#/components/schemas/MessageId"},"required":true,"name":"message_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/reactions-inbox":{"get":{"operationId":"chat_reactions_inbox","tags":["Chat"],"description":"Messages authored by the caller that carry reactions from other users. Powers the Mentions & Reactions inbox.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat inbox reactions","output":{"format":"table"}},"parameters":[{"schema":{"type":"string","description":"Max messages to return (default 50, cap 100)."},"required":false,"description":"Max messages to return (default 50, cap 100).","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelSearchResultsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/mentions-inbox":{"get":{"operationId":"chat_mentions_inbox","tags":["Chat"],"description":"Messages from other users that @-mention the caller. Powers the Mentions tab.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat inbox mentions","output":{"format":"table"}},"parameters":[{"schema":{"type":"string","description":"Max messages to return (default 50, cap 100)."},"required":false,"description":"Max messages to return (default 50, cap 100).","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelSearchResultsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/preferences":{"get":{"operationId":"chat_preferences","tags":["Chat"],"description":"Workspace-level chat preferences readable by any authenticated member (default_reactions).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat preferences","output":{"format":"raw"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatPreferencesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}/notification-prefs":{"patch":{"operationId":"chat_channel_notification_prefs","tags":["Chat"],"description":"Update the caller's per-channel notification preferences (unread_display: count | dot | since_visit).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels set-unread-display","output":{"format":"raw"}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelNotificationPrefsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelNotificationPrefsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/channels/{id}":{"get":{"operationId":"chat_channel_get","tags":["Chat"],"description":"Get a specific channel by UUID, with members.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels get"},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelDetailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"chat_channel_update","tags":["Chat"],"description":"Update channel","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels update","output":{"successMessage":"Channel {id} updated."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChannelMutationResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"chat_channel_delete","tags":["Chat"],"description":"Delete channel","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat channels delete","confirm":true,"output":{"format":"none","successMessage":"Channel {id} deleted."}},"parameters":[{"schema":{"$ref":"#/components/schemas/ChannelId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/polls":{"post":{"operationId":"poll_create","tags":["Chat"],"description":"Create a poll in a channel. Creator must be a channel member.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat polls create","output":{"format":"raw"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePollInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PollResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/polls/by-message/{message_id}":{"get":{"operationId":"poll_get_by_message","tags":["Chat"],"description":"Poll results for the poll attached to a chat message.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat polls by-message","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"message_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PollResults"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/polls/{poll_id}":{"get":{"operationId":"poll_get","tags":["Chat"],"description":"Poll details (question, options, the caller's votes).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat polls get","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"poll_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PollResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"poll_delete","tags":["Chat"],"description":"Delete a poll (creator or channel admin).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat polls delete","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"poll_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PollDeleteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/polls/{poll_id}/vote":{"post":{"operationId":"poll_vote","tags":["Chat"],"description":"Cast a vote for a poll option.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat polls vote","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"poll_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollVoteInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PollResults"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/polls/{poll_id}/unvote":{"post":{"operationId":"poll_unvote","tags":["Chat"],"description":"Remove the caller's vote for a poll option.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat polls unvote","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"poll_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollVoteInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PollResults"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/polls/{poll_id}/results":{"get":{"operationId":"poll_results","tags":["Chat"],"description":"Tallied poll results (respects anonymity).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat polls results","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"poll_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PollResults"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/polls/{poll_id}/close":{"post":{"operationId":"poll_close","tags":["Chat"],"description":"Close a poll to further voting (creator or channel admin).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"chat polls close","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"poll_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PollResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/file-requests/{token}/meta":{"get":{"operationId":"drive_file_request_meta","tags":["Drive"],"description":"What the anonymous upload page may state before an upload: the owner's published title and instructions, and the remaining bounds. Returns no Drive, folder, workspace, or owner identifier, and no detail of anything already uploaded.","x-cli":{"command":"drive file-requests meta","hidden":true},"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileRequestPublicMeta"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/file-requests/{token}/upload":{"post":{"operationId":"drive_file_request_upload","tags":["Drive"],"description":"Upload one file through a write-only file-request capability. No authentication is required, and the response exposes no Drive resource identifier.","x-cli":{"command":"drive file-requests upload","hidden":true},"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"token","in":"path"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/DriveFileRequestUploadInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileRequestUploadResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive":{"get":{"operationId":"list_files","tags":["Drive"],"description":"List files and folders in the user's Drive. Returns items with id, name, mime_type, size_bytes, is_folder, parent_folder_id, owner info, and timestamps. Use this when the user asks to see their files, browse a folder, find a specific file, or check what's in Drive. If the user is currently viewing Drive, use context for the current folder.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive list"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"parent_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"section","in":"query"},{"schema":{"type":"string"},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"owner_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/folders":{"get":{"operationId":"list_drive_folders","tags":["Drive"],"description":"List only folders (not files) in Drive — useful for folder pickers. Pass root to scope the listing to My Drive, shared drives, or Shared with me.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive folder list"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"parent_id","in":"query"},{"schema":{"type":"string","enum":["my_drive","shared_drives","shared_with_me"],"description":"Omit for the legacy merged listing; supply to scope results to one root."},"required":false,"description":"Omit for the legacy merged listing; supply to scope results to one root.","name":"root","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":100,"description":"Name filter. Spans every root at any depth, so parent_id and root are ignored."},"required":false,"description":"Name filter. Spans every root at any depth, so parent_id and root are ignored.","name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_folder","tags":["Drive"],"description":"Create a new folder in Drive. Returns the created folder with id, name, and path. Use this when the user asks to create, make, or add a new folder for organizing files. Supports nested folders via parent_folder_id.","x-tool":{"expose":["all"]},"x-cli":{"command":"drive folder create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveCreateFolderInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/folders/{id}/ancestors":{"get":{"operationId":"drive_folder_ancestors","tags":["Drive"],"description":"Breadcrumb chain (root → leaf) for a folder. Powers breadcrumb hydration on deep-link reloads. Viewer permission is sufficient.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive folder ancestors"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFolderAncestorsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/folders/{folderId}/file-requests":{"post":{"operationId":"drive_file_request_create","tags":["Drive"],"description":"Create a revocable, write-only public file request for a folder. The capability token is returned only in this response.","x-tool":{"expose":["all"],"annotations":{"openWorld":true}},"x-cli":{"command":"drive file-requests create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"folderId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveCreateFileRequestInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileRequestCreated"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"drive_file_requests_list","tags":["Drive"],"description":"List the caller's file requests for one owned Drive folder.","x-tool":{"expose":["all"]},"x-cli":{"command":"drive file-requests list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"folderId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileRequestListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/folders/{folderId}/file-requests/{requestId}/remint":{"post":{"operationId":"drive_file_request_remint","tags":["Drive"],"description":"Replace a live file request's capability token without changing its request identity, limits, upload progress, or expiry. The previous token stops working immediately and the replacement token is returned only in this response.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"drive file-requests remint","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"folderId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"requestId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveRemintFileRequestInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileRequestCreated"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/folders/{folderId}/file-requests/{requestId}/revoke":{"post":{"operationId":"drive_file_request_revoke","tags":["Drive"],"description":"Revoke a folder's public file request immediately.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"drive file-requests revoke","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"folderId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"requestId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileRequest"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/upload":{"post":{"operationId":"drive_file_upload_init","tags":["Drive"],"description":"Initiate a file upload. Reserves a Drive row + storage key and returns a short-lived presigned PUT URL the client uploads the bytes to.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"drive upload init"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveUploadInitInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileWithUploadUrl"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/upload-proxy":{"post":{"operationId":"drive_file_upload_proxy","tags":["Drive"],"description":"Server-relayed upload (multipart `file` field). Used by clients when GCS presigned URLs hit `SignatureDoesNotMatch`. Body is `multipart/form-data` with a `file` field and an optional `parent_folder_id`.","x-cli":{"hidden":true,"command":"drive upload proxy"},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/confirm-upload":{"post":{"operationId":"drive_file_confirm_upload","tags":["Drive"],"description":"Confirm a presigned upload completed successfully. Verifies the blob exists in storage, marks the file as confirmed, and emits the upload event. Idempotent — confirming an already-confirmed file returns it unchanged.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive upload confirm"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/storage":{"get":{"operationId":"get_drive_storage","tags":["Drive"],"description":"Get Drive storage usage.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive storage"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveStorageUsage"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/storage/breakdown":{"get":{"operationId":"get_drive_storage_breakdown","tags":["Drive"],"description":"Storage breakdown by file type.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive storage breakdown"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveStorageBreakdown"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/recent":{"get":{"operationId":"drive_files_recent","tags":["Drive"],"description":"Recently used files for the current user — opened in the last 30 days OR created in the last 24 hours. Sorted by `max(createdAt, lastViewedAt)` desc.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive recent"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/starred":{"get":{"operationId":"drive_files_starred","tags":["Drive"],"description":"Files the current user has starred.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive starred"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/shared-with-me":{"get":{"operationId":"drive_files_shared_with_me","tags":["Drive"],"description":"Files shared with the current user via an explicit `file_permissions` row. Excludes files the user owns.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-with-me"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/tags":{"get":{"operationId":"drive_tags_list","tags":["Drive"],"description":"Current user's tag catalog (D117). Each tag carries name, color, and sort order.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive tag list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveTagListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"drive_tag_create","tags":["Drive"],"description":"Create a new tag in the user's catalog.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive tag create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveCreateTagInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveTag"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/tags/{id}":{"patch":{"operationId":"drive_tag_update","tags":["Drive"],"description":"Rename, recolor, or reorder a tag.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive tag update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveUpdateTagInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveTag"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"drive_tag_delete","tags":["Drive"],"description":"Delete a tag (cascades to all file assignments).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive tag delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveOkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/tags/{id}/files":{"get":{"operationId":"drive_tag_files_list","tags":["Drive"],"description":"List files tagged with the given tag.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive tag files"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/batch":{"get":{"operationId":"batch_get_files","tags":["Drive"],"description":"Batch-fetch up to 50 files by ID. Powers drive:// embed hydration in Chat/Docs/Wiki/CRM.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"drive batch get"},"parameters":[{"schema":{"type":"string","description":"Comma-separated file IDs (max 50)."},"required":false,"description":"Comma-separated file IDs (max 50).","name":"ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/batch/permissions":{"get":{"operationId":"batch_file_permissions","tags":["Drive"],"description":"Batch-fetch permissions for up to 50 files by ID. Returns a map of file_id → permissions array.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive batch permissions"},"parameters":[{"schema":{"type":"string","description":"Comma-separated file IDs (max 50)."},"required":false,"description":"Comma-separated file IDs (max 50).","name":"file_ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveBatchPermissionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/batch/move":{"post":{"operationId":"bulk_move_files","tags":["Drive"],"description":"Move multiple files to a folder (max 100).","x-tool":{"expose":["all"]},"x-cli":{"command":"drive batch move"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveBatchMoveInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveBatchMoveResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/batch/copy":{"post":{"operationId":"bulk_copy_files","tags":["Drive"],"description":"Copy multiple files to a folder (max 100).","x-tool":{"expose":["all"]},"x-cli":{"command":"drive batch copy"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveBatchCopyInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveBatchCopyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/trash":{"get":{"operationId":"list_trashed_files","tags":["Drive"],"description":"List all trashed files in the user's Drive. Returns paginated results with id, name, mime_type, size, timestamps. Use this when the user asks to see their trash or wants to restore a file.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive trash list"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"empty_trash","tags":["Drive"],"description":"Permanently delete all trashed files in the user's Drive. Irreversible — confirm with user first. Returns the number of files deleted.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive trash empty","confirm":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveEmptyTrashResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/shared-drives":{"get":{"operationId":"list_shared_drives","tags":["Drive"],"description":"List shared drives user is a member of.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDriveListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_shared_drive","tags":["Drive"],"description":"Create a shared drive. Creator becomes a manager.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSharedDriveInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDrive"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/shared-drives/{driveId}":{"get":{"operationId":"get_shared_drive","tags":["Drive"],"description":"Get shared drive details.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDrive"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_shared_drive","tags":["Drive"],"description":"Update a shared drive (manager-only).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSharedDriveInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDrive"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_shared_drive","tags":["Drive"],"description":"Delete a shared drive (destructive, manager-only).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive delete","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/shared-drives/{driveId}/members":{"get":{"operationId":"list_shared_drive_members","tags":["Drive"],"description":"List shared drive members.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive members"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDriveMembersResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"add_shared_drive_member","tags":["Drive"],"description":"Add a member (manager-only).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive member add"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSharedDriveMemberInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDriveMembershipResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/shared-drives/{driveId}/members/{userId}":{"patch":{"operationId":"update_shared_drive_member","tags":["Drive"],"description":"Update a member role (manager-only).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive member update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"},{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"userId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSharedDriveMemberInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDriveMembershipResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"remove_shared_drive_member","tags":["Drive"],"description":"Remove a shared drive member (manager-only; cannot remove last manager).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive member remove"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"},{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"userId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RemoveSharedDriveMemberResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/shared-drives/{driveId}/files":{"get":{"operationId":"list_shared_drive_files","tags":["Drive"],"description":"List files in a shared drive.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive files"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"parent_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDriveFilesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/shared-drives/{driveId}/folders":{"post":{"operationId":"drive_shared_drive_folder_create","tags":["Drive"],"description":"Create a folder inside a shared drive. Requires contributor+ on the drive. Pass `parent_folder_id` to nest.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive shared-drive folder create"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSharedDriveFolderInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/shared-drives/{driveId}/upload":{"post":{"operationId":"drive_shared_drive_upload","tags":["Drive"],"description":"Server-relayed upload to a shared drive (multipart `file` field). Requires contributor+ on the drive.","x-cli":{"hidden":true,"command":"drive shared-drive upload"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"driveId","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedDriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/download":{"get":{"operationId":"drive_file_download_url","tags":["Drive"],"description":"Get a short-lived presigned URL for downloading the file body.","x-cli":{"hidden":true,"command":"drive download"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveDownloadResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/view":{"get":{"operationId":"drive_file_view_url","tags":["Drive"],"description":"Get a short-lived presigned URL for inline viewing (images, PDFs, etc.).","x-cli":{"hidden":true,"command":"drive view"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveViewResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"drive_file_view_record","tags":["Drive"],"description":"Stamp `last_viewed_at` for the file so it appears in the Recent sidebar. Folders are no-ops.","x-cli":{"hidden":true,"command":"drive view record"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveOkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/star":{"post":{"operationId":"drive_file_star","tags":["Drive"],"description":"Toggle or set the starred flag on a file. Pass `{ starred: boolean }` or omit to toggle.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive star"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveStarInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/tags":{"post":{"operationId":"drive_file_tag_attach","tags":["Drive"],"description":"Attach a tag to a file. Owner-only and idempotent.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive file tag"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveTagAttachInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/tags/{tagId}":{"delete":{"operationId":"drive_file_tag_detach","tags":["Drive"],"description":"Detach a tag from a file. Owner-only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive file untag"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"tagId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/content":{"get":{"operationId":"drive_file_content","tags":["Drive"],"description":"Proxy file bytes from GCS through the API. Returns raw binary. Pass `?download=true` for `Content-Disposition: attachment`; default is inline. Content retrieval failures can return 503/504 via raw Response because those statuses are outside the typed contract error-code enum.","x-cli":{"hidden":true,"command":"drive content"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"download","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveBinaryBody"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/permissions":{"get":{"operationId":"list_file_permissions","tags":["Drive"],"description":"List users with access to a file.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive permissions list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFilePermissionsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"set_file_permission","tags":["Drive"],"description":"Grant permission on a file (owner only). Provide exactly one of user_id or team_id.","x-tool":{"expose":["all"]},"x-cli":{"command":"drive permissions set"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveSetFilePermissionInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveSetFilePermissionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/permissions/{userId}":{"patch":{"operationId":"update_file_permission","tags":["Drive"],"description":"Update a user's permission role on a file in-place (owner-only).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive permissions update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"userId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveUpdateFilePermissionInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveUpdateFilePermissionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/permissions/{principalId}":{"delete":{"operationId":"remove_file_permission","tags":["Drive"],"description":"Remove a permission from a file. Specify the principal_id and principal_type.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive permissions remove"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"principalId","in":"path"},{"schema":{"type":"string","enum":["user","team"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveRemovePermissionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/comments":{"get":{"operationId":"list_file_comments","tags":["Drive"],"description":"List threaded comments on a file. `anchor` is always a discriminated variant: `{kind:\"file\"}` for a file-level thread, `{kind:\"region\", page, x, y, w, h}` for one bound to a region of the rendered page (unit fractions).","x-cli":{"command":"drive comments list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveCommentListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_file_comment","tags":["Drive"],"description":"Add a comment or threaded reply to a file. Commenter permission required. `anchor` is a discriminated variant: omit it or send `{kind:\"file\"}` for a file-level thread; send `{kind:\"region\", page, x, y, w, h}` (unit fractions) to bind it to a region of the preview. On a region, `kind` may be omitted and is inferred. The response always carries the discriminated form.","x-cli":{"command":"drive comments add"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveCommentCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveComment"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/comments/{commentId}":{"patch":{"operationId":"update_file_comment","tags":["Drive"],"description":"Resolve or unresolve a file comment (editor+), or edit its content (author only).","x-cli":{"command":"drive comments update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"commentId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveCommentUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveComment"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_file_comment","tags":["Drive"],"description":"Delete a file comment and its replies. Author or file owner only.","x-cli":{"command":"drive comments delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"commentId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveCommentDeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/extract-text":{"post":{"operationId":"drive_file_extract_text","tags":["Drive"],"description":"Extract the text of a file on demand (OCR). A premium action: the workspace meter is debited before the vendor call, so an exhausted meter aborts with 429 having spent nothing. Re-running rewrites the stored extract and never touches file metadata.","x-cli":{"command":"drive extract-text"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileTextExtract"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/visibility":{"patch":{"operationId":"update_file_visibility","tags":["Drive"],"description":"Change file visibility (restricted|workspace|link|public). Owner-only.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"drive visibility"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveVisibilityInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveVisibilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/revoke-link":{"post":{"operationId":"revoke_file_link","tags":["Drive"],"description":"Revoke active public link (owner-only).","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"drive revoke-link"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveVisibilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/share-invite":{"post":{"operationId":"create_file_share_invite","tags":["Drive"],"description":"Invite an external email to a file.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"drive share-invite"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveShareInviteInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveShareInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/restore":{"post":{"operationId":"restore_file","tags":["Drive"],"description":"Restore a file from trash.","x-tool":{"expose":["all"]},"x-cli":{"command":"drive restore"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveRestoreFileResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/permanent":{"delete":{"operationId":"permanent_delete_file","tags":["Drive"],"description":"Permanently delete a file. Irreversible — confirm with user first.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive delete permanent","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/export":{"post":{"operationId":"export_drive_file","tags":["Drive"],"description":"Export a workspace document (Doc, Sheet, or Slide) to a file format via its Drive ID. Docs support: docx, pdf, html, md. Sheets support: xlsx, csv. Slides support: pptx, pdf, html. Binary Drive files (images, archives, etc.) cannot be exported — use download instead.","x-tool":{"expose":["all"],"annotations":{"readOnly":true}},"x-cli":{"hidden":true,"command":"drive export"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveExportInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveBinaryBody"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}":{"get":{"operationId":"get_file_info","tags":["Drive"],"description":"Get detailed information about a file or folder in Drive. Returns id, name, mime_type, size_bytes, storage_key, owner info, parent folder, and timestamps. Use this when the user asks about a specific file's details, size, type, or location. If the user is currently viewing a file in Drive, use the resource ID from page context.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"drive get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"drive_file_update","tags":["Drive"],"description":"Rename, move, or star/unstar a file. Requires edit access — the owner or an editor/owner share.","x-tool":{"expose":["all"]},"x-cli":{"command":"drive update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveUpdateFileInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_file","tags":["Drive"],"description":"Delete a file or folder from Drive. This is a destructive action — always confirm with the user before executing. Deleting a folder also deletes all files inside it. Use this when the user explicitly asks to delete, remove, or trash a file or folder.","x-tool":{"expose":["all"]},"x-cli":{"command":"drive trash"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/versions":{"post":{"operationId":"drive_file_version_create","tags":["Drive"],"description":"Upload replacement bytes for an existing file. The current bytes become a prior version and the file points at the new upload. Body is `multipart/form-data` with a `file` field.","x-cli":{"hidden":true,"command":"drive versions create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"drive_file_versions_list","tags":["Drive"],"description":"List a file's prior versions, newest first. Each entry carries size, MIME type, uploader, and upload time. The file's current bytes are not a version and never appear here.","x-cli":{"hidden":true,"command":"drive versions list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFileVersionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/versions/{versionId}":{"get":{"operationId":"drive_file_version_get","tags":["Drive"],"description":"Fetch one prior version's bytes. Redirects to a short-lived signed URL when storage is signed, otherwise proxies the bytes. A version whose stored object is gone returns 404 `VERSION_CONTENT_NOT_FOUND`, never a 500.","x-cli":{"hidden":true,"command":"drive versions get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"versionId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriveBinaryBody"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"drive_file_version_delete","tags":["Drive"],"description":"Permanently delete one prior version and its stored bytes. This is destructive and unrecoverable — always confirm with the user first. The file's current version is never deletable here (400).","x-cli":{"hidden":true,"command":"drive versions delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"versionId","in":"path"}],"responses":{"204":{"description":"No content"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/drive/{id}/versions/{versionId}/restore":{"post":{"operationId":"drive_file_version_restore","tags":["Drive"],"description":"Make a prior version the file's current bytes. The bytes being replaced are appended as a new prior version, and the restored version stops being one — so a restore loses nothing and never leaves a stored object counted twice.","x-cli":{"hidden":true,"command":"drive versions restore"},"parameters":[{"schema":{"$ref":"#/components/schemas/DriveItemId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"versionId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DriveFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/external/auth-url":{"get":{"operationId":"mail_external_auth_url","tags":["Mail"],"description":"Start connected-mailbox (Gmail) OAuth — returns the consent URL.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"mail external auth-url"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalMailAuthUrlResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/external/callback":{"get":{"operationId":"mail_external_callback","tags":["Mail"],"description":"Gmail OAuth callback (browser redirect).","x-tool":{"expose":[]},"x-cli":{"command":"mail external callback","output":{"format":"none"},"hidden":true},"parameters":[{"schema":{"type":"string"},"required":false,"name":"code","in":"query"},{"schema":{"type":"string"},"required":false,"name":"state","in":"query"},{"schema":{"type":"string"},"required":false,"name":"error","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalMailDeleteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/external/connections":{"get":{"operationId":"mail_external_connections_list","tags":["Mail"],"description":"List connected mailboxes.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail external connections list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalMailConnectionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/external/connections/{id}":{"delete":{"operationId":"mail_external_connection_delete","tags":["Mail"],"description":"Disconnect a connected mailbox.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail external connections delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalMailDeleteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/external/connections/{id}/test":{"get":{"operationId":"mail_external_connection_test","tags":["Mail"],"description":"Verify a connected mailbox by fetching its Gmail profile.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"mail external connections test"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalMailTestResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/search":{"get":{"operationId":"search_mail","tags":["Mail"],"description":"Full-text + operator search (Gmail-style: from:, to:, cc:, bcc:, subject:, has:attachment, is:read|unread|starred, in:inbox|sent|drafts|trash|archive, label:, after:YYYY-MM-DD, before:YYYY-MM-DD, size:N, larger:N, smaller:N, \"phrase\"). cc:/bcc: filter by recipient type. size:/larger:/smaller: filter by body byte size.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail search"},"parameters":[{"schema":{"type":"string","description":"Operator-syntax query (Gmail-style)."},"required":false,"description":"Operator-syntax query (Gmail-style).","name":"q","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSearchResultsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/smart-compose":{"post":{"operationId":"mail_smart_compose","tags":["Mail"],"description":"Stream AI completion suggestions","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail smart-compose","output":{"format":"raw"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmartComposeInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SmartComposeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/folder-counts":{"get":{"operationId":"mail_folder_counts","tags":["Mail"],"description":"Per-folder badge counts for sidebar Returns { inbox: unread_count, drafts, scheduled, snoozed } — Gmail-style.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail folder-counts"},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FolderCountsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/unread-summary":{"get":{"operationId":"mail_unread_summary","tags":["Mail"],"description":"Richer unread feed for the future workspace \"Unread across modules\" aggregator row 6.35, D205). Returns the mail-side contribution: total count + top N (default 5, max 25) unread inbox rows with sender/subject/preview/timestamp so an aggregator can render a unified list without pulling ...","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail unread-summary"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UnreadSummaryResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/send-as":{"get":{"operationId":"list_send_as_addresses","tags":["Mail"],"description":"List available send-as addresses for current user","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail send-as list","output":{"format":"table"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSendAsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"set_default_send_as","tags":["Mail"],"description":"Set the user's default send-as address.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail send-as set-default"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailSetDefaultSendAsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSetDefaultSendAsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/aliases":{"get":{"operationId":"mail_aliases_list","tags":["Mail"],"description":"List all aliases for current user's mailbox","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail aliases list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailAliasListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"mail_alias_create","tags":["Mail"],"description":"Add a new alias on a verified workspace domain","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail aliases create","output":{"successMessage":"Alias created: {email}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailAliasCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailAliasResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/aliases/{id}/default":{"put":{"operationId":"mail_alias_set_default","tags":["Mail"],"description":"Set alias as default send-as identity","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail aliases set-default","output":{"format":"none","successMessage":"Default alias updated."}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailAliasResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/aliases/{id}":{"delete":{"operationId":"mail_alias_delete","tags":["Mail"],"description":"Remove alias","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail aliases delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/shared-mailboxes":{"get":{"operationId":"mail_shared_mailboxes_list","tags":["Mail"],"description":"List the shared mailboxes the caller holds, or every one in the workspace with `scope=managed` (admin only)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail shared list","output":{"format":"table"}},"parameters":[{"schema":{"type":"string","enum":["managed"],"description":"Admin only: every shared mailbox in the workspace, not just the ones you hold."},"required":false,"description":"Admin only: every shared mailbox in the workspace, not just the ones you hold.","name":"scope","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedMailboxListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"mail_shared_mailbox_create","tags":["Mail"],"description":"Create a shared mailbox and address it on a workspace domain (admin only)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail shared create","output":{"successMessage":"Shared mailbox created: {address}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SharedMailboxCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedMailboxResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/shared-mailboxes/{mailboxId}":{"get":{"operationId":"mail_shared_mailbox_get","tags":["Mail"],"description":"Get one shared mailbox and its members","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail shared get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"mailboxId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedMailboxResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"mail_shared_mailbox_update","tags":["Mail"],"description":"Rename a shared mailbox's display name; its address is unchanged (admin only)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail shared rename"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"mailboxId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SharedMailboxUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedMailboxResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"mail_shared_mailbox_delete","tags":["Mail"],"description":"Retire a shared mailbox (admin only). Soft: stored mail is retained and the address stays reserved.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail shared delete"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"mailboxId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/shared-mailboxes/{mailboxId}/restore":{"post":{"operationId":"mail_shared_mailbox_restore","tags":["Mail"],"description":"Restore a retired shared mailbox (admin only). Total — delete cascaded nothing.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail shared restore"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"mailboxId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedMailboxResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/shared-mailboxes/{mailboxId}/assignees":{"get":{"operationId":"mail_shared_mailbox_assignees","tags":["Mail"],"description":"The people who can hold a thread in this shared mailbox — team grants flattened to their members.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail shared assignees","output":{"format":"table"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"mailboxId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailboxAssigneeListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/shared-mailboxes/{mailboxId}/members":{"post":{"operationId":"mail_shared_mailbox_member_add","tags":["Mail"],"description":"Grant a user or a team access to a shared mailbox (admin only)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail shared members add"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"mailboxId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SharedMailboxMemberAddInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedMailboxResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/shared-mailboxes/{mailboxId}/members/{memberId}":{"delete":{"operationId":"mail_shared_mailbox_member_remove","tags":["Mail"],"description":"Revoke a user's or team's access to a shared mailbox (admin only)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail shared members remove","confirm":true},"parameters":[{"schema":{"type":"string"},"required":true,"name":"mailboxId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"memberId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SharedMailboxResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/signature":{"get":{"operationId":"get_mail_signature","tags":["Mail"],"description":"Get the effective email signature.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail signature get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSignatureResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_mail_signature","tags":["Mail"],"description":"Set personal email signature. Pass null to clear.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail signature set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailSignatureUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSignatureResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/send":{"post":{"operationId":"send_email","tags":["Mail"],"description":"Send an email from the current user. The body is written in Markdown and automatically converted to a beautifully formatted HTML email for delivery. Use this when the user asks to send an email, message someone, or share something via email. Supports to, cc, and bcc recipients. Recipients are specified by email address.","x-tool":{"expose":["all","automations"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail send","aliases":["mail compose"],"output":{"successMessage":"Sent: {id} — {subject}"}},"parameters":[{"schema":{"type":"string"},"required":false,"name":"verbose","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/inbox":{"get":{"operationId":"list_inbox","tags":["Mail"],"description":"List the user's received emails (inbox). Returns emails with id, from, subject, preview, read status, and sent timestamp. Use this when the user asks to check their inbox, see recent emails, or find a specific email. Use detail='headers' for bandwidth-efficient scanning (omits body), or 'minimal' for id + labels only. Use label_ids to filter by specific labels (AND semantics — all listed labels must be present).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail inbox"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"unread","in":"query"},{"schema":{"type":"string","enum":["inbox","sent","drafts","starred","snoozed","scheduled"],"description":"`inbox` (default) | `sent` | `drafts` | `starred` | `snoozed` | `scheduled`."},"required":false,"description":"`inbox` (default) | `sent` | `drafts` | `starred` | `snoozed` | `scheduled`.","name":"folder","in":"query"},{"schema":{"type":"string","description":"Default true; pass `false` to flatten."},"required":false,"description":"Default true; pass `false` to flatten.","name":"threaded","in":"query"},{"schema":{"$ref":"#/components/schemas/MailAssignmentFilter"},"required":false,"description":"Shared-mailbox queue only: `me` for threads you hold, `unassigned` for threads nobody holds. 400 on a personal mailbox or with a non-inbox `folder`.","name":"assigned","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/sent":{"get":{"operationId":"list_sent_mail","tags":["Mail"],"description":"List sent emails","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail sent"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/starred":{"get":{"operationId":"list_starred_mail","tags":["Mail"],"description":"List starred emails","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail starred"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/snoozed":{"get":{"operationId":"list_snoozed_mail","tags":["Mail"],"description":"List snoozed emails","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail snoozed"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SnoozedEmailListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/archive":{"get":{"operationId":"list_archived_threads","tags":["Mail"],"description":"List archived threads (one per thread)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail archived"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/muted":{"get":{"operationId":"list_muted_threads","tags":["Mail"],"description":"List muted threads (inbox view for muted conversations)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail muted"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/trash":{"get":{"operationId":"mail_trash_list","tags":["Mail"],"description":"List trashed (soft-deleted) emails. `deleteEmail` moves rows to folder='trash' (D099 per-user-copy model) but until now there was no list endpoint, so trashed mail was effectively invisible in the UI.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail trash"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/drafts":{"get":{"operationId":"list_drafts","tags":["Mail"],"description":"List draft emails","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail drafts list"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailDraftListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_draft_email","tags":["Mail"],"description":"Create a draft email without sending it. The draft is saved in the drafts folder for later review, editing, or sending. Use this when the user wants to compose an email for later, save a draft, or prepare a message without sending it immediately.","x-tool":{"expose":["all"]},"x-cli":{"command":"mail drafts create","output":{"successMessage":"Draft created: {id}"}},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailDraftResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/drafts/{id}":{"patch":{"operationId":"update_draft_email","tags":["Mail"],"description":"Update an existing draft email. Only works on drafts (not sent messages). Use this to refine recipients, subject, or body of a draft across multiple iterations before sending.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail drafts update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailDraftResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/drafts/{id}/send":{"post":{"operationId":"send_draft_email","tags":["Mail"],"description":"Send a previously created draft email. The draft transitions from the drafts folder to sent, SES delivery is triggered, and recipient inbox copies are created. Use this when the user wants to send a draft they previously saved.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail drafts send","output":{"successMessage":"Draft sent: {id}"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/scheduled":{"get":{"operationId":"list_scheduled_mail","tags":["Mail"],"description":"List scheduled (unsent) emails","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail scheduled"},"parameters":[{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScheduledEmailListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/reschedule":{"post":{"operationId":"reschedule_scheduled_email","tags":["Mail"],"description":"Change the delivery time of a pending scheduled email without changing its content.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail reschedule","output":{"successMessage":"Scheduled send moved to {scheduled_at}."}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailRescheduleInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailRescheduleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/settings/undo-send":{"get":{"operationId":"get_undo_send_setting","tags":["Mail"],"description":"Get undo-send duration preference.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail settings undo-send get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UndoSendSettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_undo_send_setting","tags":["Mail"],"description":"Set undo-send duration (seconds).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail settings undo-send set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UndoSendUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UndoSendSettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/undo":{"post":{"operationId":"undo_send_email","tags":["Mail"],"description":"Undo an in-flight send within the undo-send window.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail undo","output":{"successMessage":"Send undone — moved back to drafts."}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailDraftResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/settings/read-receipts":{"get":{"operationId":"get_read_receipts_default","tags":["Mail"],"description":"Get read-receipts default for new compose.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail settings read-receipts get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailReadReceiptSettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_read_receipts_default","tags":["Mail"],"description":"Toggle the default for new compose windows","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail settings read-receipts set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailReadReceiptsUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailReadReceiptSettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/settings/snooze-presets":{"get":{"operationId":"get_snooze_presets","tags":["Mail"],"description":"Get the user's custom snooze quick-presets. Returns defaults when no custom presets are saved.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail settings snooze-presets get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSnoozePresetsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_snooze_presets","tags":["Mail"],"description":"Set the user's custom snooze quick-presets (up to 10). Pass an empty array to reset to defaults.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail settings snooze-presets set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailSnoozePresetsUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSnoozePresetsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/opens":{"get":{"operationId":"get_email_opens","tags":["Mail"],"description":"Fetch open events for an email (sender only) Returns the rollup (first/last seen, open count) plus up to the most recent 50 individual open events. 403 if the caller doesn't own the email's mailbox.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail opens"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailOpensResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/label/{label}":{"get":{"operationId":"list_mail_by_label","tags":["Mail"],"description":"List emails with a specific label","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail label"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"label","in":"path"},{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Comma-separated label UUIDs (AND semantics)."},"required":false,"description":"Comma-separated label UUIDs (AND semantics).","name":"label_ids","in":"query"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/rules":{"get":{"operationId":"list_mail_rules","tags":["Mail"],"description":"List mail rules / filters.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail rules list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailRuleListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_mail_rule","tags":["Mail"],"description":"Create a mail rule.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail rules create","output":{"successMessage":"Rule created: {id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailRuleCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailRuleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/rules/reorder":{"post":{"operationId":"reorder_mail_rules","tags":["Mail"],"description":"Reorder rules.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail rules reorder"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailRuleReorderInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailRuleListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/rules/{rule_id}":{"get":{"operationId":"get_mail_rule","tags":["Mail"],"description":"Get a single rule.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail rules get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"rule_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailRuleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_mail_rule","tags":["Mail"],"description":"Update a rule.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail rules update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"rule_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailRuleUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailRuleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_mail_rule","tags":["Mail"],"description":"Delete a rule.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail rules delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"rule_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/templates":{"get":{"operationId":"list_mail_templates","tags":["Mail"],"description":"List templates.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail templates list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailTemplateListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_mail_template","tags":["Mail"],"description":"Create a template.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail templates create","output":{"successMessage":"Template created: {id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailTemplateCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailTemplateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/templates/{template_id}":{"get":{"operationId":"get_mail_template","tags":["Mail"],"description":"Get a template.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail templates get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"template_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailTemplateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_mail_template","tags":["Mail"],"description":"Update a template.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail templates update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"template_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailTemplateUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailTemplateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_mail_template","tags":["Mail"],"description":"Delete a template.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail templates delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"template_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/templates/{template_id}/use":{"post":{"operationId":"use_mail_template","tags":["Mail"],"description":"Record template use.","x-tool":{"expose":["all"]},"x-cli":{"command":"mail templates use"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"template_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailTemplateUseResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/labels":{"get":{"operationId":"list_mail_labels","tags":["Mail"],"description":"List mail labels.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail labels list"},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailLabelListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_mail_label","tags":["Mail"],"description":"Create a label.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail labels create","output":{"successMessage":"Label created: {id}"}},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailLabelCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailLabelResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/label-counts":{"get":{"operationId":"mail_label_counts","tags":["Mail"],"description":"Per-label unread counts for sidebar badges (IH row 6.21). Separate endpoint so the sidebar can refresh counts on read/receive without re-fetching the label definitions themselves. Shape mirrors /folder-counts. `rawDb` is needed because the count query uses CROSS JOIN LATERAL jsonb_array_elements ...","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail labels counts","output":{"format":"table"}},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailLabelCountsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/labels/reorder":{"post":{"operationId":"reorder_mail_labels","tags":["Mail"],"description":"Reorder labels.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail labels reorder"},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailLabelReorderInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailLabelListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/labels/{label_id}":{"patch":{"operationId":"update_mail_label","tags":["Mail"],"description":"Update a label.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail labels update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"label_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailLabelUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailLabelResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_mail_label","tags":["Mail"],"description":"Delete a label.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail labels delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"label_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/vacation":{"get":{"operationId":"get_vacation_settings","tags":["Mail"],"description":"Get vacation auto-reply settings.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail vacation get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VacationResponderResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_vacation_settings","tags":["Mail"],"description":"Update vacation auto-reply settings.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail vacation set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VacationUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VacationResponderResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/blocklist":{"get":{"operationId":"list_blocked_senders","tags":["Mail"],"description":"List all blocked senders for current user's mailbox","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail blocklist list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/BlocklistListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"block_sender","tags":["Mail"],"description":"Block a sender (address or domain).","x-tool":{"expose":["all"]},"x-cli":{"command":"mail blocklist add","output":{"successMessage":"Blocked: {entry.pattern}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailBlocklistAddInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/BlocklistAddResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"mail_blocklist_clear","tags":["Mail"],"description":"Unblock by raw pattern (convenience for \"Unblock sender\" button)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail blocklist clear","confirm":true},"parameters":[{"schema":{"type":"string","description":"Sender address or domain to remove from blocklist."},"required":true,"description":"Sender address or domain to remove from blocklist.","name":"pattern","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/blocklist/unblock":{"post":{"operationId":"unblock_sender","tags":["Mail"],"description":"Unblock by id or pattern.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail blocklist unblock"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailUnblockSenderInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailUnblockSenderResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/blocklist/{id}":{"delete":{"operationId":"mail_blocklist_remove","tags":["Mail"],"description":"Unblock by entry id","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail blocklist remove","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/unsubscribe":{"post":{"operationId":"mail_message_unsubscribe","tags":["Mail"],"description":"One-click unsubscribe. Triggers the List-Unsubscribe URL (RFC 8058) on the user's behalf. Falls back to telling the client to open a mailto: link if no HTTP URL is present.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail unsubscribe"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailUnsubscribeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/forwarding":{"get":{"operationId":"list_forwarding_addresses","tags":["Mail"],"description":"List forwarding addresses + recent log.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail forwarding list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailForwardingListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"add_forwarding_address","tags":["Mail"],"description":"Add a forwarding address (sends verification email).","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail forwarding add","output":{"successMessage":"Verification email sent to {address}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailForwardingAddInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ForwardingEntryResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/forwarding/{id}/resend":{"post":{"operationId":"resend_forwarding_verification","tags":["Mail"],"description":"Resend verification email","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail forwarding resend"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ForwardingEntryResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/forwarding/{id}":{"delete":{"operationId":"remove_forwarding_address","tags":["Mail"],"description":"Remove a forwarding address","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail forwarding remove","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/merge-preview":{"post":{"operationId":"mail_merge_preview","tags":["Mail"],"description":"Preview a merged email for one recipient","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true}},"x-cli":{"command":"mail merge preview"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailMergePreviewInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailMergePreviewResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/merge-send":{"post":{"operationId":"mail_merge_send","tags":["Mail"],"description":"Batch send personalized emails","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail merge send","output":{"successMessage":"Mail merge sent: {sent}/{total} succeeded ({failed} failed)"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailMergeSendInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailMergeSendResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/merge-parse-csv":{"post":{"operationId":"mail_merge_parse_csv","tags":["Mail"],"description":"Parse CSV text into recipient list","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true}},"x-cli":{"command":"mail merge parse-csv"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailMergeParseCsvInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailMergeParseCsvResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}":{"get":{"operationId":"get_mail_thread","tags":["Mail"],"description":"Get all emails in a thread + muted flag.","x-tool":{"expose":["assistant","mcp","automations"]},"x-cli":{"command":"mail thread get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailThreadResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_mail_thread","tags":["Mail"],"description":"Permanently delete all messages in a thread. Cannot be undone. Only deletes the authenticated user's copies.","x-cli":{"command":"mail thread delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}/mute":{"post":{"operationId":"mute_mail_thread","tags":["Mail"],"description":"Mute a thread","x-tool":{"expose":["all"]},"x-cli":{"command":"mail thread mute"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"unmute_mail_thread","tags":["Mail"],"description":"Unmute a thread","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail thread unmute"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{threadId}/mute":{"get":{"operationId":"mail_thread_mute_status","tags":["Mail"],"description":"Check if a thread is muted","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail thread mute-status"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"threadId","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailThreadMuteStatusResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}/assignee":{"put":{"operationId":"assign_mail_thread","tags":["Mail"],"description":"Claim a shared-mailbox thread for a member, or hand it to another. Shared mailboxes only.","x-tool":{"expose":["all"]},"x-cli":{"command":"mail thread assign"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailThreadAssignInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailThreadAssignmentResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"unassign_mail_thread","tags":["Mail"],"description":"Release a shared-mailbox thread back to Unassigned.","x-tool":{"expose":["all"]},"x-cli":{"command":"mail thread unassign"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailThreadAssignmentResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}/archive":{"post":{"operationId":"archive_mail_thread","tags":["Mail"],"description":"Archive every inbox-folder message in a thread","x-tool":{"expose":["all"]},"x-cli":{"command":"mail thread archive"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailThreadArchiveResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}/trash":{"post":{"operationId":"trash_mail_thread","tags":["Mail"],"description":"Trash all messages in a thread atomically. Moves every message in the thread to the trash folder.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail thread trash","confirm":true},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailThreadTrashResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}/untrash":{"post":{"operationId":"untrash_mail_thread","tags":["Mail"],"description":"Restore all trashed messages in a thread to inbox. Only affects messages currently in trash.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail thread untrash"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailThreadUntrashResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}/comments":{"get":{"operationId":"list_mail_thread_comments","tags":["Mail"],"description":"List the internal comments on a shared-mailbox thread. Team-only — never delivered to the correspondent. Top-level comments carry their replies inline.","x-tool":{"expose":["all"]},"x-cli":{"command":"mail thread comments list","output":{"format":"object"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailThreadCommentListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_mail_thread_comment","tags":["Mail"],"description":"Add an internal comment to a shared-mailbox thread. Visible to mailbox members only — this never sends mail and never reaches the correspondent. Pass `parent_id` to reply.","x-tool":{"expose":["all"]},"x-cli":{"command":"mail thread comments create"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailThreadCommentCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailThreadCommentResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}/comments/{comment_id}":{"patch":{"operationId":"update_mail_thread_comment","tags":["Mail"],"description":"Edit or resolve an internal comment. Only the author may edit its content; any mailbox member may resolve or reopen it.","x-tool":{"expose":["all"]},"x-cli":{"command":"mail thread comments update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"comment_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailThreadCommentUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailThreadCommentResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_mail_thread_comment","tags":["Mail"],"description":"Delete an internal comment. Author-only. Cascades to its replies.","x-tool":{"expose":["all"]},"x-cli":{"command":"mail thread comments delete","confirm":true},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"comment_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}/comments/{comment_id}/reactions":{"post":{"operationId":"add_mail_thread_comment_reaction","tags":["Mail"],"description":"Add an emoji reaction to an internal comment. Idempotent per (user, emoji). Returns the comment's updated reaction aggregate.","x-tool":{"expose":["all"]},"x-cli":{"hidden":true,"command":"mail thread comments react"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"comment_id","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentReactionInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CommentReactionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/thread/{thread_id}/comments/{comment_id}/reactions/{emoji}":{"delete":{"operationId":"remove_mail_thread_comment_reaction","tags":["Mail"],"description":"Remove the caller's emoji reaction from an internal comment. Returns the comment's updated reaction aggregate.","x-tool":{"expose":["all"]},"x-cli":{"hidden":true,"command":"mail thread comments unreact"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"thread_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"comment_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"emoji","in":"path"},{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CommentReactionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/batch/archive":{"post":{"operationId":"batch_archive_emails","tags":["Mail"],"description":"Archive multiple emails in one atomic call. Moves all specified messages to the archive folder. Use this when the user wants to bulk-archive many emails (e.g., inbox-zero cleanup, archiving all messages from a sender).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail batch archive","output":{"successMessage":"Archived {archived_count} email(s)."}},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailBulkDeleteInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailBulkModifyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/batch/trash":{"post":{"operationId":"batch_trash_emails","tags":["Mail"],"description":"Trash multiple emails in one atomic call. Moves all specified messages to the trash folder. Use this when the user wants to bulk-trash many emails (e.g., spam cleanup, clearing a project mailbox).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail batch trash","confirm":true,"output":{"successMessage":"Trashed {trashed_count} email(s)."}},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailBulkDeleteInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailBulkModifyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/batch/modify":{"post":{"operationId":"batch_modify_emails","tags":["Mail"],"description":"Batch modify multiple emails in one atomic call. Can star/unstar, mark read/unread, add/remove labels, and change folder — all at once for up to 500 messages. Use this when the user wants to bulk-update many emails (e.g., star all from a sender, mark a batch as read, apply labels to multiple messages).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail batch modify","output":{"successMessage":"Modified {modified_count} email(s)."}},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailBulkModifyInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailBulkModifyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/batch/delete":{"post":{"operationId":"batch_delete_emails","tags":["Mail"],"description":"Permanently delete multiple emails in one atomic call. Rows are hard-deleted — this cannot be undone. Use this when the user wants to purge old messages, clear test data, or permanently remove emails.","x-cli":{"command":"mail batch delete","confirm":true,"output":{"successMessage":"Deleted {deleted_count} email(s)."}},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailBulkDeleteInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailBulkDeleteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/bulk":{"post":{"operationId":"mail_bulk_modify","tags":["Mail"],"description":"POST /api/mail/bulk","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail bulk","output":{"successMessage":"Modified {modified_count} email(s)."}},"parameters":[{"schema":{"type":"string","description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it."},"required":false,"description":"Target a shared mailbox you hold. Omit for your own mailbox; 404 if you don't hold it.","name":"mailbox_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailBulkActionInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailBulkModifyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/invite":{"get":{"operationId":"get_email_calendar_invite","tags":["Mail"],"description":"Get calendar invite embedded in an email.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail invite get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailInvitePreviewResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/rsvp":{"post":{"operationId":"rsvp_email_invite","tags":["Mail"],"description":"RSVP to a calendar invite on an email.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"mail invite rsvp"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailRsvpInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailRsvpResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/attachments":{"get":{"operationId":"list_email_attachments","tags":["Mail"],"description":"List attachments for an email","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail attachments list"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailAttachmentListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/attachments/{attachment_id}/download":{"get":{"operationId":"get_email_attachment_url","tags":["Mail"],"description":"Get a presigned download URL for an attachment.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail attachments url"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"attachment_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailAttachmentUrlResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/archive":{"post":{"operationId":"archive_email","tags":["Mail"],"description":"Archive a single email","x-tool":{"expose":["all"]},"x-cli":{"command":"mail archive"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"unarchive_email","tags":["Mail"],"description":"Move archived email back to inbox","x-tool":{"expose":["all"]},"x-cli":{"command":"mail unarchive"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/untrash":{"post":{"operationId":"untrash_email","tags":["Mail"],"description":"Restore a trashed email to inbox","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail untrash"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailUntrashEmailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/permanent":{"delete":{"operationId":"permanent_delete_email","tags":["Mail"],"description":"Permanently delete an email. Hard-deletes the row — cannot be undone. Use for compliance/PII removal or purging test data.","x-cli":{"command":"mail permanent-delete","confirm":true},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/snooze":{"post":{"operationId":"snooze_email","tags":["Mail"],"description":"Snooze an email until a datetime.","x-tool":{"expose":["all"]},"x-cli":{"command":"mail snooze","output":{"successMessage":"Snoozed until {snoozed_until}"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailSnoozeInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSnoozeEmailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}/cancel":{"post":{"operationId":"cancel_scheduled_email","tags":["Mail"],"description":"Cancel a scheduled email","x-tool":{"expose":["all"]},"x-cli":{"command":"mail cancel","confirm":true,"output":{"format":"none","successMessage":"Scheduled send cancelled."}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail/{id}":{"get":{"operationId":"get_email","tags":["Mail"],"description":"Get a single email by ID, including full Markdown body, sender, recipients (to/cc/bcc), subject, and timestamps. Use this when the user wants to read an email, see its contents, or reply to a specific message. If the user is currently viewing an email, use the email ID from the page context. Use detail='headers' for envelope fields only (no body), or 'minimal' for id + labels only.","x-tool":{"expose":["assistant","mcp","automations"]},"x-cli":{"command":"mail get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["full","headers","minimal"],"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels)."},"required":false,"description":"Response shape: `full` (default), `headers` (envelope only), `minimal` (id + labels).","name":"detail","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"mark_email_read","tags":["Mail"],"description":"Update email status (read/unread, starred, snoozed)","x-tool":{"expose":["all"]},"x-cli":{"command":"mail mark"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailEmailMarkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_email","tags":["Mail"],"description":"Delete an email.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"mail delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/templates":{"get":{"operationId":"list_task_templates","tags":["Tasks"],"description":"List task templates in the workspace. Templates pre-fill fields when creating tasks. Optionally filter by project. Returns name, default fields (priority, status, estimate, assignee, labels), and creator.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks templates list"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskTemplateListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_task_template","tags":["Tasks"],"description":"Create a reusable task template. Templates define default field values (status, priority, estimate, assignee, labels) that are applied when creating a task from the template. Scope to a project with `project_id`, or leave workspace-wide.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks templates create","output":{"successMessage":"Template created: {template.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskTemplateCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskTemplateWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/templates/{template_id}/apply":{"post":{"operationId":"apply_task_template","tags":["Tasks"],"description":"Create a new task by applying a template's defaults. The template pre-fills status, priority, estimate, assignee, description, and labels. Override any field by passing it explicitly. Title is always required.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks templates apply","output":{"successMessage":"Task created from template: {task.id}"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"template_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskTemplateApplyInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskCreateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Response body for `POST /api/tasks`. Wrapped in `{ task }` for legacy compatibility."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/templates/{templateId}":{"get":{"operationId":"tasks_templates_get","tags":["Tasks"],"description":"Get a single task template by ID.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks templates get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"templateId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskTemplateWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"tasks_templates_update","tags":["Tasks"],"description":"Update a task template. Workspace admins or project admins only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks templates update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"templateId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskTemplateUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskTemplateWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"tasks_templates_delete","tags":["Tasks"],"description":"Delete a task template. Workspace admins or project admins only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks templates delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"templateId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/export":{"get":{"operationId":"tasks_export","tags":["Tasks"],"description":"Export the caller's tasks as CSV (default) or JSON.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks export","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","description":"'csv' (default) | 'json'. Validated by handler so the 400 error message is preserved."},"required":false,"description":"'csv' (default) | 'json'. Validated by handler so the 400 error message is preserved.","name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"task_status_id","in":"query"},{"schema":{"type":"string","description":"Comma-separated custom status IDs to exclude."},"required":false,"description":"Comma-separated custom status IDs to exclude.","name":"exclude_task_status_ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"priority","in":"query"},{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"assignee_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"due_date_start","in":"query"},{"schema":{"type":"string"},"required":false,"name":"due_date_end","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"show_archived","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cycle_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"label_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"parent_task_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskExportResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/batch":{"get":{"operationId":"tasks_batch","tags":["Tasks"],"description":"Batch-fetch up to 50 tasks by ID. Powers LinkedTaskItem hydration in Docs/Wiki (D103).","x-tool":{"expose":["mcp"]},"x-cli":{"command":"tasks batch"},"parameters":[{"schema":{"type":"string","description":"Comma-separated task IDs (max 50)."},"required":false,"description":"Comma-separated task IDs (max 50).","name":"ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskBatchListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/statuses":{"get":{"operationId":"list_task_statuses","tags":["Tasks"],"description":"List custom task statuses for the current workspace (e.g., 'Blocked', 'Shipped'). Each status has a name, color, icon, sort_order, and maps to a canonical category (todo, in_progress, done, cancelled). Workspaces are seeded with 4 defaults (To Do / In Progress / Done / Cancelled) on first read; additional statuses are added via create_task_status.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks statuses list"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskStatusEntityListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_task_status","tags":["Tasks"],"description":"Create a custom task status in the workspace. Every status must map to one canonical category (todo, in_progress, done, cancelled) so progress metrics still work.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks statuses create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskStatusCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskStatusEntityWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/statuses/reorder":{"post":{"operationId":"reorder_task_statuses","tags":["Tasks"],"description":"Reorder task statuses by passing an array of { id, sort_order } pairs. All statuses belong to the current workspace.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks statuses reorder","output":{"format":"none"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderItemsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/statuses/{status_id}":{"patch":{"operationId":"update_task_status","tags":["Tasks"],"description":"Update a workspace custom task status. Omit fields to keep unchanged. Pass null for `icon` to clear.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks statuses update"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskStatusId"},"required":true,"name":"status_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskStatusUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskStatusEntityWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_task_status","tags":["Tasks"],"description":"Delete a workspace custom status. Cannot delete a default (seeded) status. Tasks using this status have their task_status_id set to NULL — they still resolve to their canonical category.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks statuses delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskStatusId"},"required":true,"name":"status_id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/custom-fields":{"get":{"operationId":"list_task_custom_fields","tags":["Tasks"],"description":"List custom fields for the workspace's tasks. Each field has a name, field_type (text/number/select/date), options (for select), required flag, sort_order.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks custom-fields list"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskCustomFieldListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_task_custom_field","tags":["Tasks"],"description":"Create a custom field for tasks. `select` fields must include at least one option in `options`.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks custom-fields create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskCustomFieldCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskCustomFieldWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/custom-fields/reorder":{"post":{"operationId":"reorder_task_custom_fields","tags":["Tasks"],"description":"Reorder custom fields by passing an `items` array of `{id, sort_order}`.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks custom-fields reorder","output":{"format":"none"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderItemsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/custom-fields/{field_id}":{"patch":{"operationId":"update_task_custom_field","tags":["Tasks"],"description":"Update a custom field's name, type, options, required flag, or sort order. Omit fields to keep unchanged.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks custom-fields update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"field_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskCustomFieldUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskCustomFieldWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_task_custom_field","tags":["Tasks"],"description":"Delete a task custom field. Existing per-task values for this field are dropped.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks custom-fields delete","confirm":true},"parameters":[{"schema":{"type":"string"},"required":true,"name":"field_id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/labels":{"get":{"operationId":"tasks_labels_list","tags":["Tasks"],"description":"List task labels visible in the workspace, grouped by `group_name`. Without `project_id`, returns workspace-level labels only. With `project_id`, returns workspace-level labels plus labels scoped to that project.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks labels list"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskLabelListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"tasks_labels_create","tags":["Tasks"],"description":"Create a workspace task label. Returns 409 if a label with the same name already exists in the group.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks labels create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskLabelCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskLabelWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/labels/{labelId}":{"patch":{"operationId":"tasks_labels_update","tags":["Tasks"],"description":"Update a task label.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks labels update"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskLabelId"},"required":true,"name":"labelId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskLabelUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskLabelWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"tasks_labels_delete","tags":["Tasks"],"description":"Delete a task label. Existing assignments are removed.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks labels delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskLabelId"},"required":true,"name":"labelId","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/sla/thresholds":{"get":{"operationId":"tasks_sla_thresholds","tags":["Tasks"],"description":"Get the workspace's SLA thresholds (response + resolution times per priority). Auth-only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks sla thresholds"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSlaThresholds"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"SLA response + resolution thresholds in minutes, per task priority."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/sla/dashboard":{"get":{"operationId":"tasks_sla_dashboard","tags":["Tasks"],"description":"Aggregate SLA metrics for the workspace (compliance rates, avg times, counts per status). Optionally scope to a project.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks sla dashboard"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string","description":"Window in days (1..365, default 90)."},"required":false,"description":"Window in days (1..365, default 90).","name":"days","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSlaDashboard"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Aggregate SLA metrics for the workspace, split by response and resolution."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/views":{"get":{"operationId":"tasks_views_list","tags":["Tasks"],"description":"List task views accessible to the caller (own + shared + system defaults).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks views list"},"parameters":[{"schema":{"type":"string","description":"Max items to return (per-endpoint default/cap)."},"required":false,"description":"Max items to return (per-endpoint default/cap).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskViewListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"tasks_views_create","tags":["Tasks"],"description":"Create a saved task view (filter + layout). Setting `is_shared: true` exposes it to the workspace.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks views create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskViewCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskViewWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/views/{viewId}":{"patch":{"operationId":"tasks_views_update","tags":["Tasks"],"description":"Update a saved task view (rename, change filters or layout defaults, toggle sharing).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks views update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"viewId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskViewUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskViewWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"tasks_views_delete","tags":["Tasks"],"description":"Delete a saved task view.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks views delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"viewId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/views/{viewId}/layout":{"get":{"operationId":"tasks_views_layout_get","tags":["Tasks"],"description":"Get the caller's layout preferences for a view, or fall back to the view's defaults. `source` indicates which.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks views layout get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"viewId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskViewLayoutGetResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"tasks_views_layout_update","tags":["Tasks"],"description":"Upsert the caller's layout preferences for a view (per-project scope optional).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks views layout update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"viewId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskViewLayoutUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskViewLayoutUpdateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/subscribed":{"get":{"operationId":"tasks_subscribed","tags":["Tasks"],"description":"List task IDs the caller is subscribed to (manual + auto-subscribed via creator/assignee/comment).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks subscribed","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","description":"Max items to return (per-endpoint default/cap)."},"required":false,"description":"Max items to return (per-endpoint default/cap).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSubscribedIdsEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/analytics":{"get":{"operationId":"get_task_analytics","tags":["Tasks"],"description":"Get burndown + velocity analytics for tasks in the workspace within a date range. Defaults to the last 30 days when dates are omitted. Range capped at 365 days. Use this when the user asks for project progress, burndown charts, velocity trends, or completion pace.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks analytics"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"start_date","in":"query"},{"schema":{"type":"string"},"required":false,"name":"end_date","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskAnalytics"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Response body for `GET /api/tasks/analytics`."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/workload":{"get":{"operationId":"get_task_workload","tags":["Tasks"],"description":"Get workload aggregates grouped by assignee (including an unassigned bucket). Each bucket returns totalTasks, openTasks, overdueTasks, estimatedMinutes, utilization, etc. Use this when the user asks who is overloaded, who has capacity, or how work is distributed.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks workload","output":{"format":"table"}},"parameters":[{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"capacity_hours","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskWorkload"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Response body for `GET /api/tasks/workload`."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/goals":{"get":{"operationId":"list_goals","tags":["Tasks"],"description":"List goals/milestones in the workspace. Each goal returns progress (percentage, totalTasks, doneTasks), owner, status, target_date. Use this when the user asks about milestones, OKRs, or goal progress.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks goals list"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","description":"Max items to return (default 100, max 200)."},"required":false,"description":"Max items to return (default 100, max 200).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskGoalListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_goal","tags":["Tasks"],"description":"Create a goal/milestone. Tasks can be linked to goals via the `goal_id` field (see update_task / bulk_update_tasks).","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks goals create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskGoalCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskGoalWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/goals/{id}":{"get":{"operationId":"get_goal","tags":["Tasks"],"description":"Get a single goal by ID, including progress (percentage, totalTasks, doneTasks) and owner info.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks goals get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskGoalWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_goal","tags":["Tasks"],"description":"Update a goal. Provide only the fields you want to change. Pass `null` on nullable fields (description, icon, target_date, project_id, owner_id) to clear them.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks goals update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskGoalUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskGoalWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_goal","tags":["Tasks"],"description":"Delete a goal. Tasks linked to the goal are not deleted — their goal_id is set to NULL.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks goals delete","confirm":true},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/goals/{goal_id}/tasks":{"get":{"operationId":"list_goal_tasks","tags":["Tasks"],"description":"List all tasks linked to a goal. Returns id, title, status, priority, assignee, due_date, task_key.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks goals tasks"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"goal_id","in":"path"},{"schema":{"type":"string","description":"Max items to return (per-endpoint default/cap)."},"required":false,"description":"Max items to return (per-endpoint default/cap).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskGoalTaskSummaryListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/bulk/update":{"post":{"operationId":"bulk_update_tasks","tags":["Tasks"],"description":"Update multiple tasks at once by ID. Only updates tasks the current user has access to (creator or assignee). Max 100 task IDs per call. Omit fields you do not want to change. Pass `null` to clear a nullable field (assignee_id, project_id, due_date, goal_id, task_status_id).","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks bulk update"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskBulkUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskBulkUpdateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/bulk/delete":{"post":{"operationId":"bulk_delete_tasks","tags":["Tasks"],"description":"Soft-delete multiple tasks at once by ID. Only deletes tasks the current user created. Max 100 task IDs per call. Subtasks cascade. Use `restore_task` to recover individually.","x-tool":{"expose":["all"],"annotations":{"destructive":true}},"x-cli":{"command":"tasks bulk delete","confirm":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskBulkDeleteInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskBulkDeleteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/bulk/archive":{"post":{"operationId":"bulk_archive_tasks","tags":["Tasks"],"description":"Archive up to 100 tasks at once. Only archives tasks the caller created or is assigned to.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks bulk archive","confirm":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskBulkArchiveInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskBulkArchiveResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/clear":{"post":{"operationId":"clear_completed_tasks","tags":["Tasks"],"description":"Clear (soft-delete) completed tasks. Only clears tasks with status 'done' that the current user created. Subtasks of cleared tasks cascade. Scope is required: pass `project_id` to clear one project, or `all_projects: true` to clear workspace-wide (the destructive option is opt-in, never the default). An empty body or an unknown/typo'd key returns 400. Use `restore_task` to recover individually.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks clear","confirm":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskClearCompletedInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskClearCompletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/inbox-count":{"get":{"operationId":"tasks_inbox_count","tags":["Tasks"],"description":"Count of triage-bucket tasks (untriaged + projects in 'triage' status). Powers the sidebar inbox badge.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks inbox-count"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskInboxCountResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/maintenance/auto-close":{"post":{"operationId":"tasks_maintenance_auto_close","tags":["Tasks"],"description":"Admin-only: bulk-cancel tasks with no activity for `tasks_auto_close_days` (workspace setting). Adds a system comment to each.","x-cli":{"command":"tasks maintenance auto-close","confirm":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskMaintenanceCloseResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/maintenance/auto-archive":{"post":{"operationId":"tasks_maintenance_auto_archive","tags":["Tasks"],"description":"Admin-only: bulk-archive done/cancelled tasks older than `tasks_auto_archive_days` (workspace setting).","x-cli":{"command":"tasks maintenance auto-archive","confirm":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskMaintenanceArchiveResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/timer/active":{"get":{"operationId":"get_active_task_timer","tags":["Tasks"],"description":"Get the caller's currently-running task timer (or null if none).","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks timer active"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskActiveTimerResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Returns the user's currently-running timer, or `null` if none."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/favorites":{"get":{"operationId":"tasks_favorites_list","tags":["Tasks"],"description":"List the caller's pinned favorites (views or projects).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks favorites list"},"parameters":[{"schema":{"type":"string","description":"Max items to return (per-endpoint default/cap)."},"required":false,"description":"Max items to return (per-endpoint default/cap).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskFavoriteListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"tasks_favorites_add","tags":["Tasks"],"description":"Add a sidebar favorite (a view or a project).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks favorites add"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskFavoriteCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskFavorite"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Sidebar favorite — pins a view or project for the current user."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"tasks_favorites_remove","tags":["Tasks"],"description":"Remove a sidebar favorite (matched on `resource_type` + `resource_id`).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks favorites remove","output":{"format":"none"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskFavoriteRemoveInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/favorites/reorder":{"put":{"operationId":"tasks_favorites_reorder","tags":["Tasks"],"description":"Reorder the caller's sidebar favorites by passing `ordered_ids` (top-to-bottom).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks favorites reorder","output":{"format":"none"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskFavoriteReorderInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskFavoriteListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/by-key/{taskKey}":{"get":{"operationId":"tasks_by_key","tags":["Tasks"],"description":"Resolve a workspace-scoped task key (e.g. `WS-123`) to its task ID. Used by deep links and integrations.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks by-key"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"taskKey","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskKeyResolveResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/relations/batch":{"get":{"operationId":"tasks_relations_batch","tags":["Tasks"],"description":"Batch-fetch blocking/blocked_by relations for up to 200 tasks. Powers the timeline dependency overlay.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks relations batch"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskRelationsBatchEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/trash":{"get":{"operationId":"list_trashed_tasks","tags":["Tasks"],"description":"List top-level tasks the current user owns in Trash, including projectless tasks assigned to AI coworkers they manage. Returns up to 200, most-recently trashed first.","x-tool":{"expose":[]},"x-cli":{"command":"tasks trash list","output":{"columns":["id","task_key","title","status"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskTrashListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Response body for `GET /api/tasks/trash`."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks":{"get":{"operationId":"list_tasks","tags":["Tasks"],"description":"List tasks in the workspace. Pass assignee_id to filter by assignee (use the caller's user ID for 'my tasks'). Supports filtering by status, priority, project, and free-text query.","x-tool":{"expose":["mcp","assistant"]},"x-cli":{"command":"tasks list","aliases":["tasks ls"],"output":{"format":"table","columns":["id","task_key","title","status","priority","assignee.display_name","due_date"]}},"parameters":[{"schema":{"type":"string","description":"Filter to tasks assigned to this user. `unassigned` to filter to unassigned."},"required":false,"description":"Filter to tasks assigned to this user. `unassigned` to filter to unassigned.","name":"assignee_id","in":"query"},{"schema":{"type":"string","description":"Filter by creator user ID."},"required":false,"description":"Filter by creator user ID.","name":"creator_id","in":"query"},{"schema":{"type":"string","description":"Filter by system status. Comma-separated for multi-select."},"required":false,"description":"Filter by system status. Comma-separated for multi-select.","name":"status","in":"query"},{"schema":{"type":"string","description":"Filter by custom status ID."},"required":false,"description":"Filter by custom status ID.","name":"task_status_id","in":"query"},{"schema":{"type":"string","description":"Comma-separated custom status IDs to exclude."},"required":false,"description":"Comma-separated custom status IDs to exclude.","name":"exclude_task_status_ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"priority","in":"query"},{"schema":{"type":"string"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"string","description":"Filter by parent task ID. Special value `null` (string) returns top-level tasks only."},"required":false,"description":"Filter by parent task ID. Special value `null` (string) returns top-level tasks only.","name":"parent_task_id","in":"query"},{"schema":{"type":"string","description":"YYYY-MM-DD lower bound (inclusive)."},"required":false,"description":"YYYY-MM-DD lower bound (inclusive).","name":"due_date_start","in":"query"},{"schema":{"type":"string","description":"YYYY-MM-DD upper bound (inclusive)."},"required":false,"description":"YYYY-MM-DD upper bound (inclusive).","name":"due_date_end","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Pass 'true' to filter to tasks with a due date set."},"required":false,"description":"Pass 'true' to filter to tasks with a due date set.","name":"has_due_date","in":"query"},{"schema":{"type":"string"},"required":false,"name":"start_date_from","in":"query"},{"schema":{"type":"string"},"required":false,"name":"start_date_to","in":"query"},{"schema":{"type":"string","description":"Free-text search across title + description."},"required":false,"description":"Free-text search across title + description.","name":"q","in":"query"},{"schema":{"type":"string","description":"ISO 8601 lower bound on `completed_at`."},"required":false,"description":"ISO 8601 lower bound on `completed_at`.","name":"completed_min","in":"query"},{"schema":{"type":"string","description":"ISO 8601 upper bound on `completed_at`."},"required":false,"description":"ISO 8601 upper bound on `completed_at`.","name":"completed_max","in":"query"},{"schema":{"type":"string","description":"ISO 8601 lower bound on `updated_at`."},"required":false,"description":"ISO 8601 lower bound on `updated_at`.","name":"updated_min","in":"query"},{"schema":{"type":"string","description":"Filter by cycle ID. `none` returns tasks with no cycle."},"required":false,"description":"Filter by cycle ID. `none` returns tasks with no cycle.","name":"cycle_id","in":"query"},{"schema":{"type":"string","description":"Filter by a single label ID (must be a UUID)."},"required":false,"description":"Filter by a single label ID (must be a UUID).","name":"label_id","in":"query"},{"schema":{"type":"string","description":"Comma-separated label IDs (AND match)."},"required":false,"description":"Comma-separated label IDs (AND match).","name":"label_ids","in":"query"},{"schema":{"type":"string","description":"Comma-separated label IDs (OR match)."},"required":false,"description":"Comma-separated label IDs (OR match).","name":"any_label_ids","in":"query"},{"schema":{"type":"string","description":"Filter to tasks linked to this CRM contact."},"required":false,"description":"Filter to tasks linked to this CRM contact.","name":"contact_id","in":"query"},{"schema":{"type":"string","description":"Filter to tasks linked to this CRM deal."},"required":false,"description":"Filter to tasks linked to this CRM deal.","name":"deal_id","in":"query"},{"schema":{"type":"string","description":"Pass 'me' to filter to tasks the caller is subscribed to."},"required":false,"description":"Pass 'me' to filter to tasks the caller is subscribed to.","name":"subscribed","in":"query"},{"schema":{"type":"string","description":"Pass 'true' to filter to tasks assigned to AI coworkers managed by the caller."},"required":false,"description":"Pass 'true' to filter to tasks assigned to AI coworkers managed by the caller.","name":"managed_coworkers","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Pass 'true' to include archived tasks (default: hidden)."},"required":false,"description":"Pass 'true' to include archived tasks (default: hidden).","name":"show_archived","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Pass 'true' to filter to tasks with no project_id."},"required":false,"description":"Pass 'true' to filter to tasks with no project_id.","name":"untriaged","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Pass 'true' to filter out tasks blocked via task_relations."},"required":false,"description":"Pass 'true' to filter out tasks blocked via task_relations.","name":"hide_blocked","in":"query"},{"schema":{"$ref":"#/components/schemas/TaskListSort"},"required":false,"description":"Sort order for `GET /api/tasks`. `updated_at` (recently-touched first) is the default; `sort_order` for board / drag-reorder; `created_at` for chronology; `due_date` for deadline proximity; `priority` for urgency ranking.","name":"sort","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor`."},"required":false,"description":"Opaque cursor from a prior `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"Alias for `limit`."},"required":false,"description":"Alias for `limit`.","name":"max_results","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Offset-based pagination fallback."},"required":false,"description":"Offset-based pagination fallback.","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Response body for `GET /api/tasks`."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_task","tags":["Tasks"],"description":"Create a new task. Auto-subscribes the creator and (if assigned) the assignee. Auto-sets SLA due date when priority is set without an explicit due_date. Auto-logs a CRM activity if linked to a contact.","x-tool":{"expose":["all","automations"]},"x-cli":{"command":"tasks create","aliases":["task add"],"output":{"successMessage":"Task created: {task.id} — {task.title}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskCreateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Response body for `POST /api/tasks`. Wrapped in `{ task }` for legacy compatibility."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/labels":{"post":{"operationId":"tasks_labels_assign","tags":["Tasks"],"description":"Assign a label to a task. Returns the task's full label list.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks labels assign"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskLabelAssignInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskLabelListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/labels/{labelId}":{"delete":{"operationId":"tasks_labels_remove","tags":["Tasks"],"description":"Remove a label assignment from a task. Returns the task's remaining label list.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks labels remove"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/TaskLabelId"},"required":true,"name":"labelId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskLabelListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/subscriptions":{"get":{"operationId":"tasks_subscriptions_list","tags":["Tasks"],"description":"List all users subscribed to a task (with the reason each is subscribed).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks subscriptions list"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSubscriptionListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/subscribe":{"post":{"operationId":"tasks_subscribe","tags":["Tasks"],"description":"Subscribe a user to a task (reason: 'manual'). Defaults to the caller; pass an optional JSON `{ user_id }` to subscribe another user who has access to the task.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks subscribe"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskSubscribeBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSubscriptionWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"tasks_unsubscribe","tags":["Tasks"],"description":"Unsubscribe the current user from a task.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks unsubscribe","output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskUnsubscribeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/subscriptions/{userId}":{"delete":{"operationId":"tasks_remove_subscriber","tags":["Tasks"],"description":"Remove another user's subscription from a task. Requires task access.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks remove-subscriber","output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskUnsubscribeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/subscription-status":{"get":{"operationId":"tasks_subscription_status","tags":["Tasks"],"description":"Check whether the current user is subscribed to a task (and the reason if so).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks subscription-status"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSubscriptionStatusResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/pr-links":{"get":{"operationId":"tasks_pr_links","tags":["Tasks"],"description":"List GitHub pull requests linked to a task (via the integration-links service).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks pr-links","output":{"format":"table"}},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskPrLinksResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/subtasks":{"get":{"operationId":"tasks_subtasks","tags":["Tasks"],"description":"List immediate subtasks of a task (`parent_task_id = :id`).","x-tool":{"expose":["mcp"]},"x-cli":{"command":"tasks subtasks"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Max items to return (default 50, max 200)."},"required":false,"description":"Max items to return (default 50, max 200).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_subtask","tags":["Tasks"],"description":"Create a subtask under the given parent task. Equivalent to `POST /api/tasks` with `parent_task_id` pre-filled from the URL parameter.","x-tool":{"expose":["mcp","automations"]},"x-cli":{"command":"tasks subtasks create"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskCreateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Response body for `POST /api/tasks`. Wrapped in `{ task }` for legacy compatibility."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{task_id}/comments":{"get":{"operationId":"list_task_comments","tags":["Tasks"],"description":"List threaded comments on a task. Top-level comments carry their replies inline.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks comments list","output":{"format":"object"}},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"},{"schema":{"type":"string","description":"Max items to return (per-endpoint default/cap)."},"required":false,"description":"Max items to return (per-endpoint default/cap).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskCommentListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_task_comment","tags":["Tasks"],"description":"Add a comment to a task. Pass `parent_id` to reply to an existing comment. Auto-subscribes the commenter and notifies subscribers.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks comments create"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskCommentCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskComment"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{task_id}/comments/{comment_id}":{"patch":{"operationId":"update_task_comment","tags":["Tasks"],"description":"Edit or resolve a task comment. Only the comment author, task creator, or assignee may edit.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks comments update"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"comment_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskCommentUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskComment"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_task_comment","tags":["Tasks"],"description":"Delete a task comment. Only the comment author, task creator, or assignee may delete. Cascades to replies.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks comments delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"comment_id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{task_id}/comments/{comment_id}/reactions":{"post":{"operationId":"add_task_comment_reaction","tags":["Tasks"],"description":"Add an emoji reaction to a task comment. Idempotent per (user, emoji). Returns the comment's updated reaction aggregate.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks comments react"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"comment_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentReactionInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CommentReactionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{task_id}/comments/{comment_id}/reactions/{emoji}":{"delete":{"operationId":"remove_task_comment_reaction","tags":["Tasks"],"description":"Remove the caller's emoji reaction from a task comment. Returns the comment's updated reaction aggregate.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks comments unreact"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"comment_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"emoji","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CommentReactionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{task_id}/timer/start":{"post":{"operationId":"start_task_timer","tags":["Tasks"],"description":"Start a time-tracking timer on a task for the current user. If another timer is already running for this user, it is stopped automatically (only one active timer per user).","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks timer start"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskTimeEntryWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{task_id}/timer/stop":{"post":{"operationId":"stop_task_timer","tags":["Tasks"],"description":"Stop the current user's active timer. The duration is accumulated onto the task's time_spent_minutes total. Returns null if no timer is active.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks timer stop"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskTimeEntryWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{task_id}/time-entries":{"get":{"operationId":"list_task_time_entries","tags":["Tasks"],"description":"List all time entries for a task (ordered newest first). Each entry includes user, started_at, stopped_at, duration_minutes.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks time-entries list"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"},{"schema":{"type":"string","description":"Max items to return (per-endpoint default/cap)."},"required":false,"description":"Max items to return (per-endpoint default/cap).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskTimeEntryListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"log_task_time","tags":["Tasks"],"description":"Log a manual time entry against a task (no timer). Use when the user reports time spent after the fact. `duration_minutes` is added to the task's time_spent_minutes total.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks time-entries log"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskTimeEntryCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskTimeEntryWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{task_id}/time-entries/{entry_id}":{"delete":{"operationId":"delete_task_time_entry","tags":["Tasks"],"description":"Delete a time-tracking entry from a task. Only the entry's owner may delete.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"tasks time-entries delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"task_id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"entry_id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/activity":{"get":{"operationId":"tasks_activity","tags":["Tasks"],"description":"List audit-log activity entries for a task (status changes, assignments, comments, label edits, etc.). Paginated via `limit`/`offset`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks activity"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskActivityEntryListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/relations":{"get":{"operationId":"tasks_relations_list","tags":["Tasks"],"description":"List edges in the task-relations graph for a task (related, blocking, blocked_by, duplicate).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks relations list"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Max items to return (per-endpoint default/cap)."},"required":false,"description":"Max items to return (per-endpoint default/cap).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskRelationListEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"tasks_relations_create","tags":["Tasks"],"description":"Create a relation between two tasks. `blocking`/`blocked_by` auto-creates the inverse edge. With `type=duplicate, mark_as_duplicate=true` the source task is cancelled with a system comment.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks relations create"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRelationCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskRelationCreateWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/relations/{relationId}":{"delete":{"operationId":"tasks_relations_delete","tags":["Tasks"],"description":"Delete a task relation edge. Auto-deletes the inverse edge for blocking/blocked_by pairs.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks relations delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"relationId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/restore":{"post":{"operationId":"restore_task","tags":["Tasks"],"description":"Restore a soft-deleted task when the caller has task editor access.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks restore"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskRestoreResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/archive":{"post":{"operationId":"tasks_archive","tags":["Tasks"],"description":"Archive a task. Archived tasks are hidden from default lists but still accessible via filters.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks archive"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskRestoreResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/unarchive":{"post":{"operationId":"tasks_unarchive","tags":["Tasks"],"description":"Un-archive a task (clears `archived_at`).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"tasks unarchive"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskRestoreResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/permanent":{"delete":{"operationId":"permanent_delete_task","tags":["Tasks"],"description":"Permanently delete a trashed task. Allowed for its creator or the manager of its projectless AI-coworker assignee. Cannot be undone.","x-tool":{"expose":[]},"x-cli":{"command":"tasks trash delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/duplicate":{"post":{"operationId":"duplicate_task","tags":["Tasks"],"description":"Clone a task — copies title (appends ' (copy)'), description, priority, project, goal, cycle, estimate, due/start date, recurrence, custom fields, and labels. The clone starts at status 'todo' with a fresh task key.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks duplicate"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskDuplicateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/attachments":{"get":{"operationId":"list_task_attachments","tags":["Tasks"],"description":"List Drive files attached to a task.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks attachments list"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Max items to return (per-endpoint default/cap)."},"required":false,"description":"Max items to return (per-endpoint default/cap).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Number of items to skip (default 0)."},"required":false,"description":"Number of items to skip (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskAttachmentListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"add_task_attachment","tags":["Tasks"],"description":"Attach a Drive file to a task. Idempotent — re-attaching the same file returns the existing row.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks attachments add"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskAttachmentInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskAttachmentResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}/attachments/{attachmentId}":{"delete":{"operationId":"remove_task_attachment","tags":["Tasks"],"description":"Remove a file attachment from a task. Does not delete the Drive file.","x-tool":{"expose":["all"]},"x-cli":{"command":"tasks attachments remove","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"attachmentId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/tasks/{id}":{"get":{"operationId":"get_task","tags":["Tasks"],"description":"Get a single task by ID, including full details: title, description, status, priority, assignee, due date, labels, and subtask count.","x-tool":{"expose":["mcp","assistant","automations"]},"x-cli":{"command":"tasks get"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_task","tags":["Tasks"],"description":"Update a task. Status changes to 'done' auto-spawn the next recurrence (when set), trigger CRM activity logging, and emit task.completed events.","x-tool":{"expose":["all","automations"]},"x-cli":{"command":"tasks update"},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TaskCreateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Response body for `POST /api/tasks`. Wrapped in `{ task }` for legacy compatibility."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"tasks_delete","tags":["Tasks"],"description":"Soft-delete a task. Only the creator can delete.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"tasks delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/TaskId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/templates":{"get":{"operationId":"project_templates_list","tags":["Projects"],"description":"List project templates in the workspace.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects templates list"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectTemplateListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"project_templates_create","tags":["Projects"],"description":"Create a project template.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects templates create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string"},"color":{"type":"string"},"visibility":{"$ref":"#/components/schemas/ProjectVisibility"},"config":{"type":"object","additionalProperties":{}}},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectTemplateEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/templates/{templateId}/apply":{"post":{"operationId":"project_templates_apply","tags":["Projects"],"description":"Create a new project from a template. Pass `{name, description}` in the body.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects templates apply"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"templateId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"}},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/templates/{templateId}":{"get":{"operationId":"project_templates_get","tags":["Projects"],"description":"Get a single project template.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects templates get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"templateId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectTemplateEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"project_templates_delete","tags":["Projects"],"description":"Delete a project template.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects templates delete"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"templateId","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects":{"get":{"operationId":"list_projects","tags":["Projects"],"description":"List all projects in the current workspace. Returns each project with name, icon, color, visibility, and task count. Use this when the user asks to see their projects or find a project by name.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"projects list","output":{"columns":["id","name","visibility"]}},"parameters":[{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_project","tags":["Projects"],"description":"Create a new project to group related tasks. Use this when the user asks to start a new project or create a container for tasks.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"projects create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"icon":{"type":"string"},"color":{"type":"string"},"visibility":{"$ref":"#/components/schemas/ProjectVisibility"},"estimation_scale":{"type":"string","enum":["fibonacci","linear","t-shirt"]}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/{id}":{"get":{"operationId":"get_project","tags":["Projects"],"description":"Get a single project by ID, including task count, visibility, and metadata.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"projects get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_project","tags":["Projects"],"description":"Update a project's name, description, icon, or color. Provide only the fields you want to change.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"projects update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":["string","null"]},"icon":{"type":["string","null"]},"color":{"type":["string","null"]},"visibility":{"$ref":"#/components/schemas/ProjectVisibility"},"auto_archive_days":{"type":["integer","null"]},"notification_channel_id":{"type":["string","null"],"format":"uuid"},"estimation_scale":{"type":"string","enum":["fibonacci","linear","t-shirt"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_project","tags":["Projects"],"description":"Delete a project by ID. Only project admins or workspace admins can delete. Tasks belonging to the project are not deleted — they become unassigned from the project.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"projects delete","confirm":true},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/{id}/members":{"get":{"operationId":"project_members_list","tags":["Projects"],"description":"List project members.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects members list"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectMembersListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"project_members_add","tags":["Projects"],"description":"Add a member. Body `{user_id, role?}`. Notifies the new member.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects members add"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string"},"team_id":{"type":"string"},"role":{"type":"string"}},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/{id}/members/{userId}":{"patch":{"operationId":"project_members_update_role","tags":["Projects"],"description":"Change a member's role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects members update-role"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"project_members_remove","tags":["Projects"],"description":"Remove a member from the project. Notifies the removed user (unless self-removal).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects members remove"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/{project_id}/updates":{"get":{"operationId":"list_project_updates","tags":["Projects"],"description":"List status updates for a project, newest first. Returns the health timeline with author and timestamp.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects updates list"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"project_id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectUpdatesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_project_update","tags":["Projects"],"description":"Post a status update on a project. Use this when the user wants to report progress, flag a risk, or share a status update on a project. The status field captures the health signal (on_track, at_risk, off_track, paused, completed, cancelled).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects updates create"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"project_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/ProjectStatus"},"body":{"type":"string"}},"required":["status"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectUpdateEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/{id}/updates/{updateId}":{"patch":{"operationId":"project_updates_edit","tags":["Projects"],"description":"Edit a status update. Author or admin only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects updates edit"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"updateId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"body":{"type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectUpdateEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"project_updates_delete","tags":["Projects"],"description":"Delete a status update. Author or admin only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects updates delete"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"updateId","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/{id}/notification-preference":{"get":{"operationId":"project_notification_pref_get","tags":["Projects"],"description":"Get the caller's notification preference for the project.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects notification-preference get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectNotificationPreferenceEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"project_notification_pref_set","tags":["Projects"],"description":"Set the caller's notification preference (`level`) for the project.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"projects notification-preference set"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"level":{"type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProjectNotificationPreferenceEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/projects/{id}/github":{"get":{"operationId":"project_github_list","tags":["Projects"],"description":"List GitHub repo mappings for a project, including automation config.","x-cli":{"hidden":true,"command":"projects github list"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GitHubMappingListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"project_github_connect","tags":["Projects"],"description":"Connect a GitHub repo to this project. Each repo can only be connected to one project.","x-cli":{"hidden":true,"command":"projects github connect"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"integration_id":{"type":"string","format":"uuid"},"repo_full_name":{"type":["string","null"],"minLength":1,"default":null},"post_linkback_comments":{"type":"boolean","default":true},"create_autolinks":{"type":"boolean","default":true},"automations":{"type":"object","properties":{"rules":{"type":"array","items":{"type":"object","properties":{"event":{"type":"string","enum":["pr_draft","pr_ready_for_review","pr_merged"]},"target_branch":{"type":["string","null"]},"status_id":{"type":"string","format":"uuid"}},"required":["event","target_branch","status_id"],"additionalProperties":false}}},"additionalProperties":false}},"required":["integration_id"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GitHubMappingEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubMappingConflictError"}}}}}}},"/api/projects/{id}/github/{mappingId}":{"patch":{"operationId":"project_github_update","tags":["Projects"],"description":"Update automation settings for a GitHub repo mapping.","x-cli":{"hidden":true,"command":"projects github update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"mappingId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"post_linkback_comments":{"type":"boolean"},"create_autolinks":{"type":"boolean"},"automations":{"type":"object","properties":{"rules":{"type":"array","items":{"type":"object","properties":{"event":{"type":"string","enum":["pr_draft","pr_ready_for_review","pr_merged"]},"target_branch":{"type":["string","null"]},"status_id":{"type":"string","format":"uuid"}},"required":["event","target_branch","status_id"],"additionalProperties":false}}},"additionalProperties":false}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GitHubMappingEnvelope"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"project_github_disconnect","tags":["Projects"],"description":"Disconnect a GitHub repo from this project.","x-cli":{"hidden":true,"command":"projects github disconnect"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"mappingId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GitHubMappingDeleteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/cycles":{"get":{"operationId":"cycles_list","tags":["Cycles"],"description":"List cycles in the active workspace. `?status=` filters by status; `?limit=` (1–200) and `?offset=` paginate. `has_more` is set when the underlying query returned a hint of more rows.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"cycles list","output":{"columns":["id","name","status","start_date","end_date"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/CycleStatus"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CycleListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"cycles_create","tags":["Cycles"],"description":"Create a new cycle. Body fields: name, start_date, end_date, status?, cooldown_days?, auto_rollover?.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"cycles create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCycleBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Cycle"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/cycles/velocity":{"get":{"operationId":"cycles_velocity","tags":["Cycles"],"description":"Cross-cycle velocity (last N closed cycles). Default `limit=10`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"cycles velocity"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CycleVelocityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/cycles/{id}":{"get":{"operationId":"cycles_get","tags":["Cycles"],"description":"Get one cycle.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"cycles get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Cycle"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"cycles_update","tags":["Cycles"],"description":"Update cycle fields.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"cycles update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCycleBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Cycle"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"cycles_delete","tags":["Cycles"],"description":"Delete a cycle. Tasks attached to the cycle are unlinked, not deleted.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"cycles delete","confirm":true},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/cycles/{id}/analytics":{"get":{"operationId":"cycles_analytics","tags":["Cycles"],"description":"Burndown + summary analytics for the cycle.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"cycles analytics"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CycleAnalytics"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/cycles/{id}/complete":{"post":{"operationId":"cycles_complete","tags":["Cycles"],"description":"Complete a cycle. If `auto_rollover` is set, incomplete tasks are moved to the next cycle.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"cycles complete"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CompleteCycleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/cycles/{id}/tasks":{"post":{"operationId":"cycles_add_tasks","tags":["Cycles"],"description":"Add tasks to the cycle. Body `{task_ids: [...]}`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"cycles add-tasks"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"task_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1}},"required":["task_ids"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CycleTasksMutationResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"cycles_remove_tasks","tags":["Cycles"],"description":"Remove tasks from the cycle. Body `{task_ids: [...]}`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"cycles remove-tasks"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"task_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1}},"required":["task_ids"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CycleTasksMutationResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets":{"get":{"operationId":"list_sheets","tags":["Sheets"],"description":"List the current user's spreadsheets (owned + shared). Convenience alias for `GET /api/documents?type=sheet`. Returns the lightweight `SheetSummary` shape without the structured `data` body — call `GET /api/sheets/:id` to load a specific sheet's tabs/columns/rows.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets list","output":{"columns":["id","title","updated_at"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SheetListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"List of sheets accessible to the caller (owned + shared), filtered to `type: sheet`. Mirrors the `/api/documents` list envelope but without rendering doc or slide rows."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_sheet","tags":["Sheets"],"description":"Create a new spreadsheet. Convenience alias for `POST /api/documents` with `type: \"sheet\"` enforced. Returns the full `Sheet` envelope (id, title, owner, visibility, timestamps, and `data` body) so the caller can immediately read or edit cells without a second round-trip. Optional `content` may be a SheetData JSON object or a string that parses as JSON.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SheetCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/values/append":{"post":{"operationId":"append_sheet_values","tags":["Sheets"],"description":"Append rows of values to a sheet at the first empty row in a range. The server finds the insertion point — no need to read the last row first. Uses OVERWRITE semantics (does not shift existing data).","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets values append"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendValuesInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AppendValuesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/values/batchGet":{"post":{"operationId":"batch_get_sheet_values","tags":["Sheets"],"description":"Fetch multiple disjoint ranges from a spreadsheet in a single request. Avoids N sequential round-trips when reading KPIs from different regions.","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true}},"x-cli":{"command":"sheets values batchGet"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRangesInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/BatchGetResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/values/batchClear":{"post":{"operationId":"batch_clear_sheet_values","tags":["Sheets"],"description":"Clear all cell values in multiple ranges atomically. Sets cells to null without removing rows or columns. Useful for resetting template sheets or clearing data regions.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets values batchClear"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRangesInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/BatchClearResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/sheets/copy":{"post":{"operationId":"copy_sheet_to","tags":["Sheets"],"description":"Copy a sheet tab from one spreadsheet to another. Deep-copies columns, rows, formulas, formatting, and merges. Cross-document formulas will show as #REF!. Requires viewer access on source and editor access on destination.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets tab copy"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopySheetInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CopySheetResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/named-ranges":{"post":{"operationId":"create_named_range","tags":["Sheets"],"description":"Create a named range on a spreadsheet. Named ranges let formulas reference a range by name (e.g., =SUM(Revenue) instead of =SUM(Sheet1!B2:B100)). Accepts A1 notation for the range.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets named-ranges create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NamedRangeInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NamedRange"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"list_named_ranges","tags":["Sheets"],"description":"List all named ranges defined on a spreadsheet. Returns each range's name and A1 notation range specification.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets named-ranges list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NamedRangesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/named-ranges/{name}":{"delete":{"operationId":"delete_named_range","tags":["Sheets"],"description":"Delete a named range from a spreadsheet by name. Names are matched case-insensitively.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets named-ranges delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"name","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["deleted"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_named_range","tags":["Sheets"],"description":"Update where a named range points to. Use after sheet structure changes (e.g., inserted rows) to re-point a named range at the correct cells. Names are matched case-insensitively.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets named-ranges update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"name","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateNamedRangeInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NamedRange"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/validations":{"post":{"operationId":"set_sheet_validation","tags":["Sheets"],"description":"Set a data validation rule on a cell range in a spreadsheet. Supports dropdown lists (ONE_OF_LIST), number constraints (NUMBER_BETWEEN, NUMBER_GREATER, NUMBER_LESS, NUMBER_EQUAL), text matching (TEXT_CONTAINS, TEXT_NOT_CONTAINS, TEXT_EQ), date constraints (DATE_AFTER, DATE_BEFORE, DATE_BETWEEN), and custom formulas (CUSTOM_FORMULA). When strict is true, API writes that violate the rule are rejected.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets validations set"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SheetValidation"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"clear_sheet_validation","tags":["Sheets"],"description":"Remove a data validation rule from a spreadsheet by range. The range is matched after normalization (sheet tab defaults to Sheet1 if not specified). Returns 404 if no rule exists for that range.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets validations clear"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClearValidationInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"cleared":{"type":"boolean","enum":[true]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["cleared"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"list_sheet_validations","tags":["Sheets"],"description":"List all data validation rules on a spreadsheet. Returns each rule's range (A1 notation) and rule definition (type, values, strict, inputMessage).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets validations list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ValidationsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/conditional-formats":{"get":{"operationId":"list_conditional_formats","tags":["Sheets"],"description":"List all conditional formatting rules on a spreadsheet. Returns each rule's ID, ranges (A1 notation), and either a booleanRule (condition + format) or a gradientRule (minpoint/midpoint/maxpoint).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets conditional-formats list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConditionalFormatsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"add_conditional_format","tags":["Sheets"],"description":"Add a conditional formatting rule to a spreadsheet. Provide either a booleanRule (highlight cells matching a condition like NUMBER_GREATER, TEXT_CONTAINS, BLANK, CUSTOM_FORMULA) or a gradientRule (color scale across a range). The server generates a unique ID for the rule.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets conditional-formats add"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConditionalFormatInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConditionalFormatRule"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/conditional-formats/{ruleId}":{"patch":{"operationId":"update_conditional_format","tags":["Sheets"],"description":"Update a conditional formatting rule on a spreadsheet by its ID. Partial update — provide only the fields to change (ranges, booleanRule, or gradientRule). Setting booleanRule replaces any existing gradientRule and vice versa.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets conditional-formats update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"ruleId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConditionalFormatInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConditionalFormatRule"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_conditional_format","tags":["Sheets"],"description":"Delete a conditional formatting rule from a spreadsheet by its ID. Returns 200 on success, 404 if the rule does not exist.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets conditional-formats delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"ruleId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["deleted"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/protected-ranges":{"get":{"operationId":"list_protected_ranges","tags":["Sheets"],"description":"List all protected ranges on a spreadsheet. Returns each range with its ID, A1 range, description, warningOnly flag, and editorUserIds allowlist.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets protected-ranges list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProtectedRangesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"protect_range","tags":["Sheets"],"description":"Protect a range in a spreadsheet. Protected ranges restrict editing to users in editorUserIds. Set warningOnly to true for soft warnings instead of hard blocks.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets protected-ranges add"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedRangeInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ProtectedRange"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/protected-ranges/{rangeId}":{"delete":{"operationId":"unprotect_range","tags":["Sheets"],"description":"Remove a protected range from a spreadsheet by its ID. Returns 200 on success, 404 if the range does not exist.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets protected-ranges delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"rangeId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["deleted"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}":{"get":{"operationId":"get_sheet","tags":["Sheets"],"description":"Get a spreadsheet's structured data including columns, rows, and formulas. Returns the `Sheet` envelope: top-level metadata (id, title, owner, visibility, timestamps) plus the structured sheet body nested under `data` (see `SheetData`). Read tabs/columns/rows as `response.data.tabs[…]`, not at the response root. If the user is currently viewing a sheet, use the sheet ID from the page context.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/data":{"get":{"operationId":"sheet_get_data","tags":["Sheets"],"description":"Get the spreadsheet as the structured JSON canvas. Returns the `Sheet` envelope: top-level metadata plus the structured sheet body nested under `data` (see `SheetData`). Read tabs/columns/rows as `response.data.tabs[…]`, not at the response root.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets get-data"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/range":{"get":{"operationId":"get_sheet_range","tags":["Sheets"],"description":"Get a rectangular range of cell values from a sheet. Useful when you only need a slice of a large sheet (max 10,000 cells). Returns a 2D array of values plus the resolved start/end column letters and row numbers. Use orientation=COLUMNS to get column-major arrays (each inner array is one column). valueRenderOption controls how cells render: STORED (default) returns stored values verbatim — formula cells return the formula string; FORMULA forces formula strings; EVALUATED runs the server-side formula engine and returns computed values (e.g., '=SUM(A1:A3)' becomes 6). Same-sheet refs across tabs (Sheet2!A1) resolve when evaluating; IMPORTRANGE returns #REF! (server cannot recurse cross-document).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets range"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"A1-style range — `Sheet1!A1:D10`. Required."},"required":false,"description":"A1-style range — `Sheet1!A1:D10`. Required.","name":"spec","in":"query"},{"schema":{"type":"string","description":"ROWS (default) or COLUMNS."},"required":false,"description":"ROWS (default) or COLUMNS.","name":"orientation","in":"query"},{"schema":{"type":"string","description":"STORED (default), FORMULA, or EVALUATED."},"required":false,"description":"STORED (default), FORMULA, or EVALUATED.","name":"valueRenderOption","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RangeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/cells":{"patch":{"operationId":"sheet_update_cells","tags":["Sheets"],"description":"Update specific cells in a spreadsheet. Provide an array of cell updates, each specifying the row index (0-based), column ID, and new value. If the user is currently viewing a sheet, use the sheet ID from the page context.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets cells update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Pass `true` to echo the updated cell values in the response."},"required":false,"description":"Pass `true` to echo the updated cell values in the response.","name":"includeValuesInResponse","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCellsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SheetWithUpdatedCells"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/merges":{"patch":{"operationId":"update_sheet_merges","tags":["Sheets"],"description":"Update the merged cell ranges for a sheet tab. Replaces all existing merges on the tab. Pass an empty `merges` array to clear all merges.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets merges update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergesInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/tabs":{"post":{"operationId":"add_sheet_tab","tags":["Sheets"],"description":"Add a new tab to a sheet. Auto-generates the name if not provided.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets tab add"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TabInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/tabs/{tab_name}":{"patch":{"operationId":"rename_sheet_tab","tags":["Sheets"],"description":"Rename an existing sheet tab.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets tab rename"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"tab_name","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameTabInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"remove_sheet_tab","tags":["Sheets"],"description":"Remove a sheet tab by name. Cannot remove the last remaining tab.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets tab remove"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"tab_name","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"replace_sheet_tab","tags":["Sheets"],"description":"Replace a sheet tab's columns and/or rows wholesale. Use for bulk data replacement. Use update_cells for surgical edits.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets tab replace"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"tab_name","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceTabInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/columns":{"post":{"operationId":"add_sheet_column","tags":["Sheets"],"description":"Add a column to a sheet tab.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets columns add"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddColumnInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/columns/{column_id}":{"delete":{"operationId":"remove_sheet_column","tags":["Sheets"],"description":"Remove a column from a sheet tab by column ID. Use `?sheet=` to target a tab other than the first.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets columns remove"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"column_id","in":"path"},{"schema":{"type":"string","description":"Tab name; defaults to the first tab."},"required":false,"description":"Tab name; defaults to the first tab.","name":"sheet","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/rows":{"post":{"operationId":"add_sheet_rows","tags":["Sheets"],"description":"Append rows to a sheet tab. Each row is an object keyed by column ID. Example: [{\"A\": \"Widget\", \"B\": 9.99}].","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets rows add"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddRowsInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_sheet_rows","tags":["Sheets"],"description":"Delete rows from a sheet tab by 0-based index.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets rows delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRowsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/sort":{"post":{"operationId":"sort_sheet","tags":["Sheets"],"description":"Sort a tab's rows by one column. Re-anchors formulas, comment anchors, and cell notes so nothing orphans.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets sort"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SortSheetInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/move-column":{"post":{"operationId":"move_sheet_column","tags":["Sheets"],"description":"Move a column to a new position. Rewrites dependent formulas so they follow the moved column to the same logical data, and re-anchors notes and comment anchors.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets move-column"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveColumnInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Sheet"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Sheet GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, owner, visibility, timestamps); the structured sheet body — tabs, columns, rows, formulas — is nested under `data` (see `SheetData`). SDK consumers must read cells/columns/tabs as `response.data.tabs[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/data-connectors":{"get":{"operationId":"list_data_connectors","tags":["Sheets"],"description":"List data connectors registered on a sheet. Connectors fetch data from external sources (URL, CSV, etc.) into specific cells.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets connectors list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConnectorListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_data_connector","tags":["Sheets"],"description":"Create a new data connector that fetches data into specific cells of a sheet. After creating, call run_data_connector to execute it.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets connectors create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConnectorInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConnectorResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/data-connectors/{connector_id}":{"get":{"operationId":"get_data_connector","tags":["Sheets"],"description":"Get a single data connector by ID, including its config and last-run status.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets connectors get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"connector_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConnectorResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_data_connector","tags":["Sheets"],"description":"Update a data connector's name, config, target cells, or refresh schedule.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets connectors update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"connector_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConnectorInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConnectorResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_data_connector","tags":["Sheets"],"description":"Delete a data connector. Does not affect the cells it previously wrote to.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets connectors delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"connector_id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/data-connectors/{connector_id}/run":{"post":{"operationId":"run_data_connector","tags":["Sheets"],"description":"Execute a data connector: fetch the latest data and write it to the connector's target cells. Returns the connector with updated last-run metadata.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"sheets connectors run"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"connector_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConnectorResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/data-connectors/{connector_id}/run-history":{"get":{"operationId":"list_data_connector_run_history","tags":["Sheets"],"description":"List recent execution history for a data connector. Each row records one manual or scheduled run with its status, duration, row count, and error (if any). Use the `limit` query param to cap the page size (default 20, max 100). Results are ordered by completion time, newest first.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets connectors run-history"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"connector_id","in":"path"},{"schema":{"type":"string","description":"Page size, integer 1–100 (default 20)."},"required":false,"description":"Page size, integer 1–100 (default 20).","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConnectorRunHistoryResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/pivot-tables":{"get":{"operationId":"list_pivot_tables","tags":["Sheets"],"description":"List every pivot table across every tab of the sheet. Each entry is annotated with the `tab` name it lives in.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets pivot list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PivotListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_pivot_table","tags":["Sheets"],"description":"Create a pivot table from sheet data. A new sheet tab is automatically created to hold the pivot. Specify the source data range, which columns to group by (rows/columns), and which columns to aggregate (values).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets pivot create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PivotTableInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PivotTableResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/pivot-tables/{pivot_id}/computed":{"get":{"operationId":"compute_pivot_table","tags":["Sheets"],"description":"Compute the result of a persisted pivot table — applies row/column grouping, value aggregation, sort orders, and any matching slicer filters, and returns the rendered cells. The pivot config itself (row/column/value fields, source range) is not modified.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets pivot compute"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"pivot_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PivotComputeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/pivot-tables/{pivot_id}":{"patch":{"operationId":"update_pivot_table","tags":["Sheets"],"description":"Patch a pivot table's config — source range, row/column/value fields, totals toggles, source-tab name. Only the fields you send are updated; the rest of the pivot config is preserved. Pass a `tab` field to move the pivot to a different tab.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets pivot update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"pivot_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PivotUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PivotPatchResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_pivot_table","tags":["Sheets"],"description":"Remove a pivot table from the sheet. The host tab itself stays — only the pivot row in `pivotTables[]` is removed. Returns `{ deleted: true }` on success.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets pivot delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"pivot_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["deleted"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/charts":{"get":{"operationId":"list_charts","tags":["Sheets"],"description":"List every chart across every tab of the sheet. Each entry is annotated with the `tab` name it lives in.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets charts list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChartListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_chart","tags":["Sheets"],"description":"Embed a chart on a tab of the sheet. Charts visualize a rectangular data range — pick a chart type (bar / line / pie / scatter), the source range, and an overlay position. Returns the created chart with its server-assigned id.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets charts create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChartResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/charts/{chart_id}":{"patch":{"operationId":"update_chart","tags":["Sheets"],"description":"Patch a chart's config — type, title, data range, overlay position, or series styling. Only the fields you send are updated; the rest of the chart config is preserved.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets charts update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"chart_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChartResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_chart","tags":["Sheets"],"description":"Remove a chart from the sheet. Returns `{ deleted: true }` on success.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets charts delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"chart_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["deleted"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/slicers":{"get":{"operationId":"list_slicers","tags":["Sheets"],"description":"List every slicer across every tab of the sheet. Slicers are interactive filter widgets that filter pivots / charts on a shared source range. Each entry is annotated with the `tab` name it lives in.","x-tool":{"expose":["all"]},"x-cli":{"command":"sheets slicers list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlicerListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_slicer","tags":["Sheets"],"description":"Add a slicer to a tab of the sheet. Slicers filter pivot tables and charts that share the same source range by the values selected for a single column. `selectedValues: null` passes everything through; `[]` filters everything out; a non-empty array passes only those values. Returns the created slicer with its server-assigned id.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets slicers create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlicerCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlicerResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sheets/{id}/slicers/{slicer_id}":{"patch":{"operationId":"update_slicer","tags":["Sheets"],"description":"Patch a slicer's config — source range, target column, selected values, overlay position, or title. Only the fields you send are updated; the rest of the slicer config is preserved.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets slicers update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"slicer_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlicerUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlicerResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_slicer","tags":["Sheets"],"description":"Remove a slicer from the sheet. Returns `{ deleted: true }` on success.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"sheets slicers delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"slicer_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["deleted"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/layouts":{"get":{"operationId":"slide_layouts_list","tags":["Slides"],"description":"List the slide-level layouts the editor knows about.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides layouts","output":{"columns":["id","name"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideLayoutsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/templates":{"get":{"operationId":"slide_templates_list","tags":["Slides"],"description":"List the built-in slide deck templates.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides templates","output":{"columns":["id","name","description"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideTemplatesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/stars":{"get":{"operationId":"slide_stars_list","tags":["Slides"],"description":"List IDs of slide decks the current user has starred.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides stars"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideStarIdsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides":{"post":{"operationId":"create_presentation","tags":["Slides"],"description":"Create a new presentation deck. Returns the created `SlideDeck` envelope with one blank slide. This is the Slides-native alias for `POST /api/documents` with `type:'slide'` — both produce the same result.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePresentationInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/star":{"post":{"operationId":"slide_star","tags":["Slides"],"description":"Star a deck. Idempotent — re-starring is a no-op.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides star"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideStarResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"slide_unstar","tags":["Slides"],"description":"Unstar a deck. Idempotent.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides unstar"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/data":{"get":{"operationId":"get_presentation","tags":["Slides"],"description":"Get a presentation's full data including all slides and their elements. Returns the `SlideDeck` envelope: top-level metadata (id, title, slide_count, owner, visibility, timestamps) plus the structured deck body nested under `data` (see `SlideDeckData`). Read settings/slides/masterSlides as `response.data.slides[…]`, not at the response root. If the user is currently viewing a presentation, use the presentation ID from the page context.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/slides":{"post":{"operationId":"add_slide","tags":["Slides"],"description":"Add a new slide to an existing presentation. Provide the slide as a JSON object with layout, background, and elements. Each element has a type (text, image, shape, table, video, group), position (x, y), size (w, h), and type-specific properties. IMPORTANT: Create SEPARATE text elements for each visual block (title, each bullet point, each paragraph). Do NOT put multiple lines or bullet points in a single text element — create one element per line with proper positioning. Use bullet character '•' instead of markdown '*' or '-'. Set fontSize and fontWeight per element for visual hierarchy. If the user is currently viewing a presentation, use the presentation ID from the page context.","x-tool":{"expose":["all"]},"x-cli":{"command":"slides add"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSlideInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/slides/{index}":{"patch":{"operationId":"update_slide","tags":["Slides"],"description":"Update an existing slide in a presentation. Specify the slide by its 0-based index. You can update the slide properties (background, notes) and/or replace its elements. If the user is currently viewing a presentation, use the presentation ID from the page context.","x-tool":{"expose":["all"]},"x-cli":{"command":"slides update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"index","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSlideInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"remove_slide","tags":["Slides"],"description":"Remove the slide at the given zero-based index.","x-tool":{"expose":["all"]},"x-cli":{"command":"slides remove"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"index","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/slides/{index}/apply-master":{"post":{"operationId":"apply_master_to_slide","tags":["Slides"],"description":"Link a master slide to a specific slide by 0-based index. The slide stores a by-reference link, retains its existing elements as child-owned content, and clears prior master-element override markers. Current master elements inherit at render time and future master edits flow through automatically.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides apply-master"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"index","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyMasterInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/slides/{index}/group":{"post":{"operationId":"group_slide_elements","tags":["Slides"],"description":"Group existing top-level elements on a slide into a single group. The group's bounding box is computed automatically from the children. Children positions become relative to the group origin. At least 2 element IDs required. A named element may itself be a group — `groupElements` validates only that each id is top-level on the slide, so groups nest.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides group"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"index","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeckWithGroup"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/slides/{index}/ungroup/{group_id}":{"post":{"operationId":"ungroup_slide_elements","tags":["Slides"],"description":"Dissolve a group element on a slide back into independent top-level elements. Children positions are converted from group-relative to absolute coordinates. The group element is removed and its former children become top-level elements on the slide.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides ungroup"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"index","in":"path"},{"schema":{"type":"string"},"required":true,"name":"group_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeckWithPromotedElements"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/slides/{index}/duplicate":{"post":{"operationId":"duplicate_slide","tags":["Slides"],"description":"Deep-copy a slide within the same deck. The duplicate is inserted immediately after the source slide. All elements (including group children) receive new unique IDs to avoid collisions. Useful for template-based workflows: duplicate a template slide, then update the copy with new content.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides duplicate"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"index","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeckWithDuplicatedSlide"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/slides/{index}/thumbnail":{"get":{"operationId":"get_slide_thumbnail","tags":["Slides"],"description":"Get a PNG thumbnail image of a specific slide. Returns thumbnail metadata (width, height). The actual PNG is served at the URL. Sizes: small (200px), medium (800px, default), large (1600px).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"slides thumbnail"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"index","in":"path"},{"schema":{"type":"string","description":"small (200px), medium (800px, default), or large (1600px)."},"required":false,"description":"small (200px), medium (800px, default), or large (1600px).","name":"size","in":"query"},{"schema":{"type":"string","description":"Opaque client cache-bust version."},"required":false,"description":"Opaque client cache-bust version.","name":"v","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/slides/{index}/detach-master":{"post":{"operationId":"detach_master_from_slide","tags":["Slides"],"description":"Detach a slide from its master. The slide keeps its current rendered elements but no longer inherits from the master.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides detach-master"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"index","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/transition-all":{"post":{"operationId":"apply_transition_to_all","tags":["Slides"],"description":"Apply a slide transition to every slide in the deck. Set transition.type to 'none' to clear transitions on all slides. Prefer duration_s (float seconds, 0.1–10); legacy speed presets map to slow=1.0s, medium=0.5s, fast=0.3s.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides transition-all"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransitionAllInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/reorder":{"patch":{"operationId":"reorder_slides","tags":["Slides"],"description":"Reorder slides in a presentation. Provide the full list of slide indices in the desired new order. Example: [2, 0, 1, 3] moves the third slide to the front.","x-tool":{"expose":["all"]},"x-cli":{"command":"slides reorder"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/settings":{"patch":{"operationId":"update_deck_settings","tags":["Slides"],"description":"Update deck-level settings: theme, aspect ratio, default background. Changing aspect ratio rescales every slide's elements proportionally; changing default background updates slides currently using the old default.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides settings update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeckSettingsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/masters":{"get":{"operationId":"list_slide_masters","tags":["Slides"],"description":"List the master slide templates registered on a presentation. Child slides link to masters by reference and resolve current master elements at render time, beneath child-owned elements.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides masters list"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MasterSlidesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_slide_master","tags":["Slides"],"description":"Create a new master slide for a deck. If no elements are provided, a default Title + Subtitle layout is used.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides masters create"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMasterInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MasterSlide"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/masters/{master_id}":{"patch":{"operationId":"update_slide_master","tags":["Slides"],"description":"Update a master slide's name, background, or elements. Slides using the master resolve the updated elements by reference.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides masters update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"master_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMasterInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MasterSlide"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_slide_master","tags":["Slides"],"description":"Delete an unused master slide. Returns 409 with the referencing slide count while the master is in use.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides masters delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"master_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MasterSlideInUseError"}}}}}}},"/api/slides/{id}/masters/{master_id}/detach-and-delete":{"post":{"operationId":"detach_and_delete_slide_master","tags":["Slides"],"description":"Materialize inherited elements into every referencing slide, then delete the master in one deck write.","x-cli":{"command":"slides masters detach-and-delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"master_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/find-replace":{"post":{"operationId":"find_and_replace_in_deck","tags":["Slides"],"description":"Find and replace text across all slides in a presentation. Searches every text element and table cell on every slide. Useful for template-based workflows: create a deck from a template with placeholders like {{company_name}}, then replace them programmatically. Plain string matching only (no regex).","x-tool":{"expose":["all"]},"x-cli":{"command":"slides find-replace"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindReplaceInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeckWithOccurrences"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/replace-shapes-with-image":{"post":{"operationId":"replace_shapes_with_image","tags":["Slides"],"description":"Replace text placeholder elements with an image across all slides. Finds text elements whose text matches the search string and replaces them with image elements at the same position and size. Like Google Slides ReplaceAllShapesWithImage — useful for template-based workflows where placeholder shapes like {{logo}} are swapped with actual images.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"slides replace-shapes-with-image"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceShapesInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeckWithReplacements"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/thumbnail":{"get":{"operationId":"get_cover_thumbnail","tags":["Slides"],"description":"Get a PNG thumbnail of the first slide (cover image) of a presentation. Convenience endpoint — equivalent to get_slide_thumbnail with index 0.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"slides cover"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"small (200px), medium (800px, default), or large (1600px)."},"required":false,"description":"small (200px), medium (800px, default), or large (1600px).","name":"size","in":"query"},{"schema":{"type":"string","description":"Opaque client cache-bust version."},"required":false,"description":"Opaque client cache-bust version.","name":"v","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/slides/{id}/apply-template":{"post":{"operationId":"slide_apply_template","tags":["Slides"],"description":"Apply a built-in slide template to the deck or to a single slide.","x-tool":{"expose":["all"]},"x-cli":{"command":"slides apply-template"},"parameters":[{"schema":{"$ref":"#/components/schemas/DocumentId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyTemplateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlideDeck"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Envelope response shape returned by every Slides GET/POST/PATCH endpoint. Top-level fields carry document metadata (id, title, slide_count, owner, visibility, timestamps, can_edit); the structured deck body — settings, slides, master slides — is nested under `data` (see `SlideDeckData`). SDK consumers must read settings/slides as `response.data.slides[…]`, not at the response root."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/workspace-users":{"get":{"operationId":"list_crm_workspace_users","tags":["CRM"],"description":"List all users (humans and agents) in the current workspace who can own CRM records. Use before assigning contacts or deals to a specific owner_id.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm workspace-users list","output":{"columns":["id","display_name","type","email"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmWorkspaceUsersListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/address-book":{"get":{"operationId":"list_address_book","tags":["CRM"],"description":"List the caller's address book: the shared CRM contacts they can see unioned with their own privately captured addresses, deduplicated on email with the shared record winning. Use this to resolve a recipient the user has written to before instead of asking them to retype an address. Private entries are never visible to another member.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm address-book list","output":{"columns":["email","name","source"]}},"parameters":[{"schema":{"type":"string","maxLength":200},"required":false,"name":"q","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AddressBookListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/address-book/purge":{"post":{"operationId":"purge_address_book_email","tags":["CRM"],"description":"Erase an address from every member's private address book, workspace-wide. The data-subject erasure path for the private tier (agents/LEGAL.md L10) — the tier is replicated per user, so purging one member's copy would leave the rest. Admin only; it deletes from books the caller cannot otherwise read, and discloses only a count.","x-tool":{"expose":[]},"x-cli":{"command":"crm address-book purge","confirm":true,"output":{"successMessage":"Purged {purged} address(es)"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressBookPurgeInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AddressBookPurgeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/user-contacts/{id}/promotion-candidates":{"get":{"operationId":"list_promotion_candidates","tags":["CRM"],"description":"List the shared CRM records a private address could be promoted into. A workspace may already hold several records for one address, so the caller chooses; an empty list means promotion will create a new record.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"crm user-contacts promotion-candidates","output":{"format":"object"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PromotionCandidatesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/user-contacts/{id}/promote":{"post":{"operationId":"promote_user_contact","tags":["CRM"],"description":"Promote a private address into the shared workspace CRM. Carries identity fields only and never moves activities — the caller's mail and meetings stay private. Irreversible: the record becomes visible to every workspace member.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"crm user-contacts promote","confirm":true,"output":{"successMessage":"Added to CRM: {contact_id}"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoteUserContactInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PromoteUserContactResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/property-definitions":{"get":{"operationId":"list_crm_property_definitions","tags":["CRM"],"description":"List the workspace's typed custom-property definitions for contacts and deals, including relation properties that link a record to another contact, company, or deal. Optionally filter by entity_type.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm property-definitions list","output":{"columns":["id","entity_type","key","label","field_type","relation_target"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/CrmPropertyEntityType"},"required":false,"name":"entity_type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmPropertyDefinitionsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_crm_property_definition","tags":["CRM"],"description":"Define a typed custom property for contacts or deals. field_type 'relation' (with relation_target contact|company|deal) makes the property a link to another record: values written to custom_properties under this key must be the id of an existing record of the target type.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm property-definitions create","output":{"successMessage":"Property definition created: {definition.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmPropertyDefinitionCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmPropertyDefinitionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/property-definitions/{id}":{"patch":{"operationId":"update_crm_property_definition","tags":["CRM"],"description":"Update a custom-property definition's label or select options.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm property-definitions update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmPropertyDefinitionUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmPropertyDefinitionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_crm_property_definition","tags":["CRM"],"description":"Delete a custom-property definition. Existing custom_properties values are left in place; they simply stop being typed.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm property-definitions delete","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/metrics":{"get":{"operationId":"get_crm_metrics","tags":["CRM"],"description":"Get pipeline metrics summary: total open deals, total deal value, win rate, deals won/lost, and recent activity counts. Useful for high-level pipeline health questions.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm metrics"},"parameters":[{"schema":{"type":"string","enum":["this_month","this_quarter","this_year"]},"required":false,"name":"period","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmMetricsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/reports":{"get":{"operationId":"get_crm_reports","tags":["CRM"],"description":"Get the workspace-wide CRM reports dashboard: revenue, leaderboards, stage funnel, deals-by-source. Broader than get_crm_metrics/get_crm_analytics, which are owner-scoped.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm reports"},"parameters":[{"schema":{"type":"string","enum":["ytd","this_quarter","this_month","all_time"]},"required":false,"name":"period","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmReportsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts":{"get":{"operationId":"list_contacts","tags":["CRM"],"description":"List CRM contacts. Supports filtering by type, lifecycle stage, owner, and text search. Returns contacts with id, name, email, phone, type, lifecycle_stage, company, and timestamps. Use this when the user asks to see their contacts, find a person, or list companies. Also use this with the 'q' parameter to search for existing contacts BEFORE creating new ones to prevent duplicates.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts list","output":{"columns":["id","name","email","type","lifecycle_stage","lead_score"]}},"parameters":[{"schema":{"type":"string","enum":["person","company"],"description":"Filter by contact type (`person` or `company`)."},"required":false,"description":"Filter by contact type (`person` or `company`).","name":"type","in":"query"},{"schema":{"type":"string","enum":["subscriber","lead","mql","sql","opportunity","customer","evangelist"],"description":"Filter by funnel stage."},"required":false,"description":"Filter by funnel stage.","name":"lifecycle_stage","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Filter to contacts owned by this user."},"required":false,"description":"Filter to contacts owned by this user.","name":"owner_id","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Filter to contacts belonging to this company."},"required":false,"description":"Filter to contacts belonging to this company.","name":"company_id","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Filter to contacts that are members of this contact group."},"required":false,"description":"Filter to contacts that are members of this contact group.","name":"group_id","in":"query"},{"schema":{"type":"string","description":"Free-text search across name/email/phone."},"required":false,"description":"Free-text search across name/email/phone.","name":"q","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a prior `next_cursor` for page-after-page walking."},"required":false,"description":"Opaque cursor from a prior `next_cursor` for page-after-page walking.","name":"cursor","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":500,"description":"Max rows per page (1-500, default 50). The People view requests 500 for the unified company-grouped UI."},"required":false,"description":"Max rows per page (1-500, default 50). The People view requests 500 for the unified company-grouped UI.","name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Offset-based pagination; use `cursor` for large result sets."},"required":false,"description":"Offset-based pagination; use `cursor` for large result sets.","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_contact","tags":["CRM"],"description":"Create a new CRM contact (person or company). Persons can be linked to a company via company_id. IMPORTANT: Before creating a contact, ALWAYS call list_contacts with a search query (q) to check if a contact with the same name or email already exists. If a matching contact is found, use update_contact instead of creating a duplicate. Only create a new contact if no match is found. Use this when the user asks to add a contact, log a lead, or create a company record.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm contacts create","output":{"successMessage":"Contact created: {contact.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateContactError"}}}}}}},"/api/crm/contacts/batch":{"get":{"operationId":"batch_get_contacts","tags":["CRM"],"description":"Fetch multiple CRM contacts by their IDs in a single request (max 100). Missing or inaccessible IDs are silently omitted from the result.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts batch","output":{"columns":["id","name","email","type"]}},"parameters":[{"schema":{"type":"string","description":"Comma-separated list of contact UUIDs (max 100)."},"required":false,"description":"Comma-separated list of contact UUIDs (max 100).","name":"ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactBatchResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/merge":{"post":{"operationId":"merge_contacts","tags":["CRM"],"description":"Merge two CRM contacts that represent the same person/company. The secondary contact is deleted, and its activities and deals are re-linked to the primary. Use this when you discover duplicates (same email or name). The primary contact is the one kept; the secondary is removed.","x-tool":{"expose":["all"],"annotations":{"destructive":true}},"x-cli":{"command":"crm contacts merge","confirm":true,"output":{"successMessage":"Contacts merged into {contact.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactMergeInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactMergeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/bulk-delete":{"post":{"operationId":"bulk_delete_contacts","tags":["CRM"],"description":"Delete many CRM contacts in a single operation. Returns counts of deleted/skipped/failed items.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true}},"x-cli":{"command":"crm contacts bulk-delete","confirm":true,"output":{"successMessage":"Bulk delete complete: {deleted} deleted"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkIdsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactBulkResultResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/bulk-update":{"post":{"operationId":"bulk_update_contacts","tags":["CRM"],"description":"Update many CRM contacts in a single operation. Useful for re-assigning ownership, updating lifecycle stage on a list of contacts, or reclassifying industry. Provide an array of contact IDs and the fields to apply to all of them.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm contacts bulk-update","output":{"successMessage":"Bulk update complete: {updated} updated"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactBulkResultResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/bulk-export":{"post":{"operationId":"bulk_export_contacts","tags":["CRM"],"description":"Export the selected contacts as a CSV string (all core fields + custom properties). Useful for producing a snapshot for downstream analysis.","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true}},"x-cli":{"command":"crm contacts bulk-export","output":{"format":"raw"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkIdsInput"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/import/preview":{"post":{"operationId":"crm_contacts_import_preview","tags":["CRM"],"description":"Parse CSV and return headers + preview rows. Accepts multipart/form-data with a file field.","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true}},"x-cli":{"command":"crm contacts import-preview"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactImportPreviewResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/import":{"post":{"operationId":"crm_contacts_import","tags":["CRM"],"description":"Import contacts from CSV. Accepts multipart/form-data with fields: file (CSV), mapping (JSON), duplicate_handling.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts import","output":{"successMessage":"Import complete: {created} created, {updated} updated, {skipped} skipped"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactImportResultResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/{id}":{"get":{"operationId":"get_contact","tags":["CRM"],"description":"Get a single CRM contact by ID, including full details: name, email, phone, title, company, lifecycle stage, custom properties, and timestamps. If the user is currently viewing a contact, use the contact ID from the page context.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts get"},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_contact","tags":["CRM"],"description":"Update an existing CRM contact's fields. Provide only the fields you want to change. If the user is currently viewing a contact, use the contact ID from the page context.","x-tool":{"expose":["all","automations"]},"x-cli":{"command":"crm contacts update"},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_contact","tags":["CRM"],"description":"Delete a CRM contact (owner-scoped). Permanently removes the contact record. Use with caution — prefer updating lifecycle_stage to 'evangelist' or archiving via merge instead.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm contacts delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/{id}/activities":{"get":{"operationId":"list_contact_activities","tags":["CRM"],"description":"List activities (notes, calls, emails, meetings, tasks) on a specific contact's timeline. Useful for summarizing recent interactions with a contact before sending an email or making a call.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts activities","output":{"columns":["id","type","subject","occurred_at","source"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/CrmActivityType"},"required":false,"description":"Activity timeline event type. Used for filtering and badges in the UI. Mirrors the `activities.type` column enum at apps/api/src/db/schema.ts.","name":"type","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactActivitiesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/{id}/score":{"get":{"operationId":"get_contact_score","tags":["CRM"],"description":"Get a contact's current lead score with a breakdown of which scoring rules matched and how many points each contributed. Use this to explain why a contact is hot/cold.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts score"},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactScoreResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/{id}/files":{"get":{"operationId":"crm_contact_files_list","tags":["CRM"],"description":"List files attached to a contact","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts files list","output":{"columns":["file_id","name","mime_type","size_bytes"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactFilesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"crm_contact_file_attach","tags":["CRM"],"description":"Attach a Drive file to a contact","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts files attach","output":{"successMessage":"File attached to contact"}},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactFileAttachInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactFileResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/{id}/files/{fileId}":{"delete":{"operationId":"crm_contact_file_detach","tags":["CRM"],"description":"Detach a file from a contact","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts files detach","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"fileId","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contacts/{id}/photo":{"post":{"operationId":"upload_contact_photo","tags":["CRM"],"description":"Upload a profile photo for a CRM contact. The assistant cannot directly upload binary files — this tool is informational. Direct the user to use the API endpoint POST /api/crm/contacts/:id/photo with a multipart form containing the image file (max 5MB, JPEG/PNG/WebP).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts photo upload"},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactPhotoUploadResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"crm_contact_photo_get","tags":["CRM"],"description":"Serve contact photo","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts photo get","output":{"format":"raw"}},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_contact_photo","tags":["CRM"],"description":"Delete a CRM contact's profile photo. Clears the avatar_url and removes the stored image.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contacts photo delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/ContactId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contact-groups":{"get":{"operationId":"list_contact_groups","tags":["CRM"],"description":"List all contact groups in the workspace with their member counts. Groups are named collections for organizing contacts (e.g., 'Conference leads 2026').","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contact-groups list","output":{"columns":["id","name","color","member_count"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactGroupsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_contact_group","tags":["CRM"],"description":"Create a named contact group for organizing contacts. Groups allow overlapping membership — a contact can be in multiple groups.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contact-groups create","output":{"successMessage":"Contact group created: {group.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactGroupCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactGroupResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateContactGroupError"}}}}}}},"/api/crm/contact-groups/{id}":{"patch":{"operationId":"update_contact_group","tags":["CRM"],"description":"Update an existing contact group's name, color, or sort order. Group name must remain unique within the workspace.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contact-groups update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactGroupUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactGroupResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateContactGroupError"}}}}}},"delete":{"operationId":"delete_contact_group","tags":["CRM"],"description":"Delete a contact group. Memberships are removed but contacts themselves are preserved.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm contact-groups delete","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/contact-groups/{id}/members":{"get":{"operationId":"list_contact_group_members","tags":["CRM"],"description":"List all contacts that are members of a contact group. Returns the contact id, name, email, and type for each member.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm contact-groups members list","output":{"columns":["id","name","email","type"]}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactGroupMembersListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"modify_contact_group_members","tags":["CRM"],"description":"Bulk add or remove contacts from a contact group. Idempotent — adding an already-present contact or removing an absent one is a no-op.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm contact-groups members modify","output":{"successMessage":"Group members updated: {added} added, {removed} removed"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactGroupMembersInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ContactGroupMembersUpdateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals":{"get":{"operationId":"list_deals","tags":["CRM"],"description":"List CRM deals. Supports filtering by pipeline, stage, and status. Returns deals with id, title, amount, currency, stage, pipeline, contact, status, and timestamps. Use this when the user asks to see their deals, check the pipeline, or find opportunities.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals list","output":{"columns":["id","title","amount","stage","status","contact"]}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"pipeline_id","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"stage_id","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"owner_id","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"company_id","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"contact_id","in":"query"},{"schema":{"$ref":"#/components/schemas/DealStatus"},"required":false,"description":"Lifecycle of a deal. `won` and `lost` close the deal; `lost` requires a `lost_reason`.","name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":1000},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"Comma-separated embed fields. Supported: line_items."},"required":false,"description":"Comma-separated embed fields. Supported: line_items.","name":"embed","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_deal","tags":["CRM"],"description":"Create a new CRM deal (revenue opportunity). Deals belong to a pipeline and sit in a specific stage. Link to a contact and/or company. Use this when the user asks to create a deal, log an opportunity, or start tracking a sale.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm deals create","output":{"successMessage":"Deal created: {deal.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateDealError"}}}}}}},"/api/crm/deals/batch":{"get":{"operationId":"batch_get_deals","tags":["CRM"],"description":"Fetch multiple CRM deals by their IDs in a single request (max 100). Missing or inaccessible IDs are silently omitted from the result.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals batch","output":{"columns":["id","title","amount","status"]}},"parameters":[{"schema":{"type":"string","description":"Comma-separated list of deal UUIDs (max 100)."},"required":false,"description":"Comma-separated list of deal UUIDs (max 100).","name":"ids","in":"query"},{"schema":{"type":"string","description":"Comma-separated embed fields. Supported: line_items."},"required":false,"description":"Comma-separated embed fields. Supported: line_items.","name":"embed","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealBatchResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals/{id}":{"get":{"operationId":"get_deal","tags":["CRM"],"description":"Get a single CRM deal by ID, including full details: title, amount, currency, stage, pipeline, contact, company, owner, probability, close date, custom properties, and timestamps. Pass embed=line_items to include the full line-items array. If the user is currently viewing a deal, use the deal ID from the page context.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals get"},"parameters":[{"schema":{"$ref":"#/components/schemas/DealId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Comma-separated embed fields. Supported: line_items."},"required":false,"description":"Comma-separated embed fields. Supported: line_items.","name":"embed","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_deal","tags":["CRM"],"description":"Update an existing CRM deal's fields. Provide only the fields you want to change. Use this to move a deal to a new stage, update the amount, mark as won/lost, etc. If the user is currently viewing a deal, use the deal ID from the page context.","x-tool":{"expose":["all","automations"]},"x-cli":{"command":"crm deals update"},"parameters":[{"schema":{"$ref":"#/components/schemas/DealId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateDealError"}}}}}},"delete":{"operationId":"delete_deal","tags":["CRM"],"description":"Delete a CRM deal (owner-scoped). Permanently removes the deal record and its line items. Prefer updating status to 'lost' with a lost_reason for reporting purposes.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/DealId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals/{id}/activities":{"get":{"operationId":"crm_deal_activities","tags":["CRM"],"description":"List activities for deal (owner-scoped)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals activities","output":{"columns":["id","type","subject","occurred_at","source"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/DealId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/CrmActivityType"},"required":false,"description":"Activity timeline event type. Used for filtering and badges in the UI. Mirrors the `activities.type` column enum at apps/api/src/db/schema.ts.","name":"type","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealActivitiesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals/bulk-delete":{"post":{"operationId":"bulk_delete_deals","tags":["CRM"],"description":"Delete many deals","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true}},"x-cli":{"command":"crm deals bulk-delete","confirm":true,"output":{"successMessage":"Bulk delete complete: {deleted} deleted"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkIdsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealBulkResultResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals/bulk-update":{"post":{"operationId":"bulk_update_deals","tags":["CRM"],"description":"Update many CRM deals in a single operation. Useful for moving multiple deals to a new stage, reassigning ownership, or marking a batch of deals as won/lost. Provide an array of deal IDs and the fields to apply.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals bulk-update","output":{"successMessage":"Bulk update complete: {updated} updated"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealBulkUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealBulkResultResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals/bulk-export":{"post":{"operationId":"bulk_export_deals","tags":["CRM"],"description":"Export selected deals as CSV","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true}},"x-cli":{"command":"crm deals bulk-export","output":{"format":"raw"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBulkIdsInput"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals/{id}/line-items":{"get":{"operationId":"list_deal_line_items","tags":["CRM"],"description":"List all line items for a deal, plus the computed total.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals line-items list","output":{"columns":["id","name","quantity","unit_price","amount"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/DealId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealLineItemsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"add_deal_line_item","tags":["CRM"],"description":"Add a line item to a deal. Either reference an existing product (via product_id) or create a custom line by providing name and unit_price. The deal amount is auto-recalculated.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm deals line-items create","output":{"successMessage":"Line item added: {lineItem.id}"}},"parameters":[{"schema":{"$ref":"#/components/schemas/DealId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealLineItemCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealLineItemResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals/line-items/{id}":{"patch":{"operationId":"update_deal_line_item","tags":["CRM"],"description":"Update a deal line item (quantity, price, discount, name/description). Amount auto-recomputed. If sync_deal_amount defaults true, the deal's total is also refreshed.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm deals line-items update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealLineItemUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealLineItemResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_deal_line_item","tags":["CRM"],"description":"Delete a deal line item. By default the deal's total amount is re-synced after deletion.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals line-items delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"sync_deal_amount","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealLineItemDeleteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals/{id}/files":{"get":{"operationId":"crm_deal_files_list","tags":["CRM"],"description":"List files attached to a deal","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals files list","output":{"columns":["file_id","name","mime_type","size_bytes"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/DealId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealFilesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"crm_deal_file_attach","tags":["CRM"],"description":"Attach a Drive file to a deal","x-tool":{"expose":["all"]},"x-cli":{"command":"crm deals files attach","output":{"successMessage":"File attached to deal"}},"parameters":[{"schema":{"$ref":"#/components/schemas/DealId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealFileAttachInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealFileResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deals/{id}/files/{fileId}":{"delete":{"operationId":"crm_deal_file_detach","tags":["CRM"],"description":"Detach a file from a deal","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm deals files detach","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"fileId","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deal-templates":{"get":{"operationId":"list_deal_templates","tags":["CRM"],"description":"List deal templates in the workspace (reusable deal presets: default pipeline, stage, amount, probability, and line items).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm templates list","output":{"columns":["id","title_template","pipeline_id","amount","currency"]}},"parameters":[{"schema":{"type":"string","description":"Search by name or SKU."},"required":false,"description":"Search by name or SKU.","name":"q","in":"query"},{"schema":{"type":["boolean","null"],"description":"Hide products where `active=false` when true."},"required":false,"description":"Hide products where `active=false` when true.","name":"active_only","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealTemplatesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_deal_template","tags":["CRM"],"description":"Create a deal template — a reusable preset for creating deals with standard pipeline/stage/amount and line items. Use when the user has a repeatable sale like 'Standard Enterprise Plan'.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm templates create","output":{"successMessage":"Deal template created: {template.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealTemplateCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealTemplateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deal-templates/{id}":{"get":{"operationId":"get_deal_template","tags":["CRM"],"description":"Get a single deal template with its line items and resolved pipeline/stage names.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm templates get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealTemplateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_deal_template","tags":["CRM"],"description":"Update a deal template. Providing `line_items` replaces the entire line-item list.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm templates update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealTemplateUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealTemplateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_deal_template","tags":["CRM"],"description":"Delete a deal template (does not affect deals previously created from it).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm templates delete","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/deal-templates/{id}/apply":{"post":{"operationId":"apply_deal_template","tags":["CRM"],"description":"Create a new deal from a saved deal template. The template provides default pipeline, stage, amount, probability, and line items. Use this when starting a deal that matches a known pattern (e.g., 'Standard Enterprise Plan').","x-tool":{"expose":["all"]},"x-cli":{"command":"crm templates apply","output":{"successMessage":"Deal created from template: {deal.id}"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealTemplateApplyInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DealResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/pipelines":{"get":{"operationId":"list_pipelines","tags":["CRM"],"description":"List all CRM pipelines with their stages. Each pipeline contains an ordered list of stages with names, sort order, and default probabilities. Use this before creating or moving deals to find valid pipeline_id and stage_id values.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm pipelines list","output":{"columns":["id","name","stages"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PipelinesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_pipeline","tags":["CRM"],"description":"Create a new CRM pipeline with ordered stages. Each stage has a name and an optional default probability (0-100). Most workspaces need only one pipeline; create additional ones for distinct sales processes (e.g., 'New Business' vs 'Renewals').","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm pipelines create","output":{"successMessage":"Pipeline created: {pipeline.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PipelineResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/pipelines/{id}":{"patch":{"operationId":"update_pipeline","tags":["CRM"],"description":"Update a pipeline's name or stages. Providing `stages` replaces the entire stage list — include every stage you want to keep. Reordering is done by the order in the array.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm pipelines update"},"parameters":[{"schema":{"$ref":"#/components/schemas/PipelineId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PipelineResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_pipeline","tags":["CRM"],"description":"Delete a CRM pipeline and all of its stages. Deals in the pipeline must be moved or deleted first.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm pipelines delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/PipelineId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/analytics":{"get":{"operationId":"get_crm_analytics","tags":["CRM"],"description":"Get comprehensive pipeline analytics: pipeline value by stage, conversion rates between stages, average deal size, sales velocity, deals breakdown. Use this for deeper analysis questions like 'where are deals stuck?' or 'how is the pipeline trending?'.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm analytics"},"parameters":[{"schema":{"type":"string","enum":["this_month","this_quarter","this_year"]},"required":false,"name":"period","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PipelineAnalyticsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/pipelines/{id}/permissions":{"get":{"operationId":"list_pipeline_members","tags":["CRM"],"description":"List the members of a CRM pipeline. Deal visibility is pipeline membership: a deal is visible to admins/owners and to members of its pipeline (directly or via a team). Roles are admin (can manage the pipeline + members) or member.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm pipelines members list","output":{"columns":["type","display_name","role"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/PipelineId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PipelineMembersListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"add_pipeline_member","tags":["CRM"],"description":"Add (or update the role of) a user or team on a CRM pipeline. Provide either user_id or team_id, plus role (admin | member). Admins/owners and pipeline admins can manage members.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm pipelines members add"},"parameters":[{"schema":{"$ref":"#/components/schemas/PipelineId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineMemberAddInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PipelineMembersListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/pipelines/{id}/permissions/{principalId}":{"delete":{"operationId":"remove_pipeline_member","tags":["CRM"],"description":"Remove a user or team from a CRM pipeline. The principalId is the user_id or team_id of the member to remove.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm pipelines members remove","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"principalId","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/activities":{"post":{"operationId":"log_activity","tags":["CRM"],"description":"Log an activity on a CRM contact or deal timeline. Activities track interactions like calls, emails, meetings, notes, and tasks. Use this when the user asks to log a call, record meeting notes, or add a note to a contact/deal.","x-tool":{"expose":["all","automations"]},"x-cli":{"command":"crm activities create","output":{"successMessage":"Activity logged: {activity.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmActivityCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmActivityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/activities/{id}":{"get":{"operationId":"get_activity","tags":["CRM"],"description":"Get a single activity by ID. Useful for reading back a just-created activity via the resource URL in the activity.created event payload.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm activities get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmActivityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_activity","tags":["CRM"],"description":"Delete activity","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm activities delete","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/sequences":{"get":{"operationId":"list_sequences","tags":["CRM"],"description":"List all CRM email/task sequences (multi-step automated outreach campaigns). Returns sequences with their steps, active status, and current enrollment count.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm sequences list","output":{"columns":["id","name","is_active","enrollment_count"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SequencesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_sequence","tags":["CRM"],"description":"Create a multi-step CRM sequence (email/wait/task/call/branch steps). Use this when the user asks to build a nurture campaign or outreach cadence.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm sequences create","output":{"successMessage":"Sequence created: {sequence.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SequenceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/sequences/{id}":{"get":{"operationId":"get_sequence","tags":["CRM"],"description":"Get a single sequence with its full step list and current enrollment count.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm sequences get"},"parameters":[{"schema":{"$ref":"#/components/schemas/SequenceId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SequenceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_sequence","tags":["CRM"],"description":"Update a sequence (rename, description, toggle active, replace step list). Providing `steps` replaces the entire step list.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm sequences update"},"parameters":[{"schema":{"$ref":"#/components/schemas/SequenceId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SequenceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_sequence","tags":["CRM"],"description":"Delete a sequence (and all its enrollments).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm sequences delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/SequenceId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/sequences/process":{"post":{"operationId":"process_sequences","tags":["CRM"],"description":"Process all due enrollment steps across all sequences (cron/manual trigger). Returns the count of enrollments that were advanced. Use sparingly — the system runs this on a schedule already.","x-cli":{"command":"crm sequences process","output":{"successMessage":"Processed {processed} enrollments"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SequenceProcessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/sequences/{id}/enrollments":{"get":{"operationId":"list_sequence_enrollments","tags":["CRM"],"description":"List all enrollments for a sequence, including each contact's current step, status, and next execute time. Useful for checking progress or finding an enrollment ID to unenroll.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm sequences enrollments list","output":{"columns":["id","contact_id","status","current_step","next_execute_at"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/SequenceId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SequenceEnrollmentsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/sequences/{id}/enroll":{"post":{"operationId":"enroll_contact_in_sequence","tags":["CRM"],"description":"Enroll a contact in a CRM sequence so they begin receiving the automated steps (emails, tasks, calls). Use this when the user asks to start a campaign for a specific contact.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"crm sequences enroll","output":{"successMessage":"Contact enrolled in sequence"}},"parameters":[{"schema":{"$ref":"#/components/schemas/SequenceId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceEnrollInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SequenceEnrollResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/sequences/enrollments/{id}/unenroll":{"post":{"operationId":"unenroll_contact_from_sequence","tags":["CRM"],"description":"Permanently remove a contact from a CRM sequence (terminal — sets status to 'unenrolled'). The contact will not receive any further sequence steps. Returns 409 if already in a terminal status. Provide the enrollment ID (not the contact ID — find it via list_sequence_enrollments).","x-tool":{"expose":["all"],"annotations":{"destructive":true}},"x-cli":{"command":"crm sequences unenroll","confirm":true,"output":{"format":"none","successMessage":"Contact unenrolled from sequence"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/sequences/enrollments/{id}/events":{"get":{"operationId":"list_enrollment_events","tags":["CRM"],"description":"Get the event log for a single sequence enrollment (step-executed, email-opened, email-replied, branch-taken, completed). Useful for auditing why a contact moved to a particular step.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm sequences enrollments events","output":{"columns":["id","event_type","step_index","occurred_at"]}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SequenceEventsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/scoring/fields":{"get":{"operationId":"list_scorable_fields","tags":["CRM"],"description":"List the contact fields that can be used in scoring rules (lifecycle_stage, industry, title, website, custom_properties.*, etc.) and the operators each supports.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm scoring fields","output":{"columns":["field","operators"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScoringFieldsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/scoring/recalculate":{"post":{"operationId":"recalculate_lead_scores","tags":["CRM"],"description":"Recalculate lead scores for all contacts in the workspace. Use this after creating or updating scoring rules so existing contacts pick up the new scoring.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm scoring recalculate","confirm":true,"output":{"successMessage":"Recalculated scores for {updated} contacts"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScoringRecalculateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/scoring/rules":{"get":{"operationId":"list_scoring_rules","tags":["CRM"],"description":"List all lead scoring rules for the workspace.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm scoring rules list","output":{"columns":["id","name","field","operator","value","points","is_active"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScoringRulesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_scoring_rule","tags":["CRM"],"description":"Create a lead scoring rule. When a contact matches (field + operator + value), the specified points are added to their lead score. Positive points indicate engagement; negative points indicate disqualification signals.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm scoring rules create","output":{"successMessage":"Scoring rule created: {rule.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScoringRuleCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScoringRuleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/scoring/rules/{id}":{"patch":{"operationId":"update_scoring_rule","tags":["CRM"],"description":"Update a lead scoring rule (name, field, operator, value, points, is_active).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm scoring rules update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScoringRuleUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScoringRuleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_scoring_rule","tags":["CRM"],"description":"Delete a lead scoring rule.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm scoring rules delete","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/quotes":{"get":{"operationId":"list_quotes","tags":["CRM"],"description":"List CRM quotes/proposals. Filter by status (draft, sent, accepted, rejected, expired), deal, or contact. Useful for finding outstanding quotes or recently-accepted ones.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm quotes list","output":{"columns":["id","title","status","total","deal_id","contact_id"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/QuoteStatus"},"required":false,"description":"Quote lifecycle. `accepted`/`rejected` are terminal; `viewed` is recorded by the open-tracking pixel.","name":"status","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"deal_id","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"contact_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/QuotesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_quote","tags":["CRM"],"description":"Create a CRM quote (proposal) with line items. Auto-computes subtotal, tax, discount, and total. Link to a deal/contact/company via IDs. Status defaults to 'draft' — use send_quote to email it.","x-tool":{"expose":["all"]},"x-cli":{"command":"crm quotes create","output":{"successMessage":"Quote created: {quote.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/QuoteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/quotes/{id}":{"get":{"operationId":"get_quote","tags":["CRM"],"description":"Get a single CRM quote with its line items and linked deal/contact/company/owner.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm quotes get"},"parameters":[{"schema":{"$ref":"#/components/schemas/QuoteId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/QuoteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_quote","tags":["CRM"],"description":"Update a CRM quote. Providing `line_items` replaces the entire line-item list. Totals are auto-recomputed.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm quotes update"},"parameters":[{"schema":{"$ref":"#/components/schemas/QuoteId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/QuoteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_quote","tags":["CRM"],"description":"Delete a CRM quote and its line items.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm quotes delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/QuoteId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/quotes/{id}/send":{"post":{"operationId":"send_quote","tags":["CRM"],"description":"Send a CRM quote via email to the contact. Marks the quote as 'sent'. By default, sends to the linked contact's email address.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"crm quotes send","confirm":true,"output":{"successMessage":"Quote sent"}},"parameters":[{"schema":{"$ref":"#/components/schemas/QuoteId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteSendInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/QuoteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/quotes/{id}/pdf":{"get":{"operationId":"crm_quote_pdf","tags":["CRM"],"description":"Export quote as PDF (or printable HTML with ?format=html)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm quotes pdf","output":{"format":"raw"}},"parameters":[{"schema":{"$ref":"#/components/schemas/QuoteId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["html","pdf"]},"required":false,"name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/products":{"get":{"operationId":"list_products","tags":["CRM"],"description":"List products in the workspace catalog. Use this when the user asks about pricing or available SKUs, or before adding a product as a deal line item.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm products list","output":{"columns":["id","name","price","sku","is_active"]}},"parameters":[{"schema":{"type":"string","description":"Search by name or SKU."},"required":false,"description":"Search by name or SKU.","name":"q","in":"query"},{"schema":{"type":["boolean","null"],"description":"Hide products where `active=false` when true."},"required":false,"description":"Hide products where `active=false` when true.","name":"active_only","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmProductsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_product","tags":["CRM"],"description":"Create a product in the workspace catalog. Products are the reusable items that can be attached to deal line items and quote line items. Set is_active=false to retire without deleting.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm products create","output":{"successMessage":"Product created: {product.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmProductCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmProductResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/products/{id}":{"get":{"operationId":"get_product","tags":["CRM"],"description":"Get product","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm products get"},"parameters":[{"schema":{"$ref":"#/components/schemas/ProductId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmProductResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_product","tags":["CRM"],"description":"Update product","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm products update"},"parameters":[{"schema":{"$ref":"#/components/schemas/ProductId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmProductUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CrmProductResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_product","tags":["CRM"],"description":"Delete a product from the workspace catalog. Existing deal/quote line items referencing it are NOT deleted, but their product_id is nulled.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm products delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/ProductId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/views":{"get":{"operationId":"list_crm_views","tags":["CRM"],"description":"List the user's saved CRM views (filter + sort presets for contacts/companies/deals). Views personalize how CRM data is displayed without changing the underlying records.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm views list","output":{"columns":["id","name","entity_type","is_default"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/SavedViewEntity"},"required":false,"description":"Which list page the saved view applies to. Mirrors crm_saved_views.entity_type enum at apps/api/src/db/schema.ts.","name":"entity_type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SavedViewsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_crm_view","tags":["CRM"],"description":"Create a saved CRM view: a named filter+sort preset for contacts, companies, or deals. Useful when the user asks to 'save this filter' or 'create a view for high-value deals'.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm views create","output":{"successMessage":"View created: {view.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedViewCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SavedViewResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/views/{id}":{"patch":{"operationId":"update_crm_view","tags":["CRM"],"description":"Update a saved CRM view (rename, change filters, toggle default/shared).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm views update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedViewUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SavedViewResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_crm_view","tags":["CRM"],"description":"Delete a saved CRM view.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm views delete","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/workflows":{"get":{"operationId":"list_workflows","tags":["CRM"],"description":"**Deprecated — CRM Workflows have folded into Automations. Build this rule as an automation (`/api/automations`) instead.** List all CRM automation workflows in the workspace. Each workflow has a trigger (deal-stage-changed, deal-won, etc.) and an ordered list of actions that run when it fires.","deprecated":true,"x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm workflows list","output":{"columns":["id","name","trigger","is_active"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_workflow","tags":["CRM"],"description":"**Deprecated — CRM Workflows have folded into Automations. Build this rule as an automation (`/api/automations`) instead.** Create a new CRM automation workflow. Define the trigger event and an ordered list of actions. Example: trigger='deal_won' with an action to send an email to the deal owner.","deprecated":true,"x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm workflows create","output":{"successMessage":"Workflow created: {workflow.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/workflows/{id}":{"get":{"operationId":"get_workflow","tags":["CRM"],"description":"**Deprecated — CRM Workflows have folded into Automations. Build this rule as an automation (`/api/automations`) instead.** Get workflow with actions","deprecated":true,"x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm workflows get"},"parameters":[{"schema":{"$ref":"#/components/schemas/CrmWorkflowId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_workflow","tags":["CRM"],"description":"**Deprecated — CRM Workflows have folded into Automations. Build this rule as an automation (`/api/automations`) instead.** Update a workflow (name, description, trigger config, is_active, actions). Providing `actions` replaces the entire action list.","deprecated":true,"x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm workflows update"},"parameters":[{"schema":{"$ref":"#/components/schemas/CrmWorkflowId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_workflow","tags":["CRM"],"description":"**Deprecated — CRM Workflows have folded into Automations. Build this rule as an automation (`/api/automations`) instead.** Delete workflow","deprecated":true,"x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm workflows delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/CrmWorkflowId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/workflows/{id}/logs":{"get":{"operationId":"get_workflow_logs","tags":["CRM"],"description":"**Deprecated — CRM Workflows have folded into Automations. Build this rule as an automation (`/api/automations`) instead.** Get the execution history for a workflow (most recent first). Each log entry records which actions ran, their individual success/error status, and the triggering resource.","deprecated":true,"x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm workflows logs","output":{"columns":["id","status","triggered_at","resource_type","resource_id"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/CrmWorkflowId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","exclusiveMinimum":0,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowLogsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/scheduler-links":{"get":{"operationId":"list_scheduler_links","tags":["CRM"],"description":"List the user's scheduler links (Calendly-style booking pages). Each link has a shareable slug, duration, availability hours, and optionally auto-creates a contact + deal when booked.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm scheduler links list","output":{"columns":["id","name","slug","duration_minutes","is_active"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SchedulerLinksListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_scheduler_link","tags":["CRM"],"description":"Create a scheduler link (booking page). Returns the public URL slug and availability settings. If auto_create_contact is true, every booking auto-creates a CRM contact + deal.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"crm scheduler links create","output":{"successMessage":"Scheduler link created: {schedulerLink.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SchedulerLinkCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SchedulerLinkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/scheduler-links/{id}":{"get":{"operationId":"get_scheduler_link","tags":["CRM"],"description":"Get a single scheduler link (owner-scoped) with its settings and booking count.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm scheduler links get"},"parameters":[{"schema":{"$ref":"#/components/schemas/SchedulerLinkId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SchedulerLinkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_scheduler_link","tags":["CRM"],"description":"Update a scheduler link (rename, change availability, toggle active, etc.).","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"crm scheduler links update"},"parameters":[{"schema":{"$ref":"#/components/schemas/SchedulerLinkId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SchedulerLinkUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SchedulerLinkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_scheduler_link","tags":["CRM"],"description":"Delete a scheduler link. Existing confirmed bookings remain but the public booking page stops accepting new bookings.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"crm scheduler links delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/SchedulerLinkId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/scheduler-links/{id}/bookings":{"get":{"operationId":"list_scheduler_link_bookings","tags":["CRM"],"description":"List all bookings for a single scheduler link (owner-scoped).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm scheduler links bookings","output":{"columns":["id","guest_name","guest_email","start_time","status"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/SchedulerLinkId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SchedulerBookingsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/crm/scheduler-bookings":{"get":{"operationId":"list_scheduler_bookings","tags":["CRM"],"description":"List all bookings (across all scheduler links) owned by the current user. Useful for summarizing the user's upcoming meetings.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"crm scheduler bookings list","output":{"columns":["id","guest_name","guest_email","start_time","status","scheduler_link_id"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SchedulerBookingsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/w/{workspaceSlug}/{formSlug}":{"get":{"operationId":"forms_public_get_by_workspace_slug","tags":["Forms"],"description":"Public, unauthenticated read of a published form by workspace slug + form slug. Honors A/B test traffic splitting; returns the resolved variant_id when applicable.","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"formSlug","in":"path"}],"responses":{"200":{"description":"Public form","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicForm"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/w/{workspaceSlug}/{formSlug}/submit":{"post":{"operationId":"forms_public_submit_by_workspace_slug","tags":["Forms"],"description":"Public, anonymous form submission via workspace + form slug. Honors `require_auth` (rejects anonymous when set) and CAPTCHA when enabled. Optional auth — logged-in respondents are recorded.","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"formSlug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmitInput"}}}},"responses":{"201":{"description":"Submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmitResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/s/{slug}":{"get":{"operationId":"forms_public_get_by_slug","tags":["Forms"],"description":"Legacy public read of a published form by slug only (kept for backward compatibility). Prefer `/api/forms/w/:workspaceSlug/:formSlug`. Honors A/B test traffic splitting.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"Public form","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicForm"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/s/{slug}/submit":{"post":{"operationId":"forms_public_submit_by_slug","tags":["Forms"],"description":"Legacy public submission via slug-only URL. Same semantics as `/api/forms/w/:workspaceSlug/:formSlug/submit`. Optional auth.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmitInput"}}}},"responses":{"201":{"description":"Submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmitResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/views":{"post":{"operationId":"record_form_view","tags":["Forms"],"description":"Record a form view event for analytics. Typically called by the form renderer, not by an end user. Tracks session, field progression, completion, and duration for drop-off analysis.","parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormViewInput"}}}},"responses":{"200":{"description":"Recorded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSuccessResponse"}}}}}}},"/api/forms/{id}/payment-intent":{"post":{"operationId":"forms_payment_intent_create","tags":["Forms"],"description":"Create a Stripe PaymentIntent for a form with a payment field. Returns `client_secret` for client-side Stripe Elements confirmation. Public — optional auth.","parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Payment intent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntentResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Failed to create payment intent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Payment processing is not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/stripe/webhook":{"post":{"operationId":"forms_stripe_webhook","tags":["Forms"],"description":"Stripe webhook receiver — verifies the `Stripe-Signature` header, then dispatches `payment_intent.succeeded` / `payment_intent.payment_failed` events. Anonymous; called by Stripe's infrastructure only.","responses":{"200":{"description":"Received","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StripeWebhookResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Stripe not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/w/{workspaceSlug}/{formSlug}/upload":{"post":{"operationId":"forms_public_upload_by_workspace_slug","tags":["Forms"],"description":"Public file upload for a `file_upload` field on a published form, addressed by workspace slug + form slug. Multipart body: `field_id`, `file`. Returns a manifest the respondent passes back in the submit payload.","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"formSlug","in":"path"}],"responses":{"201":{"description":"Uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormUploadResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"File exceeds size limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Form has no owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{slug}/upload":{"post":{"operationId":"forms_public_upload_by_slug","tags":["Forms"],"description":"Public file upload via slug or form ID (legacy path). Multipart body: `field_id`, `file`. Returns a manifest.","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"responses":{"201":{"description":"Uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormUploadResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"File exceeds size limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Form has no owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{slug}/submit":{"post":{"operationId":"submit_form","tags":["Forms"],"description":"Submit a response to a published form, identified by its public slug or form ID. Data is a map keyed by field ID with user answers. Use when an agent is filling out a form on behalf of a user or when completing a structured data-entry task.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmitInput"}}}},"responses":{"201":{"description":"Submitted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmitResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms":{"get":{"operationId":"list_forms","tags":["Forms"],"description":"List the user's forms. Returns forms with id, title, slug, is_published, response count, and timestamps. Use this when the user asks to see their forms, find a specific form, or check form status.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms list","output":{"columns":["id","title","is_published","response_count"]}},"parameters":[{"schema":{"type":"string","description":"Search filter on title/description."},"required":false,"description":"Search filter on title/description.","name":"q","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"'true' or 'false' to filter by publish state."},"required":false,"description":"'true' or 'false' to filter by publish state.","name":"is_published","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_form","tags":["Forms"],"description":"Create a new form for collecting data (surveys, feedback, registrations, quizzes). Returns the created form with id and public slug. Use this when the user asks to create a survey, questionnaire, feedback form, registration form, or any structured data collection. Define fields with types, labels, validation, and optional conditional logic.","x-tool":{"expose":["all"]},"x-cli":{"command":"forms create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"slug":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","description":"Field type — one of FormFieldType (loose-typed for forward compat)."},"label":{"type":"string"},"required":{"type":"boolean"},"placeholder":{"type":"string"},"options":{"type":"array","items":{},"description":"Choice list for select / multi_select / rating / scale."},"min":{"type":"number"},"max":{"type":"number"},"show_if":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},{"type":"object","properties":{"logic":{"type":"string","enum":["and","or"]},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},"minItems":1}},"required":["logic","conditions"],"additionalProperties":false}],"description":"Conditional visibility — show when one or more conditions match."},"min_length":{"type":"integer","minimum":0},"max_length":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string","description":"Regex the value must match (anchored — partial matches rejected)."},"min_date":{"type":"string","description":"Earliest allowed ISO date (YYYY-MM-DD), inclusive."},"max_date":{"type":"string","description":"Latest allowed ISO date (YYYY-MM-DD), inclusive."},"min_time":{"type":"string","description":"Earliest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"max_time":{"type":"string","description":"Latest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"min_selections":{"type":"integer","minimum":0},"max_selections":{"type":"integer","exclusiveMinimum":0},"amount":{"type":"number","description":"Payment amount in smallest currency unit (cents)."},"currency":{"type":"string","description":"ISO 4217 currency code, e.g. 'usd'."},"price_description":{"type":"string"},"max_file_size_mb":{"type":"number","description":"Per-file cap in MB (default 10, hard cap 25)."},"allowed_mime_types":{"type":"array","items":{"type":"string"},"description":"Whitelist; empty/undefined = any MIME accepted."},"left_label":{"type":"string","description":"Left-end label for a scale field."},"right_label":{"type":"string","description":"Right-end label for a scale field."}},"required":["id","type","label"],"additionalProperties":false}},"schema":{"type":"object","properties":{"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","description":"Field type — one of FormFieldType (loose-typed for forward compat)."},"label":{"type":"string"},"required":{"type":"boolean"},"placeholder":{"type":"string"},"options":{"type":"array","items":{},"description":"Choice list for select / multi_select / rating / scale."},"min":{"type":"number"},"max":{"type":"number"},"show_if":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},{"type":"object","properties":{"logic":{"type":"string","enum":["and","or"]},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},"minItems":1}},"required":["logic","conditions"],"additionalProperties":false}],"description":"Conditional visibility — show when one or more conditions match."},"min_length":{"type":"integer","minimum":0},"max_length":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string","description":"Regex the value must match (anchored — partial matches rejected)."},"min_date":{"type":"string","description":"Earliest allowed ISO date (YYYY-MM-DD), inclusive."},"max_date":{"type":"string","description":"Latest allowed ISO date (YYYY-MM-DD), inclusive."},"min_time":{"type":"string","description":"Earliest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"max_time":{"type":"string","description":"Latest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"min_selections":{"type":"integer","minimum":0},"max_selections":{"type":"integer","exclusiveMinimum":0},"amount":{"type":"number","description":"Payment amount in smallest currency unit (cents)."},"currency":{"type":"string","description":"ISO 4217 currency code, e.g. 'usd'."},"price_description":{"type":"string"},"max_file_size_mb":{"type":"number","description":"Per-file cap in MB (default 10, hard cap 25)."},"allowed_mime_types":{"type":"array","items":{"type":"string"},"description":"Whitelist; empty/undefined = any MIME accepted."},"left_label":{"type":"string","description":"Left-end label for a scale field."},"right_label":{"type":"string","description":"Right-end label for a scale field."}},"required":["id","type","label"],"additionalProperties":false}}},"required":["fields"],"additionalProperties":false,"description":"Alternative to `fields` — pass `{fields: [...]}` instead."},"settings":{"type":"object","properties":{"accept_responses":{"type":"boolean"},"require_auth":{"type":"boolean"},"one_response_per_user":{"type":"boolean"},"allow_multiple_responses":{"type":"boolean"},"confirmation_message":{"type":"string"},"redirect_url":{"type":"string"},"notify_on_submit":{"type":"array","items":{"type":"string"}},"auto_create_task":{"type":"boolean"},"task_title_template":{"type":"string"},"task_description_template":{"type":"string"},"task_assignee_id":{"type":"string"},"task_project_id":{"type":"string"},"task_priority":{"type":"string","enum":["urgent","high","medium","low"]},"task_due_offset_days":{"type":["integer","null"]},"auto_create_contact":{"type":"boolean"},"auto_create_crm_contact":{"type":"boolean"},"auto_create_crm_deal":{"type":"boolean"},"contact_email_field":{"type":"string"},"contact_name_field":{"type":"string"},"contact_phone_field":{"type":"string"},"contact_company_field":{"type":"string"},"contact_title_field":{"type":"string"},"contact_lifecycle_stage":{"type":"string"},"auto_create_deal":{"type":"boolean"},"deal_title_template":{"type":"string"},"deal_amount_field":{"type":"string"},"captcha_enabled":{"type":"boolean"},"send_confirmation_email":{"type":"boolean"},"confirmation_email_subject":{"type":"string"},"confirmation_email_message":{"type":"string"},"stripe_publishable_key":{"type":"string"},"include_response_in_webhook":{"type":"boolean","description":"Enrich webhook deliveries with the full response payload."}},"additionalProperties":false},"is_published":{"type":"boolean","description":"Publish the form immediately on create."}},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Form"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/responses":{"get":{"operationId":"list_form_responses","tags":["Forms"],"description":"List responses submitted to a form. Returns responses with respondent info, submitted data (keyed by field ID), and timestamps. Use this when the user asks to see form results, check submissions, analyze feedback, or export response data.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms responses list","output":{"columns":["id","submitted_at","respondent_email"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","description":"ISO 8601 timestamp; only responses submitted after this."},"required":false,"description":"ISO 8601 timestamp; only responses submitted after this.","name":"submitted_after","in":"query"},{"schema":{"type":"string","description":"Filter by exact value of a specific field (legacy single-filter)."},"required":false,"description":"Filter by exact value of a specific field (legacy single-filter).","name":"field_id","in":"query"},{"schema":{"type":"string","description":"Required when `field_id` is set (legacy single-filter)."},"required":false,"description":"Required when `field_id` is set (legacy single-filter).","name":"value","in":"query"},{"schema":{"type":"string","description":"URL-encoded JSON array of {field_id, op, value} objects. Operators: contains, equals, is_empty, is_not_empty. Multiple filters AND together."},"required":false,"description":"URL-encoded JSON array of {field_id, op, value} objects. Operators: contains, equals, is_empty, is_not_empty. Multiple filters AND together.","name":"filters","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormResponseListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/responses/{rid}":{"get":{"operationId":"get_form_response","tags":["Forms"],"description":"Get a single form response by ID. Returns respondent info, submitted data (keyed by field ID), and timestamp. Use when the user asks about a specific submission or wants to review a particular response.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms response get"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"rid","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormResponseRecord"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_form_response","tags":["Forms"],"description":"Delete a single form response. This is destructive — always confirm with the user before executing. Use when the user asks to remove or delete a specific submission.","x-tool":{"expose":["all"]},"x-cli":{"command":"forms response delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"rid","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/variants":{"get":{"operationId":"list_form_variants","tags":["Forms"],"description":"List A/B test variants for a form. Returns each variant's id, name, traffic weight, active status, and variant form ID. Use when the user asks about their A/B tests, variant list, or experiment setup.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms variants list"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormVariantListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_form_variant","tags":["Forms"],"description":"Create a new A/B test variant by duplicating the parent form. Optionally override fields to change question wording, field types, options, or validation. Traffic weight (0–100) controls the percentage of visitors who see this variant versus the control. Use when the user asks to set up an A/B test or add a variant.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms variant create"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"traffic_weight":{"type":"number"},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","description":"Field type — one of FormFieldType (loose-typed for forward compat)."},"label":{"type":"string"},"required":{"type":"boolean"},"placeholder":{"type":"string"},"options":{"type":"array","items":{},"description":"Choice list for select / multi_select / rating / scale."},"min":{"type":"number"},"max":{"type":"number"},"show_if":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},{"type":"object","properties":{"logic":{"type":"string","enum":["and","or"]},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},"minItems":1}},"required":["logic","conditions"],"additionalProperties":false}],"description":"Conditional visibility — show when one or more conditions match."},"min_length":{"type":"integer","minimum":0},"max_length":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string","description":"Regex the value must match (anchored — partial matches rejected)."},"min_date":{"type":"string","description":"Earliest allowed ISO date (YYYY-MM-DD), inclusive."},"max_date":{"type":"string","description":"Latest allowed ISO date (YYYY-MM-DD), inclusive."},"min_time":{"type":"string","description":"Earliest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"max_time":{"type":"string","description":"Latest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"min_selections":{"type":"integer","minimum":0},"max_selections":{"type":"integer","exclusiveMinimum":0},"amount":{"type":"number","description":"Payment amount in smallest currency unit (cents)."},"currency":{"type":"string","description":"ISO 4217 currency code, e.g. 'usd'."},"price_description":{"type":"string"},"max_file_size_mb":{"type":"number","description":"Per-file cap in MB (default 10, hard cap 25)."},"allowed_mime_types":{"type":"array","items":{"type":"string"},"description":"Whitelist; empty/undefined = any MIME accepted."},"left_label":{"type":"string","description":"Left-end label for a scale field."},"right_label":{"type":"string","description":"Right-end label for a scale field."}},"required":["id","type","label"],"additionalProperties":false}}},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormVariant"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/variants/{vid}":{"patch":{"operationId":"update_form_variant","tags":["Forms"],"description":"Update an A/B test variant's name, traffic weight, or active status. Use when the user asks to rename a variant, adjust the traffic split, or pause/resume an experiment.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms variant update"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"vid","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"traffic_weight":{"type":"number"},"is_active":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormVariant"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_form_variant","tags":["Forms"],"description":"Delete an A/B test variant (and its underlying duplicated form). Destructive — always confirm with the user. Use when the user asks to remove a variant or end an experiment.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms variant delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"vid","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/analytics":{"get":{"operationId":"get_form_analytics","tags":["Forms"],"description":"Get analytics for a form: total views, total responses, completion rate, average completion time, responses-by-day (last 30 days), per-field drop-off funnel, and per-field summaries (option counts for select fields, numeric stats for rating/number fields). Use when the user asks about form performance, response rate, completion rate, or field-level statistics.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms analytics"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormAnalyticsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/ab-analytics":{"get":{"operationId":"get_form_ab_analytics","tags":["Forms"],"description":"Get A/B test comparison analytics for a form with variants. Returns control + each variant with views, responses, completion rate, and traffic weight. Use when the user asks which variant is winning, for A/B test results, or experiment performance comparison.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms ab-analytics"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormABAnalyticsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/publish":{"post":{"operationId":"publish_form","tags":["Forms"],"description":"Publish a form so it accepts public responses. Semantic shortcut for PATCH /api/forms/{id} with is_published=true; same validation (every field needs a non-empty label).","x-tool":{"expose":["all"],"annotations":{"openWorld":true}},"x-cli":{"command":"forms publish"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Form"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/unpublish":{"post":{"operationId":"unpublish_form","tags":["Forms"],"description":"Unpublish a form so it stops accepting public responses. Semantic shortcut for PATCH /api/forms/{id} with is_published=false.","x-tool":{"expose":["all"],"annotations":{"openWorld":true}},"x-cli":{"command":"forms unpublish"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Form"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/permissions":{"get":{"operationId":"forms_permissions_list","tags":["Forms"],"description":"List sharers (users + teams) plus pending invites for external recipients.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"forms permissions list"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormPermissionsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"forms_permissions_set","tags":["Forms"],"description":"Grant a permission to one principal: a user (`user_id`) or a team (`team_id`). Owner only. Roles: viewer, editor, owner.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"forms permissions set"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSetPermissionInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormSetPermissionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/permissions/{principalId}":{"delete":{"operationId":"forms_permission_remove","tags":["Forms"],"description":"Remove a permission. Use `?type=user|team` to target the right principal type.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"forms permissions remove"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"principalId","in":"path"},{"schema":{"type":"string","enum":["user","team"],"description":"Principal type; defaults to user."},"required":false,"description":"Principal type; defaults to user.","name":"type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormDeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/share-invite":{"post":{"operationId":"forms_share_invite","tags":["Forms"],"description":"Invite an external email to share the form. Creates a `pending_shares` row that's applied when the invitee accepts. Owner only.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"hidden":true,"command":"forms share-invite"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareInviteInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ShareInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/pending-shares/{pendingId}":{"delete":{"operationId":"forms_pending_share_revoke","tags":["Forms"],"description":"Revoke a pending invite that hasn't been accepted yet.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"forms pending-shares revoke"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"pendingId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormRevokePendingShareResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/visibility":{"patch":{"operationId":"forms_visibility_update","tags":["Forms"],"description":"Toggle public-link visibility. Setting visibility to `restricted` or `workspace` clears any link expiry + password. Owner only.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"hidden":true,"command":"forms visibility"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"visibility":{"type":"string","description":"One of: restricted, workspace, link, public."},"linkExpiresAt":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO 8601 timestamp, or null to clear."},"linkPassword":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Empty string or null clears the password; non-empty hashes + stores."},"linkPermission":{"type":"string","enum":["viewer","editor"],"description":"Permission level for anyone accessing via public link. Defaults to viewer."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormVisibilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}/revoke-link":{"post":{"operationId":"forms_revoke_link","tags":["Forms"],"description":"Revoke the public link — sets visibility to restricted, clears expiry, clears password. Owner only.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"hidden":true,"command":"forms revoke-link"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormRevokeLinkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/forms/{id}":{"get":{"operationId":"get_form","tags":["Forms"],"description":"Get a form's full details including field schema, settings, publish status, and slug. Use this when the user asks about a form's fields, structure, or configuration. If the user is currently viewing a form, use the resource ID from page context.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"forms get"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Form"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_form","tags":["Forms"],"description":"Update an existing form's title, description, fields, settings, or publish status. Use this when the user asks to edit a form, add/remove fields, publish/unpublish, or change form settings. If the user is currently viewing a form, use the resource ID from page context.","x-tool":{"expose":["all"],"annotations":{"destructive":true}},"x-cli":{"command":"forms update"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":["string","null"]},"slug":{"type":["string","null"]},"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","description":"Field type — one of FormFieldType (loose-typed for forward compat)."},"label":{"type":"string"},"required":{"type":"boolean"},"placeholder":{"type":"string"},"options":{"type":"array","items":{},"description":"Choice list for select / multi_select / rating / scale."},"min":{"type":"number"},"max":{"type":"number"},"show_if":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},{"type":"object","properties":{"logic":{"type":"string","enum":["and","or"]},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},"minItems":1}},"required":["logic","conditions"],"additionalProperties":false}],"description":"Conditional visibility — show when one or more conditions match."},"min_length":{"type":"integer","minimum":0},"max_length":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string","description":"Regex the value must match (anchored — partial matches rejected)."},"min_date":{"type":"string","description":"Earliest allowed ISO date (YYYY-MM-DD), inclusive."},"max_date":{"type":"string","description":"Latest allowed ISO date (YYYY-MM-DD), inclusive."},"min_time":{"type":"string","description":"Earliest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"max_time":{"type":"string","description":"Latest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"min_selections":{"type":"integer","minimum":0},"max_selections":{"type":"integer","exclusiveMinimum":0},"amount":{"type":"number","description":"Payment amount in smallest currency unit (cents)."},"currency":{"type":"string","description":"ISO 4217 currency code, e.g. 'usd'."},"price_description":{"type":"string"},"max_file_size_mb":{"type":"number","description":"Per-file cap in MB (default 10, hard cap 25)."},"allowed_mime_types":{"type":"array","items":{"type":"string"},"description":"Whitelist; empty/undefined = any MIME accepted."},"left_label":{"type":"string","description":"Left-end label for a scale field."},"right_label":{"type":"string","description":"Right-end label for a scale field."}},"required":["id","type","label"],"additionalProperties":false}},"schema":{"type":"object","properties":{"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","description":"Field type — one of FormFieldType (loose-typed for forward compat)."},"label":{"type":"string"},"required":{"type":"boolean"},"placeholder":{"type":"string"},"options":{"type":"array","items":{},"description":"Choice list for select / multi_select / rating / scale."},"min":{"type":"number"},"max":{"type":"number"},"show_if":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},{"type":"object","properties":{"logic":{"type":"string","enum":["and","or"]},"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"equals":{"type":"string"},"operator":{"type":"string"},"value":{"type":"string"}},"required":["field"],"additionalProperties":false},"minItems":1}},"required":["logic","conditions"],"additionalProperties":false}],"description":"Conditional visibility — show when one or more conditions match."},"min_length":{"type":"integer","minimum":0},"max_length":{"type":"integer","exclusiveMinimum":0},"pattern":{"type":"string","description":"Regex the value must match (anchored — partial matches rejected)."},"min_date":{"type":"string","description":"Earliest allowed ISO date (YYYY-MM-DD), inclusive."},"max_date":{"type":"string","description":"Latest allowed ISO date (YYYY-MM-DD), inclusive."},"min_time":{"type":"string","description":"Earliest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"max_time":{"type":"string","description":"Latest allowed time (HH:MM or HH:MM:SS, 24-hour), inclusive."},"min_selections":{"type":"integer","minimum":0},"max_selections":{"type":"integer","exclusiveMinimum":0},"amount":{"type":"number","description":"Payment amount in smallest currency unit (cents)."},"currency":{"type":"string","description":"ISO 4217 currency code, e.g. 'usd'."},"price_description":{"type":"string"},"max_file_size_mb":{"type":"number","description":"Per-file cap in MB (default 10, hard cap 25)."},"allowed_mime_types":{"type":"array","items":{"type":"string"},"description":"Whitelist; empty/undefined = any MIME accepted."},"left_label":{"type":"string","description":"Left-end label for a scale field."},"right_label":{"type":"string","description":"Right-end label for a scale field."}},"required":["id","type","label"],"additionalProperties":false}}},"required":["fields"],"additionalProperties":false},"settings":{"type":"object","properties":{"accept_responses":{"type":"boolean"},"require_auth":{"type":"boolean"},"one_response_per_user":{"type":"boolean"},"allow_multiple_responses":{"type":"boolean"},"confirmation_message":{"type":"string"},"redirect_url":{"type":"string"},"notify_on_submit":{"type":"array","items":{"type":"string"}},"auto_create_task":{"type":"boolean"},"task_title_template":{"type":"string"},"task_description_template":{"type":"string"},"task_assignee_id":{"type":"string"},"task_project_id":{"type":"string"},"task_priority":{"type":"string","enum":["urgent","high","medium","low"]},"task_due_offset_days":{"type":["integer","null"]},"auto_create_contact":{"type":"boolean"},"auto_create_crm_contact":{"type":"boolean"},"auto_create_crm_deal":{"type":"boolean"},"contact_email_field":{"type":"string"},"contact_name_field":{"type":"string"},"contact_phone_field":{"type":"string"},"contact_company_field":{"type":"string"},"contact_title_field":{"type":"string"},"contact_lifecycle_stage":{"type":"string"},"auto_create_deal":{"type":"boolean"},"deal_title_template":{"type":"string"},"deal_amount_field":{"type":"string"},"captcha_enabled":{"type":"boolean"},"send_confirmation_email":{"type":"boolean"},"confirmation_email_subject":{"type":"string"},"confirmation_email_message":{"type":"string"},"stripe_publishable_key":{"type":"string"},"include_response_in_webhook":{"type":"boolean","description":"Enrich webhook deliveries with the full response payload."}},"additionalProperties":false},"is_published":{"type":"boolean"},"closes_at":{"type":["string","null"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Form"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_form","tags":["Forms"],"description":"Delete a form and all its responses. This is a destructive action — always confirm with the user before executing. Use this when the user explicitly asks to delete or remove a form.","x-tool":{"expose":["all"]},"x-cli":{"command":"forms delete"},"parameters":[{"schema":{"$ref":"#/components/schemas/FormId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/colors":{"get":{"operationId":"get_calendar_colors","tags":["Calendar"],"description":"Get the available color palette for calendars and events. Returns 24 calendar colors and 11 event colors, each with a background and foreground hex value. Use this when the user asks what colors are available, or before setting a calendar or event color.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar colors"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ColorPaletteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}}}}},"/api/calendars/availability":{"get":{"operationId":"check_availability","tags":["Calendar"],"description":"Check free/busy availability for one or more users in a given time range. Returns busy time slots (not event details) for each user. Use this when the user asks to find a free time, check if someone is available, or schedule a meeting. Call this before create_event to avoid scheduling conflicts.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar availability"},"parameters":[{"schema":{"type":"string","description":"Comma-separated user IDs."},"required":true,"description":"Comma-separated user IDs.","name":"user_ids","in":"query"},{"schema":{"type":"string"},"required":true,"name":"start","in":"query"},{"schema":{"type":"string"},"required":true,"name":"end","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AvailabilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/conflicts":{"get":{"operationId":"calendar_conflicts","tags":["Calendar"],"description":"Detect attendee scheduling conflicts.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar conflicts"},"parameters":[{"schema":{"type":"string","description":"Comma-separated user IDs."},"required":false,"description":"Comma-separated user IDs.","name":"user_ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"start","in":"query"},{"schema":{"type":"string"},"required":false,"name":"end","in":"query"},{"schema":{"type":"string"},"required":false,"name":"exclude_event_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ConflictsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/ooo-status":{"get":{"operationId":"get_ooo_status","tags":["Calendar"],"description":"Check out-of-office status for one or more users. Returns per-user OOO flag and event details when applicable. Call this before scheduling to avoid inviting people who are OOO.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar ooo-status"},"parameters":[{"schema":{"type":"string","description":"Comma-separated user IDs."},"required":false,"description":"Comma-separated user IDs.","name":"user_ids","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OooStatusResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/ooo-conflicts":{"get":{"operationId":"list_ooo_conflicts","tags":["Calendar"],"description":"List existing events that overlap a proposed out-of-office window (`start`/`end`, RFC 3339) — the pre-commit conflict warning shown before marking OOO. Optionally exclude one event by id; each row carries the organizer's id and display name.","x-cli":{"command":"calendar ooo-conflicts"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"start","in":"query"},{"schema":{"type":"string"},"required":false,"name":"end","in":"query"},{"schema":{"type":"string"},"required":false,"name":"exclude_event_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OooConflictsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/upcoming-reminders":{"get":{"operationId":"calendar_upcoming_reminders","tags":["Calendar"],"description":"Reminders due to fire within the next `window_hours` (default 24, max 168), soonest first. Each row carries the event it is about — title, span, status, location and calendar — so the caller renders the row without a second fetch.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar upcoming-reminders","output":{"format":"table"}},"parameters":[{"schema":{"type":"string"},"required":false,"name":"window_hours","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UpcomingReminderListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars":{"get":{"operationId":"list_calendars","tags":["Calendar"],"description":"List the user's calendars. Returns calendar id, name, color, timezone, and whether it's the default. Use this to find the user's default calendar ID before creating events.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar list","aliases":["calendar ls"],"output":{"format":"table","columns":["id","name","color","is_default"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"calendars_create","tags":["Calendar"],"description":"Create a calendar.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar create","output":{"successMessage":"Calendar created: {calendar.id} — {calendar.name}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/public/{token}/feed.ics":{"get":{"operationId":"calendar_public_feed","tags":["Calendar"],"description":"Public .ics feed for a published calendar.","x-cli":{"command":"calendar public feed","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarBinaryBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/external/status":{"get":{"operationId":"calendar_external_status","tags":["Calendar"],"description":"Check whether Google OAuth is configured for this workspace.","x-cli":{"command":"calendar external status"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalOAuthStatusResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/external/auth-url":{"get":{"operationId":"calendar_external_auth_url","tags":["Calendar"],"description":"Start external provider OAuth.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"calendar external auth-url"},"parameters":[{"schema":{"type":"string","format":"uri"},"required":false,"name":"return_url","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalAuthUrlResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/external/callback":{"get":{"operationId":"calendar_external_callback","tags":["Calendar"],"description":"Complete Google Calendar OAuth, store the connection, enable primary-calendar sync, and redirect the browser.","x-tool":{"expose":["assistant"],"annotations":{"readOnly":false,"openWorld":true}},"x-cli":{"command":"calendar external callback","hidden":true},"parameters":[{"schema":{"type":"string"},"required":false,"name":"code","in":"query"},{"schema":{"type":"string"},"required":false,"name":"state","in":"query"},{"schema":{"type":"string"},"required":false,"name":"error","in":"query"},{"schema":{"type":"string","enum":["true"]},"required":false,"name":"dev_consent","in":"query"},{"schema":{"type":"string","enum":["true"]},"required":false,"name":"dev_grant","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/external/connections":{"get":{"operationId":"calendar_external_connections_list","tags":["Calendar"],"description":"List connected external accounts.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar external connections list","output":{"format":"table"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalConnectionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/external/connections/{id}":{"delete":{"operationId":"calendar_external_connection_delete","tags":["Calendar"],"description":"Disconnect external account.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar external connections delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/external/connections/{id}/calendars":{"get":{"operationId":"calendar_external_calendars_list","tags":["Calendar"],"description":"List calendars on connection.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"calendar external calendars list","output":{"format":"table"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalCalendarsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"calendar_external_calendars_enable_sync","tags":["Calendar"],"description":"Enable two-way sync.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"calendar external calendars enable-sync"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalCalendarSyncEnableInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalSyncEnableResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/external/connections/{id}/sync":{"post":{"operationId":"calendar_external_force_sync","tags":["Calendar"],"description":"Pull every mirror calendar on this connection now, rather than waiting for the scheduler. Returns the per-calendar created / updated / deleted counts, plus an `errors` row for each calendar the run could not reach — a sync can succeed for some mirrors and fail for others.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"calendar external force-sync"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ExternalForceSyncResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/external/synced/{calendar_id}":{"delete":{"operationId":"calendar_external_synced_disable","tags":["Calendar"],"description":"Disable sync for one calendar.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar external synced disable","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"calendar_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events":{"get":{"operationId":"list_events","tags":["Calendar"],"description":"List calendar events across all of the user's calendars. Supports filtering by date range, calendar, and free-text search. Returns events with id, title, start/end times, location, status, and attendees. Use this when the user asks to see their schedule, upcoming meetings, or events for a date. Use the q parameter to search for events by keyword (matches title, description, location, and attendee names).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events list","aliases":["calendar events ls"],"output":{"format":"table","columns":["id","title","start_at","end_at","status","all_day","location"]}},"parameters":[{"schema":{"type":"string"},"required":false,"name":"start","in":"query"},{"schema":{"type":"string"},"required":false,"name":"end","in":"query"},{"schema":{"type":"string"},"required":false,"name":"calendar_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"singleEvents","in":"query"},{"schema":{"type":"string"},"required":false,"name":"orderBy","in":"query"},{"schema":{"type":"string"},"required":false,"name":"showDeleted","in":"query"},{"schema":{"type":"string"},"required":false,"name":"eventTypes","in":"query"},{"schema":{"type":"string"},"required":false,"name":"updatedMin","in":"query"},{"schema":{"type":"string"},"required":false,"name":"timeZone","in":"query"},{"schema":{"type":"string"},"required":false,"name":"maxAttendees","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{calendar_id}/events":{"get":{"operationId":"list_calendar_events","tags":["Calendar"],"description":"List events scoped to a single calendar by its id — the RESTful path variant of list_events (`/api/calendars/events?calendar_id=…`). Requires at least viewer access to the calendar.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events list-by-calendar","output":{"format":"table","columns":["id","title","start_at","end_at","status","all_day","location"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"calendar_id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"start","in":"query"},{"schema":{"type":"string"},"required":false,"name":"end","in":"query"},{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"singleEvents","in":"query"},{"schema":{"type":"string"},"required":false,"name":"orderBy","in":"query"},{"schema":{"type":"string"},"required":false,"name":"showDeleted","in":"query"},{"schema":{"type":"string"},"required":false,"name":"eventTypes","in":"query"},{"schema":{"type":"string"},"required":false,"name":"updatedMin","in":"query"},{"schema":{"type":"string"},"required":false,"name":"timeZone","in":"query"},{"schema":{"type":"string"},"required":false,"name":"maxAttendees","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_event","tags":["Calendar"],"description":"Create a new calendar event. Requires a title, start time, and end time. Optionally add a description, location, attendees, recurrence, and more. Use this when the user asks to schedule a meeting, add an event, or book time. If the user doesn't specify a calendar, use list_calendars to find their default calendar ID first.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"calendar events create","output":{"successMessage":"Event created: {event.id} — {event.title}"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"calendar_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/search":{"get":{"operationId":"search_calendar_events","tags":["Calendar"],"description":"Full-text search across all calendar events for the current workspace. Returns matching events with id, title, start/end times, and calendar info. Use this when the user asks to find a specific event by name or description keyword.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events search","output":{"format":"table","columns":["id","title","start_at","end_at","calendar_name"]}},"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventSearchResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}":{"get":{"operationId":"get_event","tags":["Calendar"],"description":"Get a single calendar event by ID, including full details: title, description, location, start/end times, recurrence rule, status, visibility, and attendees with RSVP status. If the user is currently viewing an event, use the event ID from the page context.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events get"},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"maxAttendees","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_event","tags":["Calendar"],"description":"Update an existing calendar event. Provide only the fields you want to change. Use this to reschedule, change attendees, update the description, or cancel an event. If the user is currently viewing an event, use the event ID from the page context.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"calendar events update"},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_event","tags":["Calendar"],"description":"Delete a calendar event. This is a destructive action — always confirm with the user before calling. If the user is currently viewing an event, use the event ID from the page context.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/instances":{"get":{"operationId":"get_event_instances","tags":["Calendar"],"description":"List individual occurrences of a recurring event within a date range. Expands the RRULE server-side and returns instance objects with computed start/end times. Use this to find specific occurrences (e.g., 'what meetings are on next Tuesday?') or to list upcoming instances of a series.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events instances","output":{"format":"table"}},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"start","in":"query"},{"schema":{"type":"string"},"required":false,"name":"end","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventInstancesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/rsvp":{"post":{"operationId":"rsvp_event","tags":["Calendar"],"description":"RSVP to a calendar event that the user is invited to. Use this when the user asks to accept, decline, or mark tentative on an event invitation.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events rsvp"},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RsvpInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RsvpResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/rsvp-email":{"get":{"operationId":"calendar_event_rsvp_email","tags":["Calendar"],"description":"Record an attendee's RSVP through a signed email-link token and return the HTML confirmation page.","x-tool":{"expose":["assistant"],"annotations":{"readOnly":false}},"x-cli":{"command":"calendar events rsvp-email","output":{"format":"raw"},"hidden":true},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"token","in":"query"},{"schema":{"type":"string"},"required":false,"name":"rsvp","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RsvpEmailPayload"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/export":{"post":{"operationId":"calendar_event_export_ics","tags":["Calendar"],"description":"Export single event as .ics.","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true}},"x-cli":{"command":"calendar events export","output":{"format":"raw"}},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarBinaryBody"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/edit-single":{"post":{"operationId":"edit_recurring_event_single","tags":["Calendar"],"description":"Edit a single occurrence of a recurring event, creating an exception without affecting other occurrences. Use this when the user says 'move just next Tuesday's meeting to 3pm' or 'cancel only this one occurrence'.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events edit-single"},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventEditSingleInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/edit-future":{"post":{"operationId":"edit_recurring_event_future","tags":["Calendar"],"description":"Edit this and all future occurrences of a recurring event by splitting the series at the given date. Use this for 'change the meeting time from next week onwards' or 'update our recurring Friday sync starting next month'.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events edit-future"},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventEditFutureInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/edit-all":{"post":{"operationId":"edit_recurring_event_all","tags":["Calendar"],"description":"Edit all occurrences in a recurring series. Updates the master event.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events edit-all"},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/delete-single":{"post":{"operationId":"delete_recurring_event_single","tags":["Calendar"],"description":"Delete a single occurrence of a recurring event by adding the occurrence date to the master's excluded_dates. The occurrence is suppressed without affecting other instances.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events delete-single","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteSingleBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/delete-future":{"post":{"operationId":"delete_recurring_event_future","tags":["Calendar"],"description":"Delete this and all future occurrences of a recurring event by adding an UNTIL clause to the master's RRULE, ending the series the day before the given split_date.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events delete-future","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteFutureBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{event_id}/resources":{"post":{"operationId":"book_event_resources","tags":["Calendar"],"description":"Book one or more resources (rooms, equipment) for an existing event. Returns a conflict error if a resource is already booked.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events book-resources"},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"event_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceBookingInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResourcesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"list_event_resources","tags":["Calendar"],"description":"List resources currently booked for an event (rooms, equipment).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events list-resources","output":{"format":"table"}},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"event_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EventResourcesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/resources":{"delete":{"operationId":"calendar_event_unbook_resources","tags":["Calendar"],"description":"Unbook resources.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events unbook-resources","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/reminders":{"get":{"operationId":"calendar_event_reminders_list","tags":["Calendar"],"description":"List event reminders.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events reminders list","output":{"format":"table"}},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ReminderListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"calendar_event_reminders_create","tags":["Calendar"],"description":"Add a reminder.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events reminders create"},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReminderCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ReminderResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"calendar_event_reminders_set","tags":["Calendar"],"description":"Replace reminder list.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events reminders set","output":{"format":"table"}},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReminderSetInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ReminderListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/events/{id}/meeting-notes":{"post":{"operationId":"calendar_event_meeting_notes_create","tags":["Calendar"],"description":"Create a meeting-notes doc for an event, or — when `document_id` is given — link that existing doc and grant attendees access.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar events meeting-notes create"},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeetingNotesCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MeetingNotesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"calendar_event_meeting_notes_unlink","tags":["Calendar"],"description":"Unlink meeting-notes doc.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar events meeting-notes unlink","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/EventId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/resources":{"get":{"operationId":"list_resources","tags":["Calendar"],"description":"List bookable resources (rooms, equipment) in the workspace. Call before booking a room to see what's available.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar resources list","aliases":["calendar resources ls"],"output":{"format":"table","columns":["id","name","type","capacity","location"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ResourceListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"calendar_resources_create","tags":["Calendar"],"description":"Create a bookable resource.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar resources create","output":{"successMessage":"Resource created: {resource.id} — {resource.name}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/resources/{id}":{"get":{"operationId":"calendar_resource_get","tags":["Calendar"],"description":"Get a resource.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar resources get"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"calendar_resource_update","tags":["Calendar"],"description":"Update a resource.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar resources update"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"calendar_resource_delete","tags":["Calendar"],"description":"Delete a resource.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar resources delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/resources/{resource_id}/availability":{"get":{"operationId":"check_resource_availability","tags":["Calendar"],"description":"Check if a specific resource (room, equipment) is free in a time range. Call before booking to avoid conflicts.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar resources availability"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"resource_id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"start","in":"query"},{"schema":{"type":"string"},"required":false,"name":"end","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ResourceAvailabilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/reminders/{reminderId}":{"delete":{"operationId":"calendar_reminder_delete","tags":["Calendar"],"description":"Delete a reminder.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar reminders delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"reminderId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{calendar_id}/permissions":{"get":{"operationId":"list_calendar_permissions","tags":["Calendar"],"description":"List who has access to a calendar (collaborators and pending external invites). Use this to answer 'who can see my calendar?'.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar permissions list","output":{"format":"table"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"calendar_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PermissionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"share_calendar","tags":["Calendar"],"description":"Share a calendar with a user or team as a viewer or editor. Provide exactly one of user_id or team_id. Guest sharing is not supported for calendars.","x-tool":{"expose":["all"]},"x-cli":{"command":"calendar permissions add","output":{"format":"table"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"calendar_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionSetInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PermissionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{calendar_id}/permissions/{user_id}":{"get":{"operationId":"get_calendar_permission","tags":["Calendar"],"description":"Get a single user's permission entry on a calendar, including their role, display name, and email. Useful for checking if a specific user has access without listing all permissions.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar permissions get"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"calendar_id","in":"path"},{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"user_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarPermissionEntry"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_calendar_permission","tags":["Calendar"],"description":"Update an existing calendar permission role (e.g., upgrade a viewer to editor or downgrade an editor to viewer). The user must already have a permission entry.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar permissions update"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"calendar_id","in":"path"},{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"user_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{id}/permissions/{principalId}":{"delete":{"operationId":"calendars_permission_remove","tags":["Calendar"],"description":"Remove a user/group permission.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar permissions remove","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"principalId","in":"path"},{"schema":{"type":"string","enum":["user","team"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{id}/pending-shares/{pendingId}":{"delete":{"operationId":"calendars_pending_share_revoke","tags":["Calendar"],"description":"Revoke a pending invite.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar pending-shares revoke","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"pendingId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{id}/share-invite":{"post":{"operationId":"calendars_share_invite","tags":["Calendar"],"description":"Email-invite an external recipient to a calendar. `granted: \"direct\"` means the recipient was already a workspace member and holds the permission now; `granted: \"pending\"` means it is staged in `pending_shares` until they accept the emailed invite.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"calendar share-invite"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarShareInviteInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarShareInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{calendar_id}/publish":{"post":{"operationId":"publish_calendar","tags":["Calendar"],"description":"Publish a calendar as a public read-only .ics feed URL (no auth required). Returns a shareable feed URL that anyone can subscribe to from Google/Apple/Outlook Calendar.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"calendar publish"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"calendar_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PublishResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"unpublish_calendar","tags":["Calendar"],"description":"Revoke the public .ics feed for a calendar, making it private again.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"calendar unpublish","output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"calendar_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{id}/import":{"post":{"operationId":"calendar_import_ics","tags":["Calendar"],"description":"Import an .ics file.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar import"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ImportIcsInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ImportIcsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{id}/import-url":{"post":{"operationId":"calendar_import_ics_url","tags":["Calendar"],"description":"Import an .ics feed by URL. Fetches the URL server-side and imports its events into the calendar.","x-tool":{"expose":["assistant","mcp","coworker"],"annotations":{"openWorld":true}},"x-cli":{"command":"calendar import-url"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportIcsUrlInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ImportIcsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{id}/export":{"post":{"operationId":"calendar_export_ics","tags":["Calendar"],"description":"Export entire calendar as .ics.","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true}},"x-cli":{"command":"calendar export","output":{"format":"raw"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarBinaryBody"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{id}/clear":{"delete":{"operationId":"clear_calendar","tags":["Calendar"],"description":"Delete ALL events from a calendar. Owner-only — use for resetting shared calendars at quarter boundaries or wiping test data. Returns the count of deleted events. This is irreversible.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar clear","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarClearResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/calendars/{id}":{"get":{"operationId":"get_calendar","tags":["Calendar"],"description":"Get a single calendar by ID. Returns the calendar's name, color, timezone, default status, and owner. Use this when the user asks about a specific calendar's settings or before creating events to verify the timezone.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar get"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"calendars_update","tags":["Calendar"],"description":"Update calendar fields.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar update"},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"calendars_delete","tags":["Calendar"],"description":"Delete a calendar.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"calendar delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/CalendarId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CalendarSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/spaces":{"get":{"operationId":"list_wiki_spaces","tags":["Wiki"],"description":"List all wiki spaces. Returns spaces with id, name, slug, description, icon, owner info, privacy setting, and page count. Use this when the user asks to see wiki spaces, browse the knowledge base, or when you need a space ID to create a page.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki spaces list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSpaceListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_wiki_space","tags":["Wiki"],"description":"Create a new wiki space (a top-level container for pages). Use this when the user asks to create a new knowledge base area, team wiki, or documentation section. Spaces organize pages by team or domain (e.g., 'Engineering', 'Product', 'Company Handbook').","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki spaces create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiSpaceCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSpace"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/spaces/{id}/members":{"get":{"operationId":"wiki_space_members_list","tags":["Wiki"],"description":"List distinct members of a space — the owner plus everyone with a page-level permission inside it.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki spaces members"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiSpaceId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSpaceMemberListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"wiki_space_member_add","tags":["Wiki"],"description":"Add a user as a direct member of a wiki space with a given role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki spaces members add","output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiSpaceId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiSpaceMemberAddInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/spaces/{id}/members/{userId}":{"delete":{"operationId":"wiki_space_member_remove","tags":["Wiki"],"description":"Remove a direct member from a wiki space.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki spaces members remove","output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiSpaceId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"userId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/spaces/{id}/graph":{"get":{"operationId":"get_wiki_space_graph","tags":["Wiki"],"description":"Get backlink graph data for a wiki space. Returns nodes (pages) and edges (links between pages). Use this when the user asks to visualize the knowledge graph, see how pages connect, or find highly-linked 'hub' pages.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki spaces graph","output":{"format":"object"}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiSpaceId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiGraphResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/spaces/{id}/pages":{"get":{"operationId":"list_wiki_space_pages","tags":["Wiki"],"description":"List pages in a wiki space with offset/limit pagination. Returns page summaries (id, title, slug, icon, parent_page_id, sort_order). Use this when the user asks to see all pages in a space, or when you need to paginate through a large space.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki spaces pages list","output":{"columns":["id","title","slug"]}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiSpaceId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageChildListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_wiki_page","tags":["Wiki"],"description":"Create a new wiki page within a space. Pages use Markdown content and support nested hierarchies via parent_page_id. Use this when the user asks to create a wiki page, add documentation, write a runbook, or add to the knowledge base. Call list_wiki_spaces first to get the space ID.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki pages create"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiSpaceId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPage"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/spaces/{id}/pages/import":{"post":{"operationId":"wiki_page_import","tags":["Wiki"],"description":"Import a Markdown / HTML / plain-text file as a new wiki page. Multipart form: `file` (required), optional `title`, `parent_page_id`, `icon`, `sort_order`.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"wiki pages import"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiSpaceId"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPage"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/spaces/{slug}":{"get":{"operationId":"wiki_space_get","tags":["Wiki"],"description":"Get a wiki space by slug, with its full page tree. Supports cursor pagination on `pages`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki spaces get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSpace"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/spaces/{id}":{"patch":{"operationId":"wiki_space_update","tags":["Wiki"],"description":"Update a wiki space. Only the space owner may change settings.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"wiki spaces update"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiSpaceId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiSpaceUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSpace"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"wiki_space_delete","tags":["Wiki"],"description":"Delete a wiki space and all of its pages.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki spaces delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiSpaceId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/trash":{"get":{"operationId":"wiki_trash_list","tags":["Wiki"],"description":"List trashed (soft-deleted) wiki pages in the workspace.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki trash list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiTrashListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/restore":{"post":{"operationId":"wiki_page_restore","tags":["Wiki"],"description":"Restore a trashed wiki page and its children.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki pages restore"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/permanent":{"delete":{"operationId":"wiki_page_permanent_delete","tags":["Wiki"],"description":"Permanently delete a trashed wiki page. Irreversible.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki pages permanent-delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/children":{"get":{"operationId":"wiki_page_children_list","tags":["Wiki"],"description":"List the immediate child pages of a wiki page. Use this to traverse the page tree one level at a time, or to count children before a destructive delete.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages children"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageChildListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/backlinks":{"get":{"operationId":"wiki_page_backlinks_list","tags":["Wiki"],"description":"List wiki pages that contain `[[link]]` references to this page. Use this to see what pages cite a given page, or to find inbound knowledge links.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages backlinks"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiBacklinkListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/versions":{"get":{"operationId":"list_wiki_page_versions","tags":["Wiki"],"description":"List the saved version snapshots for a wiki page (most recent first). Use this when the user asks for revision history, wants to see who edited and when, or needs to find a version to revert to.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages versions list"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageVersionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_wiki_page_version","tags":["Wiki"],"description":"Create a manual snapshot of the current wiki page state. Useful before a risky edit or when the user wants to mark a 'known good' checkpoint. Optional `label` names the snapshot. Returns the new version's id + metadata.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages versions create"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageVersionCreateBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageVersionSummary"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/versions/{versionId}":{"get":{"operationId":"get_wiki_page_version","tags":["Wiki"],"description":"Get a wiki page version's full content (title + markdown body). Use this when the user asks what a previous version looked like, wants to compare versions, or needs the content of a specific snapshot.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages versions get"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"versionId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageVersion"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/versions/{versionId}/revert":{"post":{"operationId":"revert_wiki_page_version","tags":["Wiki"],"description":"Revert a wiki page to a previous version snapshot. This replaces the current content with the version's content and clears the CRDT state. A snapshot of the current state is automatically created before reverting. This is destructive for the in-progress edit — always confirm with the user first.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki pages versions revert","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"versionId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiOkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/duplicate":{"post":{"operationId":"wiki_page_duplicate","tags":["Wiki"],"description":"Duplicate a wiki page (and optionally its descendants) into a target space + parent. Returns the new top-level page.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki pages duplicate"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageDuplicateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPage"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/export":{"post":{"operationId":"wiki_page_export","tags":["Wiki"],"description":"Export a wiki page to docx, pdf, html, or md. Streams the file with a Content-Disposition attachment header.","x-tool":{"expose":["all"],"annotations":{"readOnly":true}},"x-cli":{"hidden":true,"command":"wiki pages export"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageExportBody"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/databases":{"get":{"operationId":"list_wiki_page_databases","tags":["Wiki"],"description":"List all inline databases hosted on a wiki page.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages databases list"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabaseListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"wiki_page_database_create","tags":["Wiki"],"description":"Create an inline database on a specific wiki page.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages databases create","output":{"format":"object"}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiDatabaseInPageCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabase"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/permissions":{"get":{"operationId":"list_wiki_page_permissions","tags":["Wiki"],"description":"List per-page permissions granted on a wiki page. Only the page owner (or space owner) can see these. Returns each grantee's user_id, role (viewer/commenter/editor/owner), and display info. Use this when the user asks who has access to a page.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages permissions list"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPagePermissionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"set_wiki_page_permission","tags":["Wiki"],"description":"Grant or update a per-page permission on a wiki page. Only the page owner can set permissions. Provide exactly one of user_id or team_id. Use this when the user asks to share a page with a user or a team.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki pages permissions set"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPagePermissionSetInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPagePermissionSetResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/permissions/{userId}":{"delete":{"operationId":"remove_wiki_page_permission","tags":["Wiki"],"description":"Revoke a per-page permission. Only the page owner can remove permissions. Use this when the user asks to remove access to a page. Specify the principal_id and principal_type (user or team).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages permissions delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"userId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/share-invite":{"post":{"operationId":"create_wiki_page_share_invite","tags":["Wiki"],"description":"Send a wiki page share invite to an external email. Creates a `pending_shares` row when the email is outside the workspace domain.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"wiki pages share-invite"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageShareInviteInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageShareInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/visibility":{"patch":{"operationId":"update_wiki_page_visibility","tags":["Wiki"],"description":"Update a wiki page's effective visibility by toggling the parent space's visibility. Only the page owner can change visibility. 'restricted' = invite-only, 'workspace' = all workspace members can view, 'link' = anyone with the link, 'public' = anyone on the internet.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"wiki pages visibility"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageVisibilityInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageVisibilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/revoke-link":{"post":{"operationId":"revoke_wiki_page_link","tags":["Wiki"],"description":"Revoke a wiki page's active public/link visibility. Resets the parent space's visibility to 'restricted'. Only the page owner can revoke the link. Use this when the user asks to unshare a page, disable a public link, or kill external access.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"wiki pages revoke-link","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageVisibilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/comments":{"get":{"operationId":"wiki_page_comments_list","tags":["Wiki"],"description":"List threaded comments on a wiki page. Reuses the Docs CommentsPanel UI via the `document_id` alias on each comment.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages comments list"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageCommentListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"wiki_page_comment_create","tags":["Wiki"],"description":"Add a comment or threaded reply to a wiki page. Notifies the page author.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki pages comments create"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageCommentCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageComment"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/comments/{commentId}":{"patch":{"operationId":"wiki_page_comment_update","tags":["Wiki"],"description":"Resolve or unresolve a wiki page comment thread. Editor role required.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages comments update"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"commentId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageCommentUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPageComment"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"wiki_page_comment_delete","tags":["Wiki"],"description":"Delete a wiki page comment. Author or page owner only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages comments delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"commentId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/comments/{commentId}/reactions":{"post":{"operationId":"wiki_page_comment_reaction_add","tags":["Wiki"],"description":"Add an emoji reaction to a wiki page comment. Idempotent per (user, emoji). Returns the comment's updated reaction aggregate.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages comments react"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"commentId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentReactionInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CommentReactionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}/comments/{commentId}/reactions/{emoji}":{"delete":{"operationId":"wiki_page_comment_reaction_remove","tags":["Wiki"],"description":"Remove the caller's emoji reaction from a wiki page comment. Returns the comment's updated reaction aggregate.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages comments unreact"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"commentId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"emoji","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CommentReactionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/pages/{id}":{"get":{"operationId":"get_wiki_page","tags":["Wiki"],"description":"Get a wiki page's full details including Markdown content, child pages, backlinks (pages that link to this page), and metadata. Use this when the user asks about a page's content, wants to read documentation, or needs to check what links to a specific page. If the user is currently viewing a wiki page, use the resource ID from page context.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki pages get"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPage"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_wiki_page","tags":["Wiki"],"description":"Update an existing wiki page's content, title, icon, or parent. Use this when the user asks to edit a wiki page, update documentation, or move a page to a different parent. If the user is currently viewing a wiki page, use the resource ID from page context.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki pages update"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiPage"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_wiki_page","tags":["Wiki"],"description":"Delete a wiki page and all its child pages. This is a destructive action — always confirm with the user before executing. Deleting a parent page deletes the entire sub-tree. Use this when the user explicitly asks to delete or remove a wiki page.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki pages delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"cascade","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiPageDeleteCascadeRequiredResponse"}}}}}}},"/api/wiki/search":{"get":{"operationId":"search_wiki","tags":["Wiki"],"description":"Case-insensitive substring search across wiki page titles and Markdown content. Returns only pages the caller can view under the effective page-to-space permission rules, with id, title, space, and content snippets. Use this when the user asks to find information in the wiki, look up documentation, or search the knowledge base. More efficient than reading individual pages.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki search"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"space","in":"query"},{"schema":{"type":"string"},"required":false,"name":"author","in":"query"},{"schema":{"type":"string"},"required":false,"name":"updated_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"updated_before","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSearchResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/databases":{"post":{"operationId":"wiki_database_create","tags":["Wiki"],"description":"Create an inline database on a wiki page. Requires editor role on the host page.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki databases create","output":{"format":"object"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiDatabaseCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabase"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/databases/{id}/rows":{"post":{"operationId":"wiki_database_row_create","tags":["Wiki"],"description":"Append a row to an inline database. Requires editor role on the host page.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki databases rows create"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiDatabaseRowCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabaseRow"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/databases/{id}/rows/{rowId}":{"patch":{"operationId":"wiki_database_row_update","tags":["Wiki"],"description":"Update properties or sort order on a database row.","x-tool":{"expose":["all"]},"x-cli":{"command":"wiki databases rows update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"rowId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiDatabaseRowUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabaseRow"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"wiki_database_row_delete","tags":["Wiki"],"description":"Delete a database row.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki databases rows delete","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"rowId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"get_wiki_database_row","tags":["Wiki"],"description":"Get a single database row by id.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki databases rows get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"rowId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabaseRow"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/databases/{id}/query":{"get":{"operationId":"query_wiki_database","tags":["Wiki"],"description":"Query rows from an inline database with optional view, filter, and sort. Returns paginated results.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki databases query"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"page_size","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabaseQueryResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/databases/{id}/relations/ensure-reverse":{"post":{"operationId":"ensure_wiki_reverse_relation","tags":["Wiki"],"description":"Auto-create the reverse relation property on the target database if missing. Idempotent — returns the existing or newly-created reverse property id.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki databases ensure-reverse"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiDatabaseEnsureReverseRelationInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabaseEnsureReverseRelationResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/databases/{id}/rollups":{"get":{"operationId":"compute_wiki_rollups","tags":["Wiki"],"description":"Compute and return rollup values for all rows in the database. Each rollup aggregates a property across related rows.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki databases rollups"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabaseRollupListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/databases/{id}":{"get":{"operationId":"wiki_database_get","tags":["Wiki"],"description":"Get an inline database with its full row set.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki databases get","output":{"format":"object"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabase"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"wiki_database_update","tags":["Wiki"],"description":"Update an inline database's name, schema, or views. Requires editor role on the host page.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"wiki databases update","output":{"format":"object"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiDatabaseUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDatabase"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/synced-blocks/by-page/{pageId}":{"get":{"operationId":"list_wiki_synced_blocks_by_page","tags":["Wiki"],"description":"List synced blocks that were originally created on a specific page. Use this when the user asks what shared content a page publishes, or to audit reuse.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki synced-blocks by-page"},"parameters":[{"schema":{"$ref":"#/components/schemas/WikiPageId"},"required":true,"name":"pageId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSyncedBlockListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/synced-blocks":{"post":{"operationId":"create_wiki_synced_block","tags":["Wiki"],"description":"Create a synced block — a reusable content fragment that can be embedded in multiple wiki pages and stays in sync everywhere it's used. Returns the new block's id. Use this when the user asks to create a shared snippet, reusable callout, or cross-page content.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki synced-blocks create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiSyncedBlockCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSyncedBlock"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/synced-blocks/{id}":{"get":{"operationId":"get_wiki_synced_block","tags":["Wiki"],"description":"Get a synced block by ID. Returns the block's content and metadata. Use this when you need to read the current content of a shared block.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki synced-blocks get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSyncedBlock"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_wiki_synced_block","tags":["Wiki"],"description":"Update a synced block's content. All pages embedding this block will reflect the new content. Use this when the user asks to edit shared content or update a reusable snippet.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki synced-blocks update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WikiSyncedBlockUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSyncedBlock"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_wiki_synced_block","tags":["Wiki"],"description":"Soft-delete a synced block. Embedded references will show error chips until restored. Use restore_wiki_synced_block to undo.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki synced-blocks delete"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiDeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/wiki/synced-blocks/{id}/restore":{"post":{"operationId":"restore_wiki_synced_block","tags":["Wiki"],"description":"Restore a previously deleted synced block. Embedding pages will render the block again instead of showing error chips.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"wiki synced-blocks restore"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WikiSyncedBlock"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/init":{"post":{"operationId":"admin_init","tags":["Admin"],"description":"Initialize system roles (idempotent, admin only)","x-tool":{"expose":[]},"x-cli":{"command":"admin init","hidden":true,"output":{"format":"none","successMessage":"System roles initialized"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/workspace":{"get":{"operationId":"get_workspace","tags":["Admin"],"description":"Get the current workspace details (id, name, slug). Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin workspace get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminWorkspaceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_workspace","tags":["Admin"],"description":"Update workspace name or slug. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin workspace update","output":{"successMessage":"Workspace updated"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminWorkspaceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"admin_workspace_delete","tags":["Admin"],"description":"Archive the workspace. Owner-only. Sets archived_at which structurally blocks all authenticated requests. Cancels Stripe subscription. Data is preserved for potential restore or GDPR purge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"string","enum":["DELETE"],"description":"Must be the literal string 'DELETE' to confirm"}},"required":["confirm"]}}}},"responses":{"200":{"description":"Workspace archived","content":{"application/json":{"schema":{"type":"object","properties":{"archived":{"type":"boolean"}},"required":["archived"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/workspace/logo":{"post":{"operationId":"admin_workspace_logo_upload","tags":["Admin"],"description":"Upload workspace logo (admin only) Accepts multipart/form-data with a \"file\" field.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin workspace logo upload","output":{"successMessage":"Workspace logo uploaded"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminLogoUploadResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"admin_workspace_logo_delete","tags":["Admin"],"description":"Remove workspace logo (admin only)","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin workspace logo delete","confirm":true,"output":{"successMessage":"Workspace logo removed"}},"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/settings":{"get":{"operationId":"get_settings","tags":["Admin"],"description":"Get all workspace settings. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin settings get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminWorkspaceSettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_settings","tags":["Admin"],"description":"Update workspace settings (name, logo, timezone, etc.). Requires admin role. Pass a flat key-value object.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin settings update","output":{"successMessage":"Settings updated"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceSettingsUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminWorkspaceSettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/security":{"get":{"operationId":"get_security_settings","tags":["Admin"],"description":"Get workspace security settings (require_2fa, session_timeout_hours, password_min_length, ip_allowlist). Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin security get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SecuritySettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Workspace-level security policy."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_security_settings","tags":["Admin"],"description":"Update workspace security settings. Emits a security.updated audit event. Requires admin role. session_timeout_hours takes effect on next login; require_2fa stores the policy flag (enforcement is gated on 2FA implementation).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin security update","output":{"successMessage":"Security settings updated"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecuritySettingsUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SecuritySettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Workspace-level security policy."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/notification-defaults":{"get":{"operationId":"admin_notification_defaults_get","tags":["Admin"],"description":"Read workspace-default email notification prefs. Returns sensible defaults (all enabled) when never configured.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin notification-defaults get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NotificationDefaultsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"admin_notification_defaults_update","tags":["Admin"],"description":"Partially update workspace-default email notification prefs. Emits settings.updated audit event.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin notification-defaults update","output":{"successMessage":"Notification defaults updated"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationDefaultsUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NotificationDefaultsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/email-signature":{"get":{"operationId":"get_email_signature","tags":["Admin"],"description":"Get the workspace default email signature (Markdown). Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin email-signature get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailSignatureResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"set_email_signature","tags":["Admin"],"description":"Set the workspace default email signature. Pass null (or omit markdown) to clear. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin email-signature set","output":{"successMessage":"Email signature updated"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSignatureUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailSignatureResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/email-deliverability":{"get":{"operationId":"get_email_deliverability","tags":["Admin"],"description":"Get email deliverability statistics (sent/bounced/complained/opened rates) for the past 30 days. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin email-deliverability get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EmailDeliverabilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users":{"get":{"operationId":"list_users","tags":["Admin"],"description":"List all users and agents in the workspace. Returns users with id, display_name, email, type (human/agent), roles, status, storage usage, and timestamps. Requires admin or owner role. Use this when the user asks to see workspace members, find a specific user, check agent accounts, or audit user activity.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin users list","output":{"columns":["id","display_name","email","type","role"]}},"parameters":[{"schema":{"type":"string","description":"Filter by user type (`human` | `agent`)."},"required":false,"description":"Filter by user type (`human` | `agent`).","name":"type","in":"query"},{"schema":{"type":"string","description":"Filter by role name."},"required":false,"description":"Filter by role name.","name":"role","in":"query"},{"schema":{"type":"string","description":"Free-text search across display name + email."},"required":false,"description":"Free-text search across display name + email.","name":"q","in":"query"},{"schema":{"type":"string","description":"Opaque pagination cursor (preferred over offset)."},"required":false,"description":"Opaque pagination cursor (preferred over offset).","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"description":"Page size (default 50, max 500)."},"required":false,"description":"Page size (default 50, max 500).","name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Offset for legacy pagination (must be ≥ 0)."},"required":false,"description":"Offset for legacy pagination (must be ≥ 0).","name":"offset","in":"query"},{"schema":{"type":["boolean","null"],"description":"When true, hydrate each user with their `coworker_config` row (or `null`). Skips a second roundtrip when the caller needs to discriminate Coworker vs Agent in one fetch."},"required":false,"description":"When true, hydrate each user with their `coworker_config` row (or `null`). Skips a second roundtrip when the caller needs to discriminate Coworker vs Agent in one fetch.","name":"include_coworker_config","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminUsersListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_user","tags":["Admin"],"description":"Provision a new user or agent account in the workspace. Requires admin or owner role. Use this when the user asks to add a new team member, create an agent account, or provision a new bot. For agents, the response is 201 with {user, api_key} (api_key shown once, response carries Cache-Control: no-store). For humans, the response is 200 with {message, invite} after an invite email is sent.","x-tool":{"expose":["assistant"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"admin users create","output":{"successMessage":"User created"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreateUserInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreateUserResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/provision-agent":{"post":{"operationId":"provision_agent","tags":["Admin"],"description":"Provision a new AI agent account in the workspace. Auto-generates an email address and API key. Requires admin role. Returns 201 with `{user, api_key}` — api_key is shown once (response carries Cache-Control: no-store).","x-tool":{"expose":["assistant"]},"x-cli":{"command":"admin users provision-agent","output":{"successMessage":"Agent provisioned: {user.display_name}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProvisionAgentInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminAgentProvisionedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/invite":{"post":{"operationId":"invite_user","tags":["Admin"],"description":"Invite a human user to the workspace by email. Sends an invite email with a link to accept. Requires admin role.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"admin users invite","output":{"successMessage":"Invite sent"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminInviteUsersInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminInviteCreatedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/{user_id}/roles":{"post":{"operationId":"assign_role","tags":["Admin"],"description":"Assign a role to a user. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin users roles assign","output":{"successMessage":"Role assigned to user {user_id}"}},"parameters":[{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"user_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserRoleAssignInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminUserResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/{user_id}/roles/{role}":{"delete":{"operationId":"remove_role","tags":["Admin"],"description":"Remove a role from a user. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin users roles remove","confirm":true,"output":{"format":"none","successMessage":"Role {role} removed from user {user_id}"}},"parameters":[{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"user_id","in":"path"},{"schema":{"type":"string","description":"Role name to remove."},"required":true,"description":"Role name to remove.","name":"role","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/{id}":{"get":{"operationId":"admin_user_get","tags":["Admin"],"description":"Get user details","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin users get"},"parameters":[{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminUserResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_user","tags":["Admin"],"description":"Update a user's role, status, or quota. Requires admin or owner role. Use this when the user asks to change someone's role, deactivate an account, or adjust a user's storage quota. Cannot remove the owner role from the last remaining owner.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin users update","output":{"successMessage":"User {id} updated"}},"parameters":[{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminUserResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_user","tags":["Admin"],"description":"Deactivate or delete a user from the workspace. Requires admin role. Cannot delete the last remaining owner. Irreversible.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin users delete","confirm":true},"parameters":[{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/{id}/reset-password":{"post":{"operationId":"admin_user_reset_password","tags":["Admin"],"description":"Admin-initiated password reset. Returns the reset outcome — `sent` is false when the email bounced, in which case `reset_url` is the only way the caller reaches the link.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"admin users reset-password","confirm":true,"output":{"format":"none","successMessage":"Password reset initiated for user {id}"}},"parameters":[{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminPasswordResetResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/{id}/suspend":{"post":{"operationId":"admin_user_suspend","tags":["Admin"],"description":"Suspend a user account. Suspended accounts return 403 on all API calls.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin users suspend","confirm":true,"output":{"format":"none","successMessage":"User {id} suspended"}},"parameters":[{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/{id}/unsuspend":{"post":{"operationId":"admin_user_unsuspend","tags":["Admin"],"description":"Unsuspend a user account. Restores access to all API calls.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin users unsuspend","output":{"format":"none","successMessage":"User {id} unsuspended"}},"parameters":[{"schema":{"$ref":"#/components/schemas/UserId"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/invites":{"get":{"operationId":"admin_invites_list","tags":["Admin"],"description":"List unaccepted, unexpired workspace invites","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin invites list","output":{"columns":["id","email","role","expires_at"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminInvitesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/invites/{id}/resend":{"post":{"operationId":"admin_invite_resend","tags":["Admin"],"description":"Resend invite email + refresh expiry","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"admin invites resend","output":{"successMessage":"Invite {id} resent"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/invites/{id}":{"delete":{"operationId":"admin_invite_delete","tags":["Admin"],"description":"Revoke (cancel) a pending invite","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin invites delete","confirm":true,"output":{"successMessage":"Invite {id} revoked"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/invites/{id}/link":{"get":{"operationId":"admin_invite_link","tags":["Admin"],"description":"Get the invite URL for copying (admin-only)","x-cli":{"command":"admin invites link","output":{"columns":["invite_url"]}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminInviteLinkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/roles":{"get":{"operationId":"list_roles","tags":["Admin"],"description":"List all roles in the workspace (system roles + custom roles). Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin roles list","output":{"columns":["id","name","is_system","permissions"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminRolesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_role","tags":["Admin"],"description":"Create a custom role with specific permissions. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin roles create","output":{"successMessage":"Role created: {name}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRoleCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminRoleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/roles/{id}":{"patch":{"operationId":"update_role","tags":["Admin"],"description":"Update a custom role's name or permissions. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin roles update","output":{"successMessage":"Role {id} updated"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRoleUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminRoleResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_role","tags":["Admin"],"description":"Delete a custom role. System roles cannot be deleted. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin roles delete","confirm":true,"output":{"successMessage":"Role {id} deleted"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/audit-log":{"get":{"operationId":"get_audit_log","tags":["Admin"],"description":"Query the workspace audit log. Returns timestamped records of significant actions (logins, document operations, role changes, settings updates, etc.) with user, action, resource type/ID, IP address, and metadata. Requires admin or owner role. Use this when the user asks about workspace activity, security events, who changed something, or compliance reporting.","x-cli":{"command":"admin audit-log list","output":{"columns":["timestamp","user_id","action","resource_type","resource_id"]}},"parameters":[{"schema":{"type":"string","description":"Filter by acting user ID."},"required":false,"description":"Filter by acting user ID.","name":"user_id","in":"query"},{"schema":{"type":"string","enum":["user.created","user.role_changed","user.login","user.login_failed","user.logout","user.password_reset","user.updated","user.invited","user.deleted","user.suspended","user.unsuspended","document.created","document.updated","document.deleted","document.shared","document.exported","task.created","task.assigned","task.completed","task.status_changed","task.commented","task.pr_linked","task.pr_merged","task.pr_closed","task.commit_linked","task.commit_landed","task.due_soon","task.overdue","task.updated","project.created","project.deleted","task.deleted","task.restored","comment.created","mention","channel.created","channel.deleted","channel.member_added","channel.member_removed","deal.stage_changed","deal.won","deal.lost","contact.deleted","settings.updated","role.created","role.updated","role.deleted","api_key.created","api_key.revoked","api_key.rotated","api_key.updated","security.updated","billing.payment_succeeded","sheet.updated","slide.updated","file.uploaded","file.deleted","file.shared","file.permission_updated","file.permission_revoked","file.link_revoked","folder.created","form.submitted","form.shared","form.unshared","form.visibility_changed","form.link_revoked","email.received","email.sent","email.bounced","email.complained","wiki.page_created","wiki.page_updated","wiki.page_deleted","wiki.page_trashed","wiki.page_restored","wiki.page_shared","wiki.page_exported","wiki.permission_removed","event.created","event.updated","event.deleted","event.rsvp_accepted","event.rsvp_declined","document.link_revoked","wiki.link_revoked","team.created","team.member_added","team.member_removed","team.member_left","team.join_requested","automation.workflow_created","automation.workflow_updated","automation.workflow_deleted","automation.workflow_enabled","automation.workflow_disabled","automation.workflow_duplicated","automation.webhook_key_rotated","automation.run_started","automation.run_completed","user.email_verified","user.phone_verified","agent.created","agent.deleted","agent.first_tool_call_succeeded","integration.connected","integration.event_received","invite.accepted","member.created","friend_invite.signup_completed","friend_invite.bonus_locked","referral.captured","billing.trial_converted","bonus.earned","bonus.paused","bonus.restored","quota.threshold_crossed","billing.topup_purchased","billing.auto_recharge_fired","billing.auto_recharge_failed","billing.plan_changed","billing.payment_failed","billing.subscription_canceled","billing.annual_refund_issued","billing.payment_method_added","billing.webhook_orphaned","billing.webhook_received","security.member_cap_blocked","security.slug_rotated","monetization.anti_abuse_flag_raised","monetization.audio_duration_exceeded","alert.received","account.data_exported","document.visibility_changed","document.unshared","user.delete_attempted","role.update_attempted","role.delete_attempted","test_notification_email.sent","billing.seats_synced","webhook.registered","webhook.updated","webhook.deleted","webhook.rotated_secret","webhook.reactivated","webhook.auto_disabled","workspace.integration.updated","workspace.merged","analytics.user_data_deleted","analytics.schema_override_updated","analytics.dashboard_permission_granted","analytics.dashboard_permission_revoked","sign.created","sign.prepared","sign.confirmed_send","sign.sent","sign.viewed","sign.consented","sign.signed","sign.completed","sign.voided","sign.declined","sign.expired","sign.retention_email_sent","sign.retrieved","sign.purge_queued","sign.purged"],"description":"Filter by action verb."},"required":false,"description":"Filter by action verb.","name":"action","in":"query"},{"schema":{"type":"string","description":"Filter by resource type."},"required":false,"description":"Filter by resource type.","name":"resource_type","in":"query"},{"schema":{"type":"string","description":"Lower-bound ISO 8601 datetime (inclusive). Bare YYYY-MM-DD is interpreted as UTC midnight. Include a TZ offset for local-day filtering, e.g. 2026-05-10T00:00:00-07:00."},"required":false,"description":"Lower-bound ISO 8601 datetime (inclusive). Bare YYYY-MM-DD is interpreted as UTC midnight. Include a TZ offset for local-day filtering, e.g. 2026-05-10T00:00:00-07:00.","name":"start","in":"query"},{"schema":{"type":"string","description":"Upper-bound ISO 8601 datetime (inclusive). Bare YYYY-MM-DD is interpreted as UTC midnight. Include a TZ offset for local-day filtering, e.g. 2026-05-10T23:59:59-07:00."},"required":false,"description":"Upper-bound ISO 8601 datetime (inclusive). Bare YYYY-MM-DD is interpreted as UTC midnight. Include a TZ offset for local-day filtering, e.g. 2026-05-10T23:59:59-07:00.","name":"end","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"description":"Page size (default 50, max 500)."},"required":false,"description":"Page size (default 50, max 500).","name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Offset for pagination (must be ≥ 0)."},"required":false,"description":"Offset for pagination (must be ≥ 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminAuditLogResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/audit-log/export":{"get":{"operationId":"admin_audit_log_export","tags":["Admin"],"description":"Export audit log as CSV","x-cli":{"command":"admin audit-log export","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string"},"required":false,"name":"user_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"action","in":"query"},{"schema":{"type":"string"},"required":false,"name":"resource_type","in":"query"},{"schema":{"type":"string","description":"Lower-bound ISO 8601 datetime (inclusive). Bare YYYY-MM-DD is interpreted as UTC midnight."},"required":false,"description":"Lower-bound ISO 8601 datetime (inclusive). Bare YYYY-MM-DD is interpreted as UTC midnight.","name":"start","in":"query"},{"schema":{"type":"string","description":"Upper-bound ISO 8601 datetime (inclusive). Bare YYYY-MM-DD is interpreted as UTC midnight."},"required":false,"description":"Upper-bound ISO 8601 datetime (inclusive). Bare YYYY-MM-DD is interpreted as UTC midnight.","name":"end","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminBinaryBody"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/external-collaborators":{"get":{"operationId":"admin_external_collaborators_list","tags":["Admin"],"description":"List every external collaborator holding a live grant in this workspace — people who can reach workspace content without being members of it. Each row carries their identity, the documents they can currently reach with the role on each, and when they last acted in this workspace (null means never). Requires admin or owner role. Use this when the user asks who outside the company can see their content, who still has access, or which external access is stale enough to revoke.","x-cli":{"command":"admin external-collaborators list","output":{"columns":["display_name","email","resource_count","last_access_at"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminExternalCollaboratorsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/external-collaborators/{user_id}":{"delete":{"operationId":"admin_external_collaborator_revoke","tags":["Admin"],"description":"Cut one external collaborator off from this workspace — removes every grant they hold here in a single action, and disconnects any live editing session. Other people's grants on the same documents are untouched, and grants this person holds in OTHER workspaces are unreachable from here. Answers 404 when the id is not an external collaborator of this workspace (a member, or somebody who already holds nothing). Requires admin or owner role.","x-cli":{"command":"admin external-collaborators revoke","confirm":true,"output":{"successMessage":"Revoked {revoked_count} grant(s)"}},"parameters":[{"schema":{"allOf":[{"$ref":"#/components/schemas/UserId"},{"description":"The `users.id` the grants point at. It is a row in the collaborator's OWN workspace — the same value the roster returns — never a member of this one."}]},"required":true,"description":"The `users.id` the grants point at. It is a row in the collaborator's OWN workspace — the same value the roster returns — never a member of this one.","name":"user_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminExternalCollaboratorRevokeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/api-keys":{"get":{"operationId":"list_api_keys","tags":["Admin"],"description":"List all API keys in the workspace. Optionally filter by user. Requires admin role.","x-cli":{"command":"admin api-keys list","output":{"columns":["id","name","user_id","expires_at","last_used_at"]}},"parameters":[{"schema":{"type":"string","description":"Filter to keys owned by a specific user."},"required":false,"description":"Filter to keys owned by a specific user.","name":"user_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminApiKeysListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_api_key","tags":["Admin"],"description":"Create an API key for a user with optional scopes and expiration. Returns the full key once — save it immediately. Requires admin role.","x-cli":{"command":"admin api-keys create","output":{"successMessage":"API key created — save the key now, it will not be shown again"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminApiKeyCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminApiKeyWithSecretResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/api-keys/{id}/rotate":{"post":{"operationId":"rotate_api_key","tags":["Admin"],"description":"Rotate an API key. Issues a new key and keeps the old one valid for 24 hours. Requires admin role. Returns the new key — save it immediately.","x-tool":{"expose":["assistant"],"annotations":{"destructive":true}},"x-cli":{"command":"admin api-keys rotate","confirm":true,"output":{"successMessage":"API key rotated — save the new key now"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminApiKeyWithSecretResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/api-keys/{id}":{"patch":{"operationId":"update_api_key","tags":["Admin"],"description":"Update an API key's name, scopes, or rate limit. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin api-keys update","output":{"successMessage":"API key {id} updated"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminApiKeyUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminApiKeyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"revoke_api_key","tags":["Admin"],"description":"Revoke an API key. Immediate — any requests using the key will fail. Requires admin role.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin api-keys revoke","confirm":true,"output":{"successMessage":"API key {id} revoked"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/billing":{"get":{"operationId":"admin_billing_get","tags":["Admin"],"description":"Consolidated billing overview. Returns current plan, subscription details, seat usage, recent invoices, and the unified action-meter view (per-seat caps, auto-recharge config, base/earned/topup quota, consumed-this-month, member count + cap, trial state, active bonuses).","x-cli":{"command":"admin billing get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminBillingOverviewResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/billing/upgrade-plan":{"post":{"operationId":"admin_billing_upgrade_plan","tags":["Admin"],"description":"Upgrade the workspace to a Pro plan or switch between monthly / annual. Free→Pro returns `{ mode: \"checkout\", url }` for Stripe redirect. Existing-Pro switches return `{ mode: \"switched\", subscription }` after an in-place `subscriptions.update` with prorated billing (Stripe handles the credit/debit for the half-period delta automatically).","x-cli":{"hidden":true,"command":"admin billing upgrade"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"$ref":"#/components/schemas/PlanLookupKey"},"success_url":{"type":"string","format":"uri"},"cancel_url":{"type":"string","format":"uri"}},"required":["plan"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PlanUpgradeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/billing/cancel":{"post":{"operationId":"admin_billing_cancel","tags":["Admin"],"description":"Cancel the workspace's active Pro subscription. Defaults to end-of-period cancellation (`at_period_end: true`) so the workspace keeps access through the current period. For annual mid-year cancellations, the `customer.subscription.deleted` webhook handler schedules a prorated refund via Stripe credit-note. Top-up balance is preserved (non-refundable per spec).","x-cli":{"hidden":true,"command":"admin billing cancel"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"at_period_end":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PlanCancelResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/referrals":{"get":{"operationId":"admin_referrals_get","tags":["Admin"],"description":"Return the referral dashboard payload — Your invites (friend / coworker / share_friend invites the caller has sent), Active bonuses (perpetual ladder bonuses currently in effect), and the caller's primary share link with conversion counts. Used by the admin referrals page.","x-cli":{"hidden":true,"command":"admin referrals"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ReferralDashboardData"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/usage":{"get":{"operationId":"get_usage_stats","tags":["Admin"],"description":"Get workspace usage statistics including storage breakdown by user and module, active user count, API call volume, and per-module adoption metrics. Requires admin or owner role. Use this when the user asks about workspace usage, storage consumption, billing metrics, or capacity planning.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin usage get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UsageStatsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/usage/timeseries":{"get":{"operationId":"admin_usage_timeseries","tags":["Admin"],"description":"Daily creation counts (last 14 days, split into \"last 7\" + \"prior 7\" windows) for the four hero metrics on the Overview tab. Powers row 13.16 sparkline cards. Returns `{users, documents, messages, emails}` each with `{buckets[7], total, previous_total}` so the UI can draw a sparkline + render a 7...","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin usage timeseries"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UsageTimeSeriesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/usage/export":{"get":{"operationId":"admin_usage_export","tags":["Admin"],"description":"Export usage stats as CSV","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin usage export","output":{"format":"raw"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminBinaryBody"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains":{"get":{"operationId":"list_domains","tags":["Admin"],"description":"List workspace email domains (default + custom). Requires admin role.","x-cli":{"command":"admin domains list","output":{"columns":["id","domain","domain_type","verified"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains/register":{"post":{"operationId":"admin_domain_register","tags":["Admin"],"description":"Register workspace's default domain with SES","x-cli":{"command":"admin domains register","hidden":true,"output":{"successMessage":"Default domain registered"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainRegisterInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains/custom":{"post":{"operationId":"register_custom_domain","tags":["Admin"],"description":"Register a custom email domain (e.g., pokermethod.com). Creates a pending domain row; ownership must be verified via DNS TXT before sending is enabled. Requires admin role.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"admin domains add-custom","output":{"successMessage":"Custom domain registered — verify DNS to activate"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainCustomInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains/{id}/verify":{"post":{"operationId":"verify_domain","tags":["Admin"],"description":"Trigger DNS verification for a workspace domain. Requires admin role.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"admin domains verify","output":{"successMessage":"Domain verification triggered"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains/{id}/verify-ownership":{"post":{"operationId":"verify_domain_ownership","tags":["Admin"],"description":"Verify custom domain ownership via DNS TXT record. On success, auto-registers with SES to retrieve DKIM/SPF records. Requires admin role.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"admin domains verify-ownership","output":{"successMessage":"Domain ownership verified"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains/{id}/register-ses":{"post":{"operationId":"admin_domain_register_ses","tags":["Admin"],"description":"stub (SES registration happens on domain add) Frontend still calls this route during the transition period — return the domain directly.","x-cli":{"command":"admin domains register-ses","hidden":true},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains/{id}/refresh":{"post":{"operationId":"refresh_domain","tags":["Admin"],"description":"Refresh a domain's verification status from SES. Requires admin role.","x-cli":{"command":"admin domains refresh","output":{"successMessage":"Domain {id} verification refreshed"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains/{id}/set-default":{"post":{"operationId":"set_default_domain","tags":["Admin"],"description":"Set a verified custom domain as the workspace default. Requires admin role.","x-cli":{"command":"admin domains set-default","output":{"successMessage":"Domain {id} set as default"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains/{id}/deletion-impact":{"get":{"operationId":"get_domain_deletion_impact","tags":["Admin"],"description":"Preview addresses that stop working when a custom domain is deleted. Requires admin role.","x-cli":{"command":"admin domains deletion-impact"},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainDeletionImpactResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/domains/{id}":{"get":{"operationId":"get_domain","tags":["Admin"],"description":"Get a workspace domain by ID. Requires admin role.","x-cli":{"command":"admin domains get"},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_domain","tags":["Admin"],"description":"Delete a workspace domain. Requires admin role.","x-cli":{"command":"admin domains delete","confirm":true,"output":{"successMessage":"Domain {id} deleted"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/test-notification-email":{"post":{"operationId":"send_test_notification_email","tags":["Admin"],"description":"Send a test notification email (useful for checking email rendering and deliverability). Requires admin role.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true}},"x-cli":{"command":"admin test-notification-email send","output":{"format":"none","successMessage":"Test notification email sent"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestNotificationEmailInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminTestEmailSendResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/test-notification-email/preview":{"get":{"operationId":"list_notification_previews","tags":["Admin"],"description":"List available notification email templates (event type + subject). Requires admin role.","x-tool":{"expose":[]},"x-cli":{"command":"admin test-notification-email previews","output":{"format":"table","columns":["event_type","subject"]}},"parameters":[{"schema":{"type":"string","description":"Event type to preview as HTML. When omitted, returns the JSON list of templates."},"required":false,"description":"Event type to preview as HTML. When omitted, returns the JSON list of templates.","name":"type","in":"query"},{"schema":{"type":"string","description":"Pass 'json' to return {subject, html, text} instead of rendered HTML."},"required":false,"description":"Pass 'json' to return {subject, html, text} instead of rendered HTML.","name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AdminTestEmailPreviewResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/mail-suppressions":{"get":{"operationId":"admin_mail_suppressions_list","tags":["Admin"],"description":"list suppressed addresses","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin mail-suppressions list","output":{"columns":["id","email","reason","created_at"]}},"parameters":[{"schema":{"type":"string","enum":["bounce","complaint"],"description":"Filter by suppression type."},"required":false,"description":"Filter by suppression type.","name":"type","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"description":"Page size (default 50, max 500)."},"required":false,"description":"Page size (default 50, max 500).","name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Offset for pagination (must be ≥ 0)."},"required":false,"description":"Offset for pagination (must be ≥ 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuppressionsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"admin_mail_suppression_create","tags":["Admin"],"description":"manually add a suppression","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin mail-suppressions create","output":{"successMessage":"Suppression added"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailSuppressionCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MailSuppressionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/mail-suppressions/{id}":{"delete":{"operationId":"admin_mail_suppression_delete","tags":["Admin"],"description":"remove a suppression","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin mail-suppressions delete","confirm":true,"output":{"successMessage":"Suppression {id} removed"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/integrations":{"get":{"operationId":"admin_integrations_list","tags":["Admin"],"description":"list all integrations for workspace","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin integrations list","output":{"columns":["id","provider","status"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/IntegrationsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/integrations/slack/channels":{"get":{"operationId":"admin_integrations_slack_channels","tags":["Admin"],"description":"list Slack channels via bot token","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"command":"admin integrations slack-channels","output":{"columns":["id","name"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SlackChannelsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/integrations/{id}":{"patch":{"operationId":"admin_integration_update","tags":["Admin"],"description":"update integration config","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin integrations update","output":{"successMessage":"Integration {id} updated"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/IntegrationResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"admin_integration_delete","tags":["Admin"],"description":"disconnect an integration","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"admin integrations delete","confirm":true,"output":{"successMessage":"Integration {id} disconnected"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Resource ID."},"required":true,"description":"Resource ID.","name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/chat/purge-deleted-messages":{"post":{"summary":"Purge soft-deleted chat messages older than TTL","operationId":"post_api_admin_chat_purge_deleted_messages","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ttl_days":{"type":"integer","minimum":1,"maximum":365,"default":30}}}}}},"responses":{"200":{"description":"Purge completed","content":{"application/json":{"schema":{"type":"object","properties":{"purged_count":{"type":"number"},"ttl_days":{"type":"number"}},"required":["purged_count","ttl_days"]}}}}}}},"/api/admin/workspace/integrations":{"get":{"operationId":"admin_workspace_integrations_list","tags":["Admin"],"description":"List workspace third-party integration credentials (Turnstile, Stripe, Google OAuth). Secret keys are never returned.","responses":{"200":{"description":"List of saved integrations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceIntegrationsListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"admin_workspace_integrations_upsert","tags":["Admin"],"description":"Save (insert or update) a workspace third-party integration credential. Secret is encrypted at rest.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceIntegrationUpsertInput"}}}},"responses":{"200":{"description":"Integration saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceIntegrationSummary"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/workspace/integrations/{provider}":{"delete":{"operationId":"admin_workspace_integrations_delete","tags":["Admin"],"description":"Disconnect a workspace third-party integration. Removes the stored credential row.","parameters":[{"schema":{"type":"string","enum":["turnstile","stripe","google"]},"required":true,"name":"provider","in":"path"}],"responses":{"204":{"description":"Integration removed"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Integration not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/admin/workspace/registrar":{"get":{"operationId":"admin_workspace_registrar_list","tags":["Admin"],"description":"List workspace registrar connections. Tokens are never returned.","responses":{"200":{"description":"Registrar connections","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistrarConnectionListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"admin_workspace_registrar_connect","tags":["Admin"],"description":"Connect a registrar by storing an encrypted API token. Token is never returned.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistrarConnectInput"}}}},"responses":{"200":{"description":"Registrar connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistrarConnectionSummary"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/workspace/registrar/auto-configure":{"post":{"operationId":"admin_workspace_registrar_auto_configure","tags":["Admin"],"description":"Auto-configure DNS records for a custom domain via the connected registrar. Writes the domain's dnsRecords into the matching registrar zone, then verifies.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistrarAutoConfigureInput"}}}},"responses":{"200":{"description":"DNS records written and domain verification triggered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistrarAutoConfigureResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Domain or registrar connection not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Registrar API error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}}}}},"/api/admin/workspace/registrar/{provider}":{"delete":{"operationId":"admin_workspace_registrar_disconnect","tags":["Admin"],"description":"Disconnect a registrar connection. Removes the stored credential.","parameters":[{"schema":{"type":"string","enum":["cloudflare"]},"required":true,"name":"provider","in":"path"}],"responses":{"204":{"description":"Registrar disconnected"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Connection not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/account/referrals":{"get":{"operationId":"get_account_referrals","tags":["Account"],"description":"Referral dashboard for the caller's account: slug, share URL, invite roster, active perpetual bonuses, and share links.","x-cli":{"command":"account referrals","output":{"format":"object"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AccountReferralsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/account/data-export":{"get":{"operationId":"get_account_data_export","tags":["Account"],"description":"Export all personal data for the authenticated user in the active workspace (Right of Access / GDPR Art. 15). Default format is JSON. With `?format=portable`, returns data in standard interchange formats: docs as Markdown, sheets as CSV, contacts as vCard, events as ICS.","x-cli":{"command":"account data-export","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","enum":["json","portable"],"default":"json"},"required":false,"name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DataExportResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/account/rotate-referral-slug":{"post":{"operationId":"post_account_rotate_referral_slug","tags":["Account"],"description":"Rotate the caller's `?ref=:slug` referral identifier. Mints a fresh slug, abandons the old one. Past attributions remain intact; new clicks on the old slug stop resolving. Rate-limited to 3 rotations per 24 hours per account.","x-cli":{"command":"account rotate-referral-slug"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RotateReferralSlugResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/gdpr/export/{id}":{"get":{"operationId":"gdpr_export_personal_data","tags":["GDPR"],"description":"Machine-readable export (GDPR Art.20 portability / Art.15 access) of the personal data the workspace holds about one data subject, keyed by store name. Readable by the subject themselves or a workspace admin; any other caller receives 404 (existence-masked, ENGINEERING P11).","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Structured export keyed by store name.","content":{"application/json":{"schema":{"type":"object","properties":{"exported_at":{"type":"string"},"subject_id":{"type":"string"},"data":{"type":"object","additionalProperties":{"type":"array","items":{}}}},"required":["exported_at","subject_id","data"]}}}},"401":{"description":"Unauthenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Subject not found in the caller's workspace, or the caller is not authorized.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/workspace":{"get":{"operationId":"get_current_workspace","tags":["Workspaces"],"description":"Get the active workspace (name, slug, logo). Accessible to any authenticated user.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"workspace get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ActiveWorkspaceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"active_workspace_update","tags":["Workspaces"],"description":"Rename the active workspace and/or update its logo. Admin role required (`AdminService.requireAdmin`). The name change is gated by a customization guard — if the workspace already has a non-default name, the caller must pass `force: true` to overwrite (returns 409 otherwise).","x-cli":{"command":"workspace update","output":{"successMessage":"Workspace updated: {slug}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"New workspace display name. Trimmed server-side; must be a non-empty string. To overwrite an already-customized name, also pass `force: true`."},"logo_url":{"type":["string","null"],"description":"Workspace logo URL. Pass null to clear. Stored as `workspace_settings.workspace_logo_url`."},"force":{"type":"boolean","description":"Override the customized-name guard. Required to change the name when the current name is not in the default list (`Default`, `Default Workspace`, `Ambiguous`)."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ActiveWorkspaceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWorkspaceConflictResponse"}}}}}}},"/api/workspaces/check-slug":{"get":{"operationId":"check_workspace_slug","tags":["Workspaces"],"description":"Check whether a workspace slug is available.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"workspaces check-slug"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"slug","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckSlugResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckSlugUnavailableResponse"}}}}}}},"/api/workspaces":{"get":{"operationId":"list_my_workspaces","tags":["Workspaces"],"description":"List workspaces the current user belongs to (human users may have multiple). Returns workspace id, name, slug, role, and which one is active.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"workspaces list","output":{"columns":["slug","name","role","is_active"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkspaceListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"workspace_create","tags":["Workspaces"],"description":"Create a workspace. Two auth paths: (1) **registration_token** — new users coming from `/api/auth/register` or `/verify-email` pass the short-lived registration JWT in the body; the server creates the user + workspace atomically. (2) **JWT auth** — legacy human users without a workspace use a regular auth JWT; agents are rejected.","x-cli":{"command":"workspaces create","output":{"successMessage":"Workspace created: {workspace.slug}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkspaceBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CreateWorkspaceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/workspaces/{workspace_id}/restore":{"post":{"operationId":"restore_workspace","tags":["Workspaces"],"description":"Un-archive a workspace the caller administers. Called from another workspace's session — an archived workspace refuses authentication, so it cannot be restored from inside itself.","x-tool":{"expose":[]},"x-cli":{"command":"workspaces restore","output":{"successMessage":"Restored workspace: {workspace.slug}"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Workspace ID (UUID)."},"required":true,"description":"Workspace ID (UUID).","name":"workspace_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RestoreWorkspaceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/workspaces/{workspace_id}/switch":{"post":{"operationId":"switch_workspace","tags":["Workspaces"],"description":"Switch the caller's active workspace. Re-issues a JWT scoped to the new workspace.","x-tool":{"expose":[]},"x-cli":{"command":"workspaces switch","output":{"successMessage":"Active workspace: {workspace.slug}"}},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Workspace ID (UUID)."},"required":true,"description":"Workspace ID (UUID).","name":"workspace_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SwitchWorkspaceResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/webhooks/event-types":{"get":{"operationId":"webhooks_event_types","tags":["Webhooks"],"description":"List event types an agent can subscribe to. Includes the `*` wildcard.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"webhooks event-types","output":{"columns":["type","description"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEventTypesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/webhooks":{"get":{"operationId":"webhooks_list","tags":["Webhooks"],"description":"List webhook registrations owned by the caller.","x-tool":{"expose":[]},"x-cli":{"command":"webhooks list","output":{"columns":["id","url","events","active"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"webhooks_create","tags":["Webhooks"],"description":"Register a new webhook. Body shape matches `CreateWebhookInput` (url + events + optional description). Returns the webhook record plus the HMAC signing `secret` (one-time visibility — store it; subsequent reads omit `secret`).","x-tool":{"expose":[]},"x-cli":{"command":"webhooks create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookWithSecret"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/webhooks/{id}":{"get":{"operationId":"webhooks_get","tags":["Webhooks"],"description":"Get one webhook.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"webhooks get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"webhooks_update","tags":["Webhooks"],"description":"Update a webhook (url, events, description, active). Body shape matches `UpdateWebhookInput`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"webhooks update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"webhooks_delete","tags":["Webhooks"],"description":"Delete a webhook.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"webhooks delete"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/webhooks/{id}/rotate-secret":{"post":{"operationId":"webhooks_rotate_secret","tags":["Webhooks"],"description":"Rotate the HMAC signing secret. Returns the new secret (one-time visibility). The previous secret remains valid for a 24h grace period.","x-cli":{"hidden":true,"command":"webhooks rotate-secret"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RotateSecretResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/webhooks/{id}/revoke-previous-secret":{"post":{"operationId":"webhooks_revoke_previous_secret","tags":["Webhooks"],"description":"Immediately invalidate the previous secret (bypasses the 24h grace period). Use after updating the receiver.","x-cli":{"hidden":true,"command":"webhooks revoke-previous-secret"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RevokePreviousSecretResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/webhooks/{id}/deliveries":{"get":{"operationId":"webhooks_deliveries_list","tags":["Webhooks"],"description":"List recent delivery attempts (status, response, retries). Paginated via `?limit=` (default 25) and `?offset=` (default 0).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"webhooks deliveries"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":500,"description":"Page size (default 25, max 500)."},"required":false,"description":"Page size (default 25, max 500).","name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Offset for pagination (must be ≥ 0)."},"required":false,"description":"Offset for pagination (must be ≥ 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookDeliveryListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/webhooks/{id}/test":{"post":{"operationId":"webhooks_test","tags":["Webhooks"],"description":"Send a test ping payload to the webhook URL.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"hidden":true,"command":"webhooks test"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TestPingResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications":{"get":{"operationId":"notifications_list","tags":["Notifications"],"description":"List notifications for the current user. Supports cursor pagination via `?cursor=`; legacy offset pagination still works. Toggles: `unread_only`, `include_dismissed`, `include_snoozed`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"notifications list","output":{"columns":["id","type","createdAt","read"]}},"parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"unread_only","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"include_dismissed","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"include_snoozed","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NotificationListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications/mutes":{"get":{"operationId":"notifications_mutes_list","tags":["Notifications"],"description":"List active mute rules. Pass `?include_expired=true` to also see rules whose `until` has passed (these no longer suppress notifications).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"notifications mutes list"},"parameters":[{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"include_expired","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MutesListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications/mute":{"post":{"operationId":"notifications_mute_create","tags":["Notifications"],"description":"Create or refresh a mute rule. At least one of `resourceId` / `eventType` is required (DB CHECK). When a matching rule already exists, the existing row's `expiresAt` is refreshed.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"notifications mute"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"resourceType":{"type":["string","null"]},"resourceId":{"type":["string","null"]},"eventType":{"type":["string","null"]},"until":{"type":["string","null"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MuteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications/mutes/{id}":{"delete":{"operationId":"notifications_mute_delete","tags":["Notifications"],"description":"Remove a mute rule by id. Scoped to the owning user.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"notifications mute delete"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications/mark-all-read":{"post":{"operationId":"notifications_mark_all_read","tags":["Notifications"],"description":"Mark every unread notification as read.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"notifications mark-all-read"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications/{id}/mark-read":{"post":{"operationId":"notifications_mark_read","tags":["Notifications"],"description":"Mark a single notification read. Returns `was_unread` — true only if THIS call flipped it. A consumer that gets `false` skips the work, so two processes on one identity cannot both act on one notification.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"notifications mark-read"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MarkReadResult"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications/{id}/mark-unread":{"post":{"operationId":"notifications_mark_unread","tags":["Notifications"],"description":"Convenience alias for `PATCH /api/notifications/:id` with `{read:false}`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"notifications mark-unread"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications/{id}/dismiss":{"post":{"operationId":"notifications_dismiss","tags":["Notifications"],"description":"Soft-delete (hide from default feed). Preserved for audit / undismiss.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"notifications dismiss"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications/{id}/undismiss":{"post":{"operationId":"notifications_undismiss","tags":["Notifications"],"description":"Restore a dismissed notification.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"notifications undismiss"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/notifications/{id}/snooze":{"post":{"operationId":"notifications_snooze","tags":["Notifications"],"description":"Hide until `{until: ISO8601}`. Pass `{until: null}` to clear snooze.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"notifications snooze"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"until":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO 8601 timestamp, or null to clear snooze."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/images/generate":{"post":{"operationId":"generate_image","tags":["Images"],"description":"Generate an image using AI (Gemini Imagen 4.0). Returns a URL to the generated image. Use this when the user asks to generate, create, draw, or make an image, picture, illustration, diagram, logo, icon, or any visual content. Provide a detailed, descriptive prompt for best results. The generated image can be displayed inline in the chat or inserted into documents/slides.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"images generate"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","minLength":1,"description":"Natural-language description of the image to generate. Routed to Gemini's native image-gen model (default `gemini-3.1-flash-image-preview`, override via `GEMINI_IMAGE_MODEL`)."}},"required":["prompt"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/GenerateImageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/images/scan-business-card":{"post":{"operationId":"scan_business_card","tags":["Images"],"description":"OCR a photo of a business card and extract structured contact fields (name, title, company, email, phone, website, address, notes). Returns JSON with each field nullable when not present on the card. Use when the user uploads or references a business card image and wants to add the contact to CRM. The image must be passed as a base64 data URL (data:image/jpeg;base64,...) of an image format Gemini Vision supports (JPEG, PNG, WebP, HEIC). Max 6 MB.","x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"x-cli":{"hidden":true,"command":"images scan-business-card"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"image":{"type":"string","pattern":"^data:image\\/[^;]+;base64,","description":"Base64-encoded image as a `data:` URL (`data:image/png;base64,...`). Capped at ~6MB of raw image data to protect the upstream OCR call."}},"required":["image"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ScanBusinessCardResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/audio/transcribe":{"post":{"operationId":"audio_transcribe","tags":["Audio"],"description":"Transcribe an audio recording to text via OpenAI Whisper. Accepts a `multipart/form-data` body with an `audio` file field (mp3, mp4, mpeg, mpga, m4a, wav, webm; max 25 MB) plus optional `language` and `prompt` text fields. Returns the cleaned transcript, duration in seconds, and detected language. Use when the user records voice input (`Cmd+Shift+V` voice dictation, mobile microphone, meeting capture) and wants the spoken text turned into a transcript that can be edited, summarized, or assigned as a task. Per-minute vendor cost: 3 actions per `ceil(duration_seconds / 60)` minutes (Whisper). Direct-UI callers and external coworkers pay vendor cost only; SPEAR pays vendor cost + 1 LLM cost per call.","x-cli":{"hidden":true,"command":"audio transcribe"},"x-tool":{"expose":["assistant","mcp"],"annotations":{"openWorld":true}},"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/TranscribeAudioInput"}}}},"responses":{"200":{"description":"Transcribed audio","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranscribeAudioResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Audio rejected — exceeds 25 MB file size cap OR exceeds the configured per-recording duration cap (`MONETIZATION_AUDIO_MAX_MINUTES`, default 15 minutes). Duration-cap responses use `error: \"AUDIO_DURATION_EXCEEDED\"` and include `max_minutes`, `gate`, and (post-Whisper case) `duration_minutes`. Burns zero actions per BUILD_PLAN §7 / Rock 7 Item 3.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"No speech detected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"Upstream Whisper failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Transcription not configured (missing OPENAI_API_KEY)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/unread-counts":{"get":{"operationId":"get_unread_counts","tags":["Unread"],"description":"Get the full unread projection (mail inbox, per-channel chat badges with mute/preference resolved, notifications, total). Used for cold-connect / reconnect hydration; live updates arrive on the mux `unread` channel.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"unread counts"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UnreadCountsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/widget/summary":{"get":{"operationId":"get_widget_summary","tags":["Widget"],"description":"Compact single-payload summary for a native home-screen widget: the signed-in user's tasks due today, unread mail/chat counts, and next few calendar events. `tz_offset_minutes` anchors the day window to the device's local time.","parameters":[{"schema":{"type":"string"},"required":false,"name":"tz_offset_minutes","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WidgetSummaryResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/push/subscribe":{"post":{"operationId":"push_subscribe","tags":["Push"],"description":"Register or refresh a browser Web Push subscription for the current user. Upsert on `(user_id, endpoint)` — re-subscribing from the same browser refreshes the keys and `last_seen_at`. Rate-limited to 10 requests/min per user.","x-tool":{"expose":[]},"x-cli":{"hidden":true,"command":"push subscribe"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"type":"string","format":"uri","description":"Push service endpoint URL returned by `PushSubscription.endpoint`."},"keys":{"type":"object","properties":{"p256dh":{"type":"string","description":"Base64url-encoded P-256 ECDH public key from `PushSubscription.getKey('p256dh')`."},"auth":{"type":"string","description":"Base64url-encoded authentication secret from `PushSubscription.getKey('auth')`."}},"required":["p256dh","auth"],"additionalProperties":false,"description":"Keys required to encrypt push payloads (RFC 8291)."},"user_agent":{"type":"string","description":"Optional UA string captured at subscribe time, surfaced in settings so users can identify which device a subscription belongs to."}},"required":["endpoint","keys"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PushSubscribeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"push_unsubscribe","tags":["Push"],"description":"Remove a Web Push subscription by endpoint. Scoped to the caller's userId — only the owning user can remove a subscription. Idempotent: deleting a non-existent endpoint returns 200.","x-tool":{"expose":[]},"x-cli":{"hidden":true,"command":"push unsubscribe"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"type":"string","format":"uri","description":"Push endpoint URL of the subscription to remove. Scoped to the caller's userId at the ORM layer."}},"required":["endpoint"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PushUnsubscribeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/push/vapid-key":{"get":{"operationId":"push_vapid_key","tags":["Push"],"description":"Fetch the workspace's VAPID public key for `PushManager.subscribe({applicationServerKey})`. Returns 503 (outside the contract error-code enum) with `{error: \"Web push is not configured\"}` when `VAPID_PUBLIC_KEY` is unset.","x-tool":{"expose":[]},"x-cli":{"hidden":true,"command":"push vapid-key"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PushVapidKeyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/chat-sidebar/sections":{"get":{"operationId":"chat_sidebar_list_sections","tags":["Chat"],"description":"The caller's custom chat-sidebar sections, ordered by position.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"chat sections list","output":{"format":"table"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSidebarSectionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"chat_sidebar_create_section","tags":["Chat"],"description":"Create a custom chat-sidebar section for the caller.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"chat sections create","output":{"format":"raw"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSidebarCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSidebarSection"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/chat-sidebar/sections/reorder":{"patch":{"operationId":"chat_sidebar_reorder_sections","tags":["Chat"],"description":"Reorder the caller's chat-sidebar sections.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"chat sections reorder","output":{"format":"table"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSidebarReorderInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSidebarSectionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/chat-sidebar/sections/{id}":{"patch":{"operationId":"chat_sidebar_update_section","tags":["Chat"],"description":"Rename a chat-sidebar section or set its channels.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"chat sections update","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSidebarUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSidebarSection"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"chat_sidebar_delete_section","tags":["Chat"],"description":"Delete a chat-sidebar section owned by the caller.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"chat sections delete","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatSidebarDeleteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/chat-drafts":{"get":{"operationId":"chat_drafts_list","tags":["Chat"],"description":"The caller's chat drafts (inflight + saved), newest first.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"chat drafts list","output":{"format":"table"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatDraftListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"chat_draft_upsert_inflight","tags":["Chat"],"description":"Upsert the caller's inflight draft for a channel/thread. Blank content clears it (returns { deleted: true }).","x-cli":{"command":"chat drafts upsert","output":{"format":"raw"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDraftUpsertInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDraftUpsertResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"chat_draft_create_saved","tags":["Chat"],"description":"Create a saved (named) draft for the caller.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"chat drafts create","output":{"format":"raw"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDraftCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatDraft"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/chat-drafts/{id}":{"patch":{"operationId":"chat_draft_update","tags":["Chat"],"description":"Update a saved draft owned by the caller.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"chat drafts update","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDraftUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChatDraft"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"chat_draft_delete","tags":["Chat"],"description":"Delete a draft owned by the caller.","x-tool":{"expose":["mcp"]},"x-cli":{"command":"chat drafts delete","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/presence/heartbeat":{"post":{"operationId":"presence_heartbeat","tags":["Presence"],"description":"Legacy liveness ack (D245) — presence-neutral by design and kept only for back-compat. A blind periodic heartbeat must NEVER mark the caller present: it does not advance activity and does not touch reachability. Declared activity flows only through the input-gated beacon (POST /api/presence/activity); reachability is the live /ws/mux socket. Returns { ok: true } with no presence effect.","x-cli":{"command":"presence heartbeat","output":{"format":"object"}},"responses":{"200":{"description":"Acknowledged (no presence effect)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresenceHeartbeatResponse"}}}}}}},"/api/presence/activity":{"post":{"operationId":"presence_activity_beacon","tags":["Presence"],"description":"Declare that the calling principal is actively engaged. The web/CLI beacon and login fire this; ambient API traffic does not. Writes the principal's activity timestamp consumed by the presence resolver.","x-cli":{"command":"presence activity","output":{"format":"object"}},"responses":{"200":{"description":"Activity recorded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresenceHeartbeatResponse"}}}}}}},"/api/presence":{"get":{"operationId":"get_user_presence","tags":["Presence"],"description":"Get online status (true = online within the last 5 minutes) for a set of users in the current workspace. Returns user_id → boolean. Capped at 100 user IDs. Fallback/cold-hydrate surface only — the primary presence path is the full-state push over the `presence` /ws/mux channel (D245); poll this on connect or when the socket is down, not on a steady timer.","x-cli":{"command":"presence status","output":{"format":"object"}},"x-tool":{"expose":["assistant","mcp"]},"parameters":[{"schema":{"type":"string","description":"Comma-separated user IDs (capped at 100 per request)."},"required":true,"description":"Comma-separated user IDs (capped at 100 per request).","name":"user_ids","in":"query"}],"responses":{"200":{"description":"Status map keyed by user ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresenceStatusResponse"}}}},"400":{"description":"Missing user_ids query parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/presence/detailed":{"get":{"operationId":"get_detailed_user_presence","tags":["Presence"],"description":"Get detailed presence for a set of users — online (≤5min), idle (5–30min), or offline — plus the lastActiveAt timestamp. Capped at 100 user IDs. Fallback/cold-hydrate surface only — the primary presence path is the full-state push over the `presence` /ws/mux channel (D245); poll this on connect or when the socket is down, not on a steady timer.","x-cli":{"command":"presence detailed","output":{"format":"object"}},"x-tool":{"expose":["assistant","mcp"]},"parameters":[{"schema":{"type":"string","description":"Comma-separated user IDs (capped at 100 per request)."},"required":true,"description":"Comma-separated user IDs (capped at 100 per request).","name":"user_ids","in":"query"}],"responses":{"200":{"description":"Detailed presence map","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresenceDetailedResponse"}}}},"400":{"description":"Missing user_ids query parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/presence/resolved":{"get":{"operationId":"get_resolved_presence","tags":["Presence"],"description":"Cold-hydrate the resolved presence dot (D245) for a set of users in the current workspace. Returns user_id → { kind, state } — the same already-resolved dot the projector pushes over the `presence` WebSocket channel. Used on connect and as the WS-down fallback; the client renders the state and computes nothing. Capped at 100 user IDs.","x-cli":{"command":"presence resolved","output":{"format":"object"}},"x-tool":{"expose":["assistant","mcp"]},"parameters":[{"schema":{"type":"string","description":"Comma-separated user IDs (capped at 100 per request)."},"required":true,"description":"Comma-separated user IDs (capped at 100 per request).","name":"user_ids","in":"query"}],"responses":{"200":{"description":"Resolved presence map","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresenceResolvedResponse"}}}},"400":{"description":"Missing user_ids query parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/assistant/capabilities":{"get":{"operationId":"assistant_capabilities","tags":["Assistant"],"description":"Returns the active LLM model identifier so the client can render the workspace + model scope indicator in the assistant header.","x-cli":{"hidden":true,"command":"assistant capabilities"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantCapabilities"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/assistant/recent-activity":{"get":{"operationId":"assistant_recent_activity","tags":["Assistant"],"description":"Returns the current user's last N assistant-initiated actions for the empty-state 'Since you last opened me' section. User- + workspace-scoped; falls through to an empty list when the workspace can't be resolved (e.g. registration token) so the UI never errors.","x-cli":{"hidden":true,"command":"assistant recent-activity"},"parameters":[{"schema":{"type":"string","description":"Number of entries to return (default 5, capped at 25)."},"required":false,"description":"Number of entries to return (default 5, capped at 25).","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantRecentActivityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/assistant/chat":{"post":{"operationId":"assistant_chat","tags":["Assistant"],"description":"Synchronous SPEAR chat turn. Request body matches the `AssistantChatRequest` schema (see Schemas section): `message` is required; `context` and `history` are optional with safe defaults (`{}` and `[]`) — the minimum valid payload is `{\"message\": \"...\"}`. Type/required validation lives in `validateChatRequest` (services/assistant.ts) so existing AssistantError messages stay byte-identical; the wired `ChatRequestBody` adds only unknown-key rejection. Returns the resolved assistant response + tool-call trace.","x-tool":{"expose":["all"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"hidden":true,"command":"assistant chat"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantChatRequestBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantChatResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/assistant/chat/stream":{"post":{"operationId":"assistant_chat_stream","tags":["Assistant"],"description":"Same input as `/api/assistant/chat` but streams Server-Sent Events. Event names: `delta`, `tool_start`, `tool_end`, `done`, `error`. Type/required validation stays in `validateChatRequest`; the wired `ChatRequestBody` adds only unknown-key rejection.","x-cli":{"hidden":true,"command":"assistant chat stream"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantChatRequestBody"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/assistant/turns/{id}/replay":{"get":{"operationId":"assistant_replay","tags":["Assistant"],"description":"Replay the persisted SSE event chain for an in-flight or completed assistant turn, then tail new events as they're written. Tenant-scoped — turns from other workspaces yield an empty stream. Closes after a terminal `done` or `error` row, after the client disconnects, or after a hard duration cap (3 minutes).","x-cli":{"hidden":true,"command":"assistant turn replay"},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Turn id minted server-side at turn-start and emitted as the `turn_started` SSE event of the originating chat-stream call. Replay is workspace-scoped — querying a turn from a different workspace yields an empty stream."},"required":true,"description":"Turn id minted server-side at turn-start and emitted as the `turn_started` SSE event of the originating chat-stream call. Replay is workspace-scoped — querying a turn from a different workspace yields an empty stream.","name":"id","in":"path"}],"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/assistant/conversations/migrate":{"post":{"operationId":"assistant_migrate_conversations","tags":["Assistant"],"description":"Bulk upload conversations from localStorage. Idempotent — returns 0 if the user already has server-side conversations. Max 50 conversations × 100 messages each.","x-cli":{"hidden":true,"command":"assistant conversations migrate"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantMigrateConversationsBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantMigrateConversationsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/assistant/conversations":{"get":{"operationId":"assistant_list_conversations","tags":["Assistant"],"description":"List the current user's assistant conversations, newest first. Cursor-paginated by `updated_at`.","x-cli":{"hidden":true,"command":"assistant conversations list"},"parameters":[{"schema":{"type":"string","description":"Cursor for pagination (ISO timestamp from previous page's last item)."},"required":false,"description":"Cursor for pagination (ISO timestamp from previous page's last item).","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Number of conversations to return (default 50, max 100)."},"required":false,"description":"Number of conversations to return (default 50, max 100).","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantListConversationsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"assistant_create_conversation","tags":["Assistant"],"description":"Create a new conversation. Auto-prunes oldest unpinned conversations when the user exceeds 200.","x-cli":{"hidden":true,"command":"assistant conversations create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantCreateConversationBody"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantConversation"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/assistant/conversations/{id}":{"get":{"operationId":"assistant_get_conversation","tags":["Assistant"],"description":"Get a single conversation with all its messages. User-scoped — returns 404 for other users' conversations.","x-cli":{"hidden":true,"command":"assistant conversations get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantConversationWithMessages"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"assistant_update_conversation","tags":["Assistant"],"description":"Update a conversation's title, pinned state, or last-seen message count.","x-cli":{"hidden":true,"command":"assistant conversations update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantUpdateConversationBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantConversation"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"assistant_delete_conversation","tags":["Assistant"],"description":"Delete a conversation and all its messages. User-scoped.","x-cli":{"hidden":true,"command":"assistant conversations delete"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/assistant/conversations/{id}/share":{"post":{"operationId":"assistant_share_conversation","tags":["Assistant"],"description":"Mint a stateless public read-only share link for a conversation. Owner-scoped — returns 404 for other users' conversations. The token binds the conversation + workspace and is verified anonymously at GET /api/public/assistant/conversations/{id}?token=…","x-cli":{"hidden":true,"command":"assistant conversations share"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantShareConversationResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/billing/webhook":{"post":{"operationId":"billing_webhook_receive","summary":"Receive a Stripe webhook event","description":"Public endpoint that receives and processes Stripe webhook events. No Bearer auth required — signature is verified via stripe.webhooks.constructEvent() using STRIPE_WEBHOOK_SECRET.","tags":["Billing"],"security":[],"parameters":[{"schema":{"type":"string","description":"Stripe webhook signature header"},"required":true,"description":"Stripe webhook signature header","name":"stripe-signature","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":{},"description":"Raw Stripe event payload"}}}},"responses":{"200":{"description":"Event received and processed (or duplicate — idempotent)","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean","enum":[true]},"id":{"type":"string","description":"Stripe event ID"}},"required":["received","id"]}}}},"400":{"description":"Missing or invalid stripe-signature header","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/billing/checkout":{"post":{"operationId":"billing_checkout","tags":["Billing"],"description":"Create a Stripe Checkout Session for upgrading to a paid plan. Returns the URL the client should redirect to.","x-tool":{"expose":[]},"x-cli":{"hidden":true,"command":"billing checkout"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","enum":["pro"]},"interval":{"type":"string","enum":["monthly","annual"],"default":"monthly"},"success_url":{"type":"string","format":"uri"},"cancel_url":{"type":"string","format":"uri"}},"required":["plan"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CheckoutResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/portal":{"post":{"operationId":"billing_portal","tags":["Billing"],"description":"Create a Stripe Customer Portal session. Lets owners manage subscriptions, payment methods, and invoices in Stripe's hosted UI.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing portal"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"return_url":{"type":"string","format":"uri"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PortalResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/cancel":{"post":{"operationId":"billing_cancel","tags":["Billing"],"description":"Cancel the workspace subscription (downgrade to Free). Default: end-of-period cancellation — workspace retains access until the current billing period ends. Pass `at_period_end: false` for immediate cancellation (admin emergency only).","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing cancel"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"at_period_end":{"type":"boolean","default":true}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CancelSubscriptionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/subscription":{"get":{"operationId":"get_billing_subscription","tags":["Billing"],"description":"Get the current workspace subscription (plan tier, status, trial info, renewal date). Admin only.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"billing subscription"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SubscriptionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/plans":{"get":{"operationId":"list_billing_plans","tags":["Billing"],"description":"List available billing plans with tier, name, description.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing plans"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PlansListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/seats":{"get":{"operationId":"get_billing_seats","tags":["Billing"],"description":"Get seat usage for the workspace (current seats, Stripe subscription quantity, breakdown by role). Admin only.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing seats"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SeatsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/seats/sync":{"post":{"operationId":"sync_billing_seats","tags":["Billing"],"description":"Syncs the workspace seat count to Stripe for the workspace bound to your API key. No input arguments — workspace scope is derived from auth context. Admin only.","x-cli":{"hidden":true,"command":"billing seats sync"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SeatsSyncResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/usage":{"get":{"operationId":"get_billing_usage","tags":["Billing"],"description":"Get current workspace usage (users/agents/documents/storage/AI actions) vs. plan limits. Admin only.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing usage"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/UsageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/ai-usage":{"get":{"operationId":"get_billing_ai_usage","tags":["Billing"],"description":"Get AI token usage for the current billing period (used, limit, percent, resets at). Admin only.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing ai-usage"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AiUsageResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/features":{"get":{"operationId":"get_billing_features","tags":["Billing"],"description":"Get the workspace's plan tier and feature-flag map. Plans gate volume, not features — every feature is available on every plan, so the map is always empty. Admin only.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing features"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FeaturesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/invoices":{"get":{"operationId":"list_billing_invoices","tags":["Billing"],"description":"List invoices from Stripe (paginated via starting_after cursor). Admin only.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing invoices"},"parameters":[{"schema":{"type":"string","description":"Page size 1-100; defaults to 10."},"required":false,"description":"Page size 1-100; defaults to 10.","name":"limit","in":"query"},{"schema":{"type":"string","description":"Stripe cursor for the next page (Stripe invoice id)."},"required":false,"description":"Stripe cursor for the next page (Stripe invoice id).","name":"starting_after","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/InvoicesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/discount":{"get":{"operationId":"get_billing_discount","tags":["Billing"],"description":"Get the active discount on the workspace subscription. Admin only.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing discount"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DiscountResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"remove_billing_discount","tags":["Billing"],"description":"Remove the active discount from the workspace subscription. Admin only.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing remove-discount"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RemoveDiscountResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/promotion-code":{"post":{"operationId":"apply_promotion_code","tags":["Billing"],"description":"Apply a promotion code to the active subscription. Codes can also be entered during Stripe Checkout via `allow_promotion_codes`.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing apply-promotion"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":64}},"required":["code"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DiscountResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/quota":{"get":{"operationId":"get_billing_quota","tags":["Billing"],"description":"Return the workspace's unified action-meter view: plan, base/earned/topup quota, consumed-this-month, reset_at, member count + cap, trial state, active bonuses, auto-recharge config. Replaces the deprecated /api/billing/usage + /api/billing/ai-usage endpoints. Any authenticated caller in the workspace.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing quota"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkspaceBillingView"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/bonuses":{"get":{"operationId":"get_billing_bonuses","tags":["Billing"],"description":"Return the workspace's full earned-bonus history, newest-first — perpetual activation bonuses merged with one-time activation grants. Powers the Home Action-bonuses card, which needs the whole history the notification feed cannot show. Any authenticated caller in the workspace.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing bonuses"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EarnedBonusesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/topup":{"post":{"operationId":"billing_topup_create","tags":["Billing"],"description":"Create a Stripe Checkout session for a top-up pack (small/medium/large = 500/2,500/10,000 actions for $5/$20/$50). Returns the hosted Stripe Checkout URL the client redirects to. The actual credit to `top_up_purchases` happens in the `charge.succeeded` webhook — by the time this returns, no money has moved.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing topup"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pack":{"$ref":"#/components/schemas/TopUpPack"},"success_url":{"type":"string","format":"uri"},"cancel_url":{"type":"string","format":"uri"}},"required":["pack"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TopUpCheckoutResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/auto-recharge":{"get":{"operationId":"billing_auto_recharge_get","tags":["Billing"],"description":"Get the workspace's auto-recharge configuration. Returns `{ config: null }` when no config has been saved. Even disabled configs surface their saved threshold / pack so the UI can pre-fill the form.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing auto-recharge get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutoRechargeGetResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"billing_auto_recharge_update","tags":["Billing"],"description":"Update the workspace's auto-recharge configuration. Allowed thresholds: 50/100/250/500. Allowed packs: small/medium/large. The 24h throttle and payment-method-on-file checks are evaluated at trigger time, not when this route runs — admins can pre-configure threshold/pack before adding a card.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing auto-recharge set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"threshold":{"anyOf":[{"type":"number","enum":[50]},{"type":"number","enum":[100]},{"type":"number","enum":[250]},{"type":"number","enum":[500]}]},"pack":{"type":"string","enum":["small","medium","large"]}},"required":["enabled","threshold","pack"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutoRechargeUpdateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/per-seat-cap":{"get":{"operationId":"billing_per_seat_cap_get","tags":["Billing"],"description":"Get the workspace's per-seat cap configuration. Returns `{ config: null }` when no row exists; otherwise `{ config: { enabled, amount_per_seat } }`. Available to any authenticated member; mutation is admin-only.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing per-seat-cap get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PerSeatCapGetResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"billing_per_seat_cap_update","tags":["Billing"],"description":"Update the workspace's per-seat cap configuration. Body: `{ enabled: boolean, amount_per_seat?: number }`. When `enabled: true`, `amount_per_seat` must be a positive integer. Admin only.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing per-seat-cap set"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"amount_per_seat":{"type":"integer","exclusiveMinimum":0}},"required":["enabled"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PerSeatCapUpdateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/notifications/dismiss":{"post":{"operationId":"billing_notifications_dismiss","tags":["Billing"],"description":"Dismiss the quota-threshold banner for the current billing period. Body: { threshold: 80 | 95 }. The 100% wall is sticky per spec — payloads with threshold=100 return 400.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing notifications dismiss"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"threshold":{"anyOf":[{"type":"number","enum":[80]},{"type":"number","enum":[95]}]}},"required":["threshold"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/QuotaNotificationDismissResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/billing/ledger":{"get":{"operationId":"billing_ledger_get","tags":["Billing"],"description":"Per-call actions ledger for the current 30-day window. Each row is one tool call: timestamp, source (spear / coworker_microservice / coworker_byo / human_direct_ui), tool, label, llm_cost + vendor_cost breakdown, total. SPEAR turns share `turn_id` for client-side grouping. Visibility: non-admins see only rows they initiated; admins see everything.","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"billing ledger"},"parameters":[{"schema":{"type":"string","description":"Page size 1-200; defaults to 50."},"required":false,"description":"Page size 1-200; defaults to 50.","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor for the next page."},"required":false,"description":"Opaque cursor for the next page.","name":"cursor","in":"query"},{"schema":{"type":"string","enum":["spear","coworker_microservice","coworker_byo","human_direct_ui"],"description":"Filter by caller class."},"required":false,"description":"Filter by caller class.","name":"source","in":"query"},{"schema":{"type":"string","description":"Lookback window in days, 1-90 (clamped). Defaults to 30."},"required":false,"description":"Lookback window in days, 1-90 (clamped). Defaults to 30.","name":"window_days","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ActionsLedgerResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/mail-forwarding-public/verify":{"post":{"operationId":"mail_forwarding_verify","tags":["Mail"],"description":"Verify ownership of an external forwarding destination using the token from the click-through email. Idempotent — reusing the token after success returns the verified row again. No auth header required; the token IS the credential.","x-cli":{"hidden":true,"command":"mail forwarding verify"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyForwardingInput"}}}},"responses":{"200":{"description":"Forwarding address (verified or already verified)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForwardingAddress"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/search":{"get":{"operationId":"search_palette","tags":["Search"],"description":"Cross-module command-palette search. `q` is the query string; `limit` caps results (default 30, max 50). Empty query returns an empty response. Module diversity is preserved (per D219).","x-tool":{"expose":["mcp"]},"x-cli":{"command":"search","output":{"columns":["module","id","title"]}},"parameters":[{"schema":{"type":"string","description":"Search query string."},"required":false,"description":"Search query string.","name":"q","in":"query"},{"schema":{"type":"string","description":"Max results (capped at 50, default 30)."},"required":false,"description":"Max results (capped at 50, default 30).","name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SearchResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"search_workspace","tags":["Search"],"description":"Search across every module in the user's workspace (docs, sheets, slides, tasks, contacts, deals, channels, wiki, forms, calendar, users). Returns a flat list of results with module-aware metadata. Optional module filter narrows the search to one or more modules. Use this when the user asks to find something but you don't know which module it lives in.","x-tool":{"expose":["assistant","mcp"],"annotations":{"readOnly":true}},"x-cli":{"command":"search filtered","output":{"format":"object"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"Search query string."},"modules":{"type":"array","items":{"type":"string"},"description":"Restrict to specific modules (docs, sheets, slides, tasks, etc)."},"limit":{"type":"integer","minimum":1,"maximum":50},"offset":{"type":"integer","minimum":0},"from":{"type":"array","items":{"type":"string"},"description":"Restrict to rows authored by these people, matched against each module's author-equivalent (document owner, task assignee, message sender, mail sender) by display name or email. Multiple values widen the match."},"has_link":{"type":"boolean","description":"Restrict to rows that contain a link."},"has_attachment":{"type":"boolean","description":"Restrict to rows that carry an attachment."},"before":{"type":"string","format":"date","description":"Keep only rows created strictly before this date (YYYY-MM-DD, UTC). Bounds the row's creation timestamp — mail uses its sent date — never its last-modified time."},"after":{"type":"string","format":"date","description":"Keep only rows created on or after this date (YYYY-MM-DD, UTC). Same creation axis as `before`."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SearchResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/search/preview/{module}/{id}":{"get":{"operationId":"get_entity_preview","tags":["Search"],"description":"Look up a hover-card style preview of any referenced entity (document, task, contact, deal, channel, user, event, file, wiki page, form, email). Returns rich details — title, status, owner, due date, amount, etc. — without fetching the full record. Use this when an entity is referenced by ID and you need a quick summary.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"search preview"},"parameters":[{"schema":{"type":"string","description":"Entity module (e.g. 'document', 'task')."},"required":true,"description":"Entity module (e.g. 'document', 'task').","name":"module","in":"path"},{"schema":{"type":"string","description":"Entity ID."},"required":true,"description":"Entity ID.","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SearchPreviewResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/workspace/invite":{"post":{"operationId":"create_workspace_invite","tags":["Admin"],"description":"Create one or more workspace invites. Empty body mints a generic shareable link (returns `invite_url`). `{email}` or `{emails:[...]}` creates per-recipient invites and sends emails. Role defaults to `member` and is forced to `member` for any value other than `admin`.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"command":"workspace invite create","output":{"successMessage":"Invite created"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CreateInvitesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/invite/context":{"post":{"operationId":"invite_context_create","tags":["Invite"],"description":"Exchange an invitation capability for an HttpOnly continuation cookie without accepting the invitation.","x-cli":{"hidden":true,"command":"invite context create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteContextInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/InviteContextCreatedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"invite_context_get","tags":["Invite"],"description":"Read the invitation, exact resources, terminal state, and authenticated account choice without exposing the email-link capability.","x-cli":{"hidden":true,"command":"invite context get"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/InviteContextResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/invite/context/accept":{"post":{"operationId":"invite_context_accept","tags":["Invite"],"description":"Accept the focused invitation as the authenticated invited account. Reject stale tab context, mismatched or unverified accounts, and replay.","x-cli":{"hidden":true,"command":"invite context accept"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteContextMutationInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AcceptInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Gone","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/invite/context/decline":{"post":{"operationId":"invite_context_decline","tags":["Invite"],"description":"Decline the focused invitation without carrying its email-link capability through client routing.","x-cli":{"hidden":true,"command":"invite context decline"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteContextMutationInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DeclineInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/invite/{token}":{"get":{"operationId":"get_invite_by_token","tags":["Invite"],"description":"Fetch invite metadata for the accept page — workspace name, inviter, expiration. Public endpoint; the token itself is the credential. Returns 404 (not found or expired) or 409 (already accepted).","x-tool":{"expose":["assistant"]},"x-cli":{"hidden":true,"command":"invite get"},"parameters":[{"schema":{"type":"string","description":"Invite token from the email link."},"required":true,"description":"Invite token from the email link.","name":"token","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/InviteDetails"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/invite/{token}/accept":{"post":{"operationId":"invite_accept","tags":["Invite"],"description":"Accept an invite. New users supply `display_name` + `password` to register. Existing users authenticate via Bearer token to join an additional workspace; the body is otherwise ignored in that case. On an `external_grant` invite the body may carry `accept_as_workspace_id` — which of the accepter's own identities the grant binds to, named by the workspace that identity lives in; omitted when the account holds only one. Returns a fresh JWT bound to the accepter's own workspace.","x-cli":{"hidden":true,"command":"invite accept"},"parameters":[{"schema":{"type":"string","description":"Invite token from the email link."},"required":true,"description":"Invite token from the email link.","name":"token","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AcceptInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/invite/{token}/decline":{"post":{"operationId":"invite_decline","tags":["Invite"],"description":"Decline an invite. Invalidates the token immediately — the invite can no longer be accepted. Public endpoint; the token itself is the credential. Returns 404 (not found or expired) or 409 (already accepted).","x-cli":{"hidden":true,"command":"invite decline"},"parameters":[{"schema":{"type":"string","description":"Invite token from the email link."},"required":true,"description":"Invite token from the email link.","name":"token","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DeclineInviteResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/activity":{"get":{"operationId":"list_activity","tags":["Activity"],"description":"List recent workspace activity (last 30 days). Scoped to the current user's workspace. Filterable by resource type, resource ID, and acting user.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"activity list","output":{"columns":["created_at","user_name","action","resource_type"]}},"parameters":[{"schema":{"type":"string","description":"Max entries to return (capped at 100, default 50)."},"required":false,"description":"Max entries to return (capped at 100, default 50).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Pagination offset."},"required":false,"description":"Pagination offset.","name":"offset","in":"query"},{"schema":{"type":"string","description":"Filter to a single resource type (e.g. 'document', 'task')."},"required":false,"description":"Filter to a single resource type (e.g. 'document', 'task').","name":"resource_type","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Filter to a specific resource (UUID)."},"required":false,"description":"Filter to a specific resource (UUID).","name":"resource_id","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Filter to actions performed by a specific user (UUID)."},"required":false,"description":"Filter to actions performed by a specific user (UUID).","name":"user_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ActivityListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/home/digest":{"get":{"operationId":"home_digest","tags":["Home"],"description":"Workspace-home roll-up: trailing-window task velocity (with prior-window deltas) plus the actor-aggregated team digest, visibility-gated per viewer. The `window` param selects the trailing window (7d default, or 1d for Today). Accessible to any authenticated workspace member.","parameters":[{"schema":{"type":"string","enum":["7d","1d"],"description":"Trailing window for the velocity counts and the digest: '7d' (default) or '1d' (Today)."},"required":false,"description":"Trailing window for the velocity counts and the digest: '7d' (default) or '1d' (Today).","name":"window","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/HomeDigestResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/changelog":{"get":{"operationId":"changelog_list","tags":["Changelog"],"description":"Returns the static API changelog (newest first). Public — no auth required. Powers the Developers portal 'What's New' tab.","x-cli":{"command":"changelog list","output":{"columns":["published_at","version","title","breaking"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ChangelogResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}}}}},"/api/feedback":{"post":{"operationId":"submit_feedback","tags":["Feedback"],"description":"Submit a bug report from the workspace app. Auth-gated and rate-limited per user (10/min in production, 200/min in dev). Body shape: `{description, priority?, screenshotDataUrl?, attachments?, context}` — see `FeedbackInput`. Returns 200 with a receipt id even when the downstream webhook fails (best-effort GCS screenshot fallback runs in that case so triage retains the evidence). Returns 503 with `{error: \"Feedback reporting not available\"}` when the webhook isn't configured (outside the contract error-code enum, surfaced via raw Response).","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true,"openWorld":true}},"x-cli":{"hidden":true,"command":"feedback submit"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackBodyInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FeedbackResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackErrorResponse"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"oauth_protected_resource_metadata","tags":["OAuth"],"description":"RFC 9728. Tells MCP clients that hit `/mcp` (and got a 401) where to find the matching authorization server.","x-cli":{"hidden":true,"command":"oauth resource-metadata"},"responses":{"200":{"description":"Protected resource metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"oauth_authorization_server_metadata","tags":["OAuth"],"description":"RFC 8414. Advertises every OAuth endpoint and supported feature so MCP clients can complete the discovery → register → authorize → token loop.","x-cli":{"hidden":true,"command":"oauth server-metadata"},"responses":{"200":{"description":"Authorization server metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizationServerMetadata"}}}}}}},"/oauth/register":{"post":{"operationId":"oauth_register_client","tags":["OAuth"],"description":"Dynamic client registration. Public clients self-register and receive a `client_id`. PKCE is required at /authorize because no client secret is issued.","x-cli":{"hidden":true,"command":"oauth register"},"responses":{"201":{"description":"Client registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterClientResponse"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Too many client registrations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/oauth/authorize":{"get":{"operationId":"oauth_authorize_get","tags":["OAuth"],"description":"Validates the OAuth request, then redirects to the app's consent screen, which authenticates the caller through the normal login (every provider) and calls POST /api/oauth/grant on approval.","x-cli":{"hidden":true,"command":"oauth authorize"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"client_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"redirect_uri","in":"query"},{"schema":{"type":"string"},"required":false,"name":"response_type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"code_challenge","in":"query"},{"schema":{"type":"string"},"required":false,"name":"code_challenge_method","in":"query"},{"schema":{"type":"string"},"required":false,"name":"scope","in":"query"},{"schema":{"type":"string"},"required":false,"name":"state","in":"query"}],"responses":{"302":{"description":"Redirect to the app's consent screen","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"description":"Invalid request — error page","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/api/oauth/client/{client_id}":{"get":{"operationId":"oauth_client_public_profile","tags":["OAuth"],"description":"The registered display name of an OAuth client, for the consent screen. Returns only what the client published at registration.","parameters":[{"schema":{"type":"string"},"required":true,"name":"client_id","in":"path"}],"responses":{"200":{"description":"The client's registered profile","content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string"},"name":{"type":"string"}},"required":["client_id","name"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/oauth/agents":{"get":{"operationId":"oauth_list_authorizable_agents","tags":["OAuth"],"description":"Agent identities the caller may grant an authorization as. Empty when they manage none.","responses":{"200":{"description":"Authorizable coworker identities","content":{"application/json":{"schema":{"type":"object","properties":{"agents":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string"},"display_name":{"type":"string"},"handle":{"type":"string"}},"required":["user_id","display_name","handle"]}}},"required":["agents"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/oauth/grant":{"post":{"operationId":"oauth_grant","tags":["OAuth"],"description":"Mints an authorization code for the authenticated user after they approve a client. Returns the URL to redirect to; the caller never constructs it, so an unregistered redirect_uri cannot be reached.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string"},"redirect_uri":{"type":"string"},"decision":{"type":"string","enum":["approve","deny"]},"principal":{"anyOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["self"]}},"required":["kind"]},{"type":"object","properties":{"kind":{"type":"string","enum":["agent"]},"user_id":{"type":"string","format":"uuid"}},"required":["kind","user_id"]},{"type":"object","properties":{"kind":{"type":"string","enum":["new_agent"]},"display_name":{"type":"string","minLength":1,"maxLength":64}},"required":["kind","display_name"]}]},"scope":{"type":"string"},"state":{"type":"string"},"code_challenge":{"type":"string"},"code_challenge_method":{"type":"string"}},"required":["client_id","redirect_uri","decision"]}}}},"responses":{"200":{"description":"Approved — redirect the browser to `redirect_to`","content":{"application/json":{"schema":{"type":"object","properties":{"redirect_to":{"type":"string"}},"required":["redirect_to"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/oauth/token":{"post":{"operationId":"oauth_token","tags":["OAuth"],"description":"Exchanges a one-time authorization code for a long-lived API key. Accepts `application/json` or `application/x-www-form-urlencoded` (the OAuth spec mandates form-encoded; we accept either). PKCE verifier is required when the original /authorize call included a code_challenge.","x-cli":{"hidden":true,"command":"oauth token"},"responses":{"200":{"description":"Access token issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenResponse"}}}},"400":{"description":"OAuth error (invalid_grant, invalid_request, …)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenError"}}}},"429":{"description":"Too many token requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/oauth/revoke":{"post":{"operationId":"oauth_revoke","tags":["OAuth"],"description":"Revoke an API key issued via /oauth/token. RFC 7009 mandates 200 even when the token is missing or already invalid — only the caller's own keys can be revoked (auth required).","x-cli":{"hidden":true,"command":"oauth revoke"},"responses":{"200":{"description":"Revoked (or no-op if token missing/invalid)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRevokeResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/provision":{"post":{"operationId":"provision_coworker","tags":["Coworkers"],"description":"Provision a new AI coworker (persona + focus areas). Auto-generates an agent account and coworker config.","x-tool":{"expose":[]},"x-cli":{"hidden":true,"command":"coworkers provision"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":100},"persona":{"type":"string"},"focus_areas":{"type":"array","items":{"type":"string"}},"avatar_url":{"type":"string"},"role":{"type":"string","enum":["member","admin"]},"manager_user_id":{"type":"string","format":"uuid","description":"Workspace user accountable for this coworker. Defaults to the provisioning caller."}},"required":["display_name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers":{"get":{"operationId":"list_coworkers","tags":["Coworkers"],"description":"List all AI coworkers in the workspace (persona-backed agents with focus areas and playbooks).","x-tool":{"expose":[]},"x-cli":{"command":"coworkers list","output":{"columns":["id","display_name","status"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/executions":{"get":{"operationId":"list_running_executions","tags":["Coworkers"],"description":"List in-flight executions across every coworker in the active workspace. Joins coworker_executions → coworkers, filtered by status IN ('PENDING','RUNNING'). Powers the 'Coworkers — running now' saved filter on People & Access.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers executions running"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"$ref":"#/components/schemas/CoworkerExecutionSurface"},"required":false,"name":"surface","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"since","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"coworker_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerRunningExecutionsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/dispatch":{"post":{"operationId":"dispatch_coworker","tags":["Coworkers"],"description":"Dispatch a trigger to a coworker. Invoked by Automations as the canonical 'wake a coworker' action.","x-tool":{"expose":["automations","assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers dispatch"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string","description":"Trigger source identifier (e.g. chat, mail, automation)."},"event":{"type":"string","description":"Event type that triggered the dispatch (e.g. message.created, email.received)."},"payload":{"type":"object","additionalProperties":{},"description":"Arbitrary trigger data forwarded to the coworker's SPEAR loop."},"playbook_id":{"type":"string","format":"uuid","description":"Optional playbook UUID to execute. When set, skips Scope-phase auto-selection (reason: explicit). When absent, the Scope phase selects the best-fit playbook or falls back to persona."},"idempotency_key":{"type":"string","minLength":1,"description":"Client-generated key for at-most-once dispatch deduplication."}},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerDispatchResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/pause":{"post":{"operationId":"pause_coworker","tags":["Coworkers"],"description":"Pause coworker (stops scheduled executions).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers pause"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/resume":{"post":{"operationId":"resume_coworker","tags":["Coworkers"],"description":"Resume a paused coworker.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers resume"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/manager":{"patch":{"operationId":"change_coworker_manager","tags":["Coworkers"],"description":"Reassign the accountable human (manager) for a coworker. Admin-only — the current manager cannot reassign themselves out.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers change-manager"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"manager_user_id":{"type":["string","null"],"format":"uuid","description":"New manager (workspace user id), or null to clear (admin-only after)."}},"required":["manager_user_id"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/rotate-token":{"post":{"operationId":"coworkers_rotate_token","tags":["Coworkers"],"description":"Rotate the management token used to talk to the coworker service.","x-tool":{"expose":["assistant","mcp"],"annotations":{"destructive":true}},"x-cli":{"hidden":true,"command":"coworkers rotate-token"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/status":{"get":{"operationId":"get_coworker_status","tags":["Coworkers"],"description":"Get a coworker's runtime status (proxied from coworker service).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers status"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerProxyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/playbooks":{"get":{"operationId":"coworkers_playbooks_list","tags":["Coworkers"],"description":"List the coworker's playbooks (metadata + current version pointer).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"coworkers playbooks list"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerPlaybookListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"coworkers_playbooks_create","tags":["Coworkers"],"description":"Create a playbook and its initial version. `instructions` and `subtasks` seed version 1, which becomes the current version.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"coworkers playbooks create"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"objective":{"type":["string","null"],"maxLength":2000},"instructions":{"type":["string","null"],"maxLength":50000},"subtasks":{},"trigger_types":{"type":["array","null"],"items":{"type":"string","minLength":1},"maxItems":20}},"required":["title"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerPlaybookResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/playbooks/{playbookId}/versions":{"get":{"operationId":"coworkers_playbook_versions_list","tags":["Coworkers"],"description":"List all versions of a playbook, newest first.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"coworkers playbooks versions list"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"playbookId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerPlaybookVersionsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"coworkers_playbook_versions_create","tags":["Coworkers"],"description":"Append a new version. Auto-increments the version number and marks the new version current. Prior versions stay readable for audit.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"coworkers playbooks versions create"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"playbookId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"instructions":{"type":["string","null"],"maxLength":50000},"subtasks":{},"change_reason":{"type":["string","null"],"maxLength":500}},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerPlaybookVersionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/playbooks/{playbookId}/versions/{versionId}":{"get":{"operationId":"coworkers_playbook_versions_get","tags":["Coworkers"],"description":"Get one historical version's instructions and subtasks.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"coworkers playbooks versions get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"playbookId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"versionId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerPlaybookVersionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/playbooks/{playbookId}":{"get":{"operationId":"coworkers_playbooks_get","tags":["Coworkers"],"description":"Get one playbook with its current version's instructions and subtasks.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"coworkers playbooks get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"playbookId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerPlaybookResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"coworkers_playbooks_update","tags":["Coworkers"],"description":"Edit playbook metadata in place (title, objective). Instructions and subtasks are immutable — create a new version instead.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"coworkers playbooks update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"playbookId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"objective":{"type":["string","null"],"maxLength":2000},"trigger_types":{"type":["array","null"],"items":{"type":"string","minLength":1},"maxItems":20}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerPlaybookResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"coworkers_playbooks_delete","tags":["Coworkers"],"description":"Delete a playbook and its versions. Returns 409 if any coworker_executions still reference the playbook — use the archive endpoint to retire it instead.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"coworkers playbooks delete","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"playbookId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/playbooks/{playbookId}/archive":{"post":{"operationId":"coworkers_playbooks_archive","tags":["Coworkers"],"description":"Archive a playbook. Archived playbooks are hidden from lists and cannot be selected during dispatch, but remain linked to historical executions for audit.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"coworkers playbooks archive","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"playbookId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/executions":{"get":{"operationId":"coworkers_executions_list","tags":["Coworkers"],"description":"Proxy: list coworker execution history (paginated).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers executions"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerProxyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/executions/{executionId}":{"get":{"operationId":"coworkers_execution_get","tags":["Coworkers"],"description":"Get one execution with full trace data — task row, parent/children lineage, conversation, SPEAR cycles, and tool-call activities. Powers the Execution Trace debug view.","x-tool":{"expose":["assistant","mcp","automations"]},"x-cli":{"hidden":true,"command":"coworkers executions get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"executionId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerProxyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/executions/{executionId}/cancel":{"post":{"operationId":"coworkers_execution_cancel","tags":["Coworkers"],"description":"Kill switch: cancel an in-flight execution. Flips an active (PENDING/RUNNING/PAUSED) coworker_executions row to CANCELLED; the SPEAR loop aborts at its next action-call boundary. Idempotent no-op on an already-terminal execution.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers executions cancel"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"executionId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/conversations":{"get":{"operationId":"coworkers_conversations_list","tags":["Coworkers"],"description":"Proxy (workspace-isolated): list conversations for the coworker in the active workspace.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers conversations"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerProxyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/conversations/{threadId}":{"get":{"operationId":"coworkers_conversation_get","tags":["Coworkers"],"description":"Proxy (workspace-isolated): get a single conversation thread.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers conversation get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"threadId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerProxyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/monitored-channels":{"get":{"operationId":"coworkers_monitored_channels_list","tags":["Coworkers"],"description":"Proxy (workspace-isolated): list channels the coworker is monitoring.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers monitored-channels list"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerProxyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"coworkers_monitored_channels_add","tags":["Coworkers"],"description":"Proxy (workspace-isolated): start monitoring a channel.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers monitored-channels add"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerProxyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}/monitored-channels/{chId}":{"delete":{"operationId":"coworkers_monitored_channels_remove","tags":["Coworkers"],"description":"Proxy (workspace-isolated): stop monitoring a channel.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers monitored-channels remove"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"chId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerProxyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"additionalProperties":{}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/coworkers/{id}":{"get":{"operationId":"get_coworker","tags":["Coworkers"],"description":"Get one coworker.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_coworker","tags":["Coworkers"],"description":"Update coworker metadata (persona, focus areas, display name, avatar).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"display_name":{"type":"string","minLength":1},"persona":{"type":"string"},"focus_areas":{"type":"array","items":{"type":"string"}},"avatar_url":{"type":"string"},"enabled_skills":{"type":["array","null"],"items":{"$ref":"#/components/schemas/CoworkerSkill"},"description":"Scope the coworker to these skills. Null clears the scope (full skill set)."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_coworker","tags":["Coworkers"],"description":"Delete a coworker (revokes API key + tears down config).","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"coworkers delete","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CoworkerSuccess"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/agents/{id}/subscriptions":{"get":{"operationId":"agent_get_subscriptions","tags":["Agents"],"description":"Read a 3P agent's directed-event subscriptions. Returns the resolved row with defaults applied (all interests on, no watched channels/keywords) when the agent has never saved one. Scoped to the caller's workspace.","x-tool":{"expose":[]},"x-cli":{"hidden":true,"command":"agents subscriptions get"},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Agent user id (users.type='agent')."},"required":true,"description":"Agent user id (users.type='agent').","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentSubscriptions"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"agent_put_subscriptions","tags":["Agents"],"description":"Full-replace a 3P agent's directed-event subscriptions. Upsert on (workspace_id, agent user_id); GET returns exactly what was set.","x-tool":{"expose":[]},"x-cli":{"hidden":true,"command":"agents subscriptions set"},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Agent user id (users.type='agent')."},"required":true,"description":"Agent user id (users.type='agent').","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mentions":{"type":"boolean","description":"Hear @mentions of this agent."},"dms":{"type":"boolean","description":"Hear direct messages sent to this agent."},"tasks_assigned":{"type":"boolean","description":"Hear tasks assigned to this agent."},"docs_shared":{"type":"boolean","description":"Hear docs/wiki shared with this agent."},"emails":{"type":"boolean","description":"Hear emails delivered to this agent's mailbox."},"watched_channel_ids":{"type":"array","items":{"type":"string"},"description":"Channel ids whose messages this agent hears (must be a member)."},"keywords":{"type":"array","items":{"type":"string"},"description":"Keywords that, when matched in an accessible message, this agent hears."}},"required":["mentions","dms","tasks_assigned","docs_shared","emails","watched_channel_ids","keywords"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentSubscriptions"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/agents/{id}/transport":{"get":{"operationId":"agent_get_transport","tags":["Agents"],"description":"Live-connection status for a 3P agent: whether a socket is currently registered on the `live` channel. An agent's transport is its live connection, not human push/email/in-app — an event that arrives while the agent is offline stays unread, so it is picked up from `GET /api/notifications` on the next connect.","x-tool":{"expose":[]},"x-cli":{"hidden":true,"command":"agents transport"},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Agent user id (users.type='agent')."},"required":true,"description":"Agent user id (users.type='agent').","name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentTransportStatus"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/agents/{id}/api-keys":{"post":{"operationId":"agent_create_api_key","tags":["Agents"],"description":"Mint an API key for an agent you manage. Returns the plaintext under `raw_key` once. Unlike POST /api/admin/api-keys this is reachable by the agent's manager, not admins only — and unlike rotate it is additive, revoking no existing key. Scoped to the caller's workspace.","x-tool":{"expose":[]},"x-cli":{"command":"agents api-keys create"},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Agent user id (users.type='agent')."},"required":true,"description":"Agent user id (users.type='agent').","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Label for the key, shown in the workspace API-key list."}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentApiKeyWithSecret"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/agents/{id}/manager":{"patch":{"operationId":"agent_set_manager","tags":["Agents"],"description":"Reassign the human accountable for an agent. Admin/owner only — a manager must not transfer themselves out. Keyed on the agent's user id, so it reaches a 3P agent, which `PATCH /api/coworkers/{id}/manager` cannot.","x-tool":{"expose":[]},"x-cli":{"command":"agents manager set"},"parameters":[{"schema":{"type":"string","format":"uuid","description":"Agent user id (users.type='agent')."},"required":true,"description":"Agent user id (users.type='agent').","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"manager_user_id":{"type":["string","null"],"format":"uuid","description":"Human accountable for this agent, or null to clear it."}},"required":["manager_user_id"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentManagerUpdated"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/users/{id}/notifications":{"get":{"operationId":"get_notification_settings","tags":["Notifications"],"description":"Get the unified notification-settings grid (sinks × events, sound, keywords, watched channels) for a principal. Admin/manager or the principal itself.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NotificationSettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"update_notification_settings","tags":["Notifications"],"description":"Patch a principal's notification-settings grid. Partial: only the events/sound/keywords/watched-channels keys present are written.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationSettingsPatchInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NotificationSettingsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/unsubscribe":{"get":{"operationId":"groups_unsubscribe_page","tags":["Groups"],"description":"Public unsubscribe confirmation page (clicked from an email footer). Verifies the signed JWT in `?token=` and renders a button that POSTs to the same URL. Changes nothing. Returns HTML.","x-cli":{"hidden":true,"command":"groups unsubscribe-page"},"x-tool":{"expose":[]},"responses":{"200":{"description":"Confirmation page (HTML)","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"description":"Invalid token (HTML page)","content":{"text/html":{"schema":{"type":"string"}}}},"410":{"description":"Expired token (HTML page)","content":{"text/html":{"schema":{"type":"string"}}}}}},"post":{"operationId":"groups_unsubscribe","tags":["Groups"],"description":"Perform the unsubscribe. Verifies the signed JWT in `?token=` and sets the member's team email delivery to none. Returns HTML.","x-cli":{"hidden":true,"command":"groups unsubscribe"},"responses":{"200":{"description":"Unsubscribed (HTML page)","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"description":"Invalid token (HTML page)","content":{"text/html":{"schema":{"type":"string"}}}},"410":{"description":"Expired token (HTML page)","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/api/teams/mine":{"get":{"operationId":"list_my_teams","tags":["Teams"],"description":"List teams the current user belongs to, with their role (admin or member) in each. Use this when the user asks 'what teams am I in?' or 'my teams' or 'my memberships'.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams mine","output":{"columns":["id","name","role"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/searchable":{"get":{"operationId":"teams_searchable","tags":["Teams"],"description":"Search teams visible to the caller for the share dialog. Returns the union of public teams and private teams where the caller is a member. Supports case-insensitive name filtering via `q` and a configurable `limit`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"hidden":true,"command":"teams searchable"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SearchableTeamListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams":{"get":{"operationId":"list_teams","tags":["Teams"],"description":"List workspace teams visible to the current user. Returns public teams and private teams the user is a member of, with member counts. Filterable by `q` (case-insensitive substring match on name + slug). Optional `limit` caps the result count. Use this when the user asks to see teams, distribution lists, or workspace teams.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams list","output":{"columns":["id","name","visibility","is_member"]}},"parameters":[{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_team","tags":["Teams"],"description":"Create a new team in the workspace. The caller becomes the team admin. Teams can serve as email distribution lists (when email_local_part is set) and/or permission targets. Use this when the user asks to create a team, distribution list, or mailing list.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"slug":{"type":"string"},"description":{"type":["string","null"]},"email_local_part":{"type":["string","null"]},"parent_team_id":{"type":["string","null"],"format":"uuid"},"default_channels":{"type":"array","items":{"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"join_policy":{"type":"string","enum":["open","request","invite"]},"posting_policy":{"type":"string","enum":["open","members_only","admins_only"]},"icon":{"type":["string","null"]},"color":{"type":["string","null"]}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Team"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/members":{"get":{"operationId":"teams_members_list","tags":["Teams"],"description":"Paginated member list. Private teams visible only to members or admins.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams members list"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamMembersListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{team_id}/members":{"post":{"operationId":"add_team_member","tags":["Teams"],"description":"Add a user to a team with an optional role (admin or member). Only team admins or workspace admins can add members. Default role is 'member'. Use this when the user asks to add someone to a team or distribution list.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams members add"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"team_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string","minLength":1},"role":{"type":"string","enum":["admin","member"]}},"required":["user_id"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamMemberDetailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/members/{userId}":{"patch":{"operationId":"teams_members_update_role","tags":["Teams"],"description":"Change a member's role. Admin only. Cannot demote the last admin.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams members update-role"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["admin","member"]}},"required":["role"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamMemberDetailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"teams_members_remove","tags":["Teams"],"description":"Remove a member. Admin only. Cannot remove the last admin.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams members remove"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userId","in":"path"}],"responses":{"204":{"description":"No content"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/subscription":{"get":{"operationId":"teams_get_subscription","tags":["Teams"],"description":"Get the caller's email-delivery preference for the team. Returns `{team_id, user_id, email_delivery}`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams subscription get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamSubscriptionStateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"teams_update_subscription","tags":["Teams"],"description":"Update the caller's email-delivery preference for the team. Body: `{email_delivery: 'each' | 'none'}`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams subscription update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email_delivery":{"type":"string","enum":["each","daily_digest","weekly_digest","none"]}},"required":["email_delivery"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamSubscriptionStateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/join":{"post":{"operationId":"teams_join","tags":["Teams"],"description":"Join a team. Open teams grant instant membership; request teams create a pending join request; invite teams reject.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams join"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamJoinResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/leave":{"post":{"operationId":"teams_leave","tags":["Teams"],"description":"Leave a team. Cannot leave if you're the last admin.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams leave"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/star":{"post":{"operationId":"teams_star","tags":["Teams"],"description":"Star (favorite) a team for the current user. Idempotent — starring an already-starred team is a no-op. Per-user state; never affects membership or access.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams star"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamStarStateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"teams_unstar","tags":["Teams"],"description":"Remove the current user's star from a team. Idempotent — unstarring a non-starred team is a no-op.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams unstar"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamStarStateResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/join-request":{"delete":{"operationId":"teams_cancel_join_request","tags":["Teams"],"description":"Cancel your own pending join request for this team.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams cancel-request"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/requests":{"get":{"operationId":"teams_requests_list","tags":["Teams"],"description":"List pending join requests. Admin only.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams requests list"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamJoinRequestsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/requests/{requestId}/approve":{"post":{"operationId":"teams_requests_approve","tags":["Teams"],"description":"Approve a join request — adds the user as a member.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams requests approve"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"requestId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/TeamMemberDetailResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{id}/requests/{requestId}/deny":{"post":{"operationId":"teams_requests_deny","tags":["Teams"],"description":"Deny a join request.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams requests deny"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"requestId","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/teams/{team_id}":{"get":{"operationId":"get_team","tags":["Teams"],"description":"Get details of a single team including its first 10 members. Returns team metadata (name, slug, visibility, join policy, email) and an embedded members list with each member's user_id, display_name, email, role, and added_at. Use this when the user asks about a specific team, its members, or 'who is in team X?'.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"team_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Team"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_team","tags":["Teams"],"description":"Update a team's settings (name, slug, description, email, parent, visibility, join policy, posting policy, icon, color). Only team admins or workspace admins can update. If changing parent, validates no cycle in hierarchy. Use this when the user asks to rename a team, move a team under a different parent, or change team settings.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams update"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"team_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"email_local_part":{"type":["string","null"]},"email_domain_id":{"type":["string","null"],"format":"uuid"},"parent_team_id":{"type":["string","null"],"format":"uuid"},"default_channels":{"type":"array","items":{"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"join_policy":{"type":"string","enum":["open","request","invite"]},"posting_policy":{"type":"string","enum":["open","members_only","admins_only"]},"icon":{"type":["string","null"]},"color":{"type":["string","null"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Team"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_team","tags":["Teams"],"description":"Permanently delete a team from the workspace. Only team admins or workspace admins can delete. All memberships are removed. Child teams are orphaned (parent set to null). Use this when the user asks to delete, remove, or dissolve a team.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"teams delete","confirm":true},"parameters":[{"schema":{"type":"string"},"required":true,"name":"team_id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/virality/cohort/{month}":{"get":{"operationId":"internal_virality_cohort_get","tags":["Internal"],"description":"Internal-staff K-factor metrics for a given cohort month. Returns the cohort size, K_1/K_2/K_3, K_total, and per-generation conversion rate. Authentication required + caller email must be on INTERNAL_ADMIN_EMAILS allowlist (empty env = feature off).","x-cli":{"hidden":true,"command":"internal virality cohort"},"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}$"},"required":true,"name":"month","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/KFactorCohortMetrics"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/coworkers":{"get":{"operationId":"internal_coworkers_dashboard_get","tags":["Internal"],"description":"Cross-workspace coworker dashboard. Internal-staff only.","x-cli":{"hidden":true,"command":"internal coworkers list"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"coworkers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"persona":{"type":["string","null"]},"base_url":{"type":"string"},"model_family":{"type":"string"},"manager_user_id":{"type":["string","null"],"format":"uuid"},"manager_display_name":{"type":["string","null"]},"workspace_id":{"type":["string","null"],"format":"uuid"},"workspace_slug":{"type":["string","null"]},"workspace_name":{"type":["string","null"]},"user_id":{"type":["string","null"],"format":"uuid"},"display_name":{"type":["string","null"]},"username":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"task_counts":{"type":"object","properties":{"pending":{"type":"integer","minimum":0},"running":{"type":"integer","minimum":0},"completed":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"cancelled":{"type":"integer","minimum":0},"paused":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0}},"required":["pending","running","completed","failed","cancelled","paused","total"]},"memory_count":{"type":"integer","minimum":0}},"required":["id","persona","base_url","model_family","manager_user_id","manager_display_name","workspace_id","workspace_slug","workspace_name","user_id","display_name","username","created_at","updated_at","task_counts","memory_count"]}},"total_coworkers":{"type":"integer","minimum":0},"total_running_tasks":{"type":"integer","minimum":0},"total_memories":{"type":"integer","minimum":0},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["coworkers","total_coworkers","total_running_tasks","total_memories"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/coworkers/coworkers/{id}":{"get":{"operationId":"internal_coworkers_get","tags":["Internal"],"description":"Coworker detail. Internal-staff only.","x-cli":{"hidden":true,"command":"internal coworkers get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"persona":{"type":["string","null"]},"base_url":{"type":"string"},"model_family":{"type":"string"},"manager_user_id":{"type":["string","null"],"format":"uuid"},"manager_display_name":{"type":["string","null"]},"workspace_id":{"type":["string","null"],"format":"uuid"},"workspace_slug":{"type":["string","null"]},"workspace_name":{"type":["string","null"]},"user_id":{"type":["string","null"],"format":"uuid"},"display_name":{"type":["string","null"]},"username":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"task_counts":{"type":"object","properties":{"pending":{"type":"integer","minimum":0},"running":{"type":"integer","minimum":0},"completed":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"cancelled":{"type":"integer","minimum":0},"paused":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0}},"required":["pending","running","completed","failed","cancelled","paused","total"]},"memory_count":{"type":"integer","minimum":0},"recent_tasks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"coworker_id":{"type":"string","format":"uuid"},"parent_task_id":{"type":["string","null"],"format":"uuid"},"title":{"type":"string"},"status":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","FAILED","CANCELLED","PAUSED"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"duration_ms":{"type":["integer","null"]},"error_message":{"type":["string","null"]}},"required":["id","coworker_id","parent_task_id","title","status","started_at","completed_at","duration_ms","error_message"]}},"llm_usage_24h":{"type":"object","properties":{"calls":{"type":"integer","minimum":0},"total_tokens":{"type":"integer","minimum":0},"cost":{"type":"string"}},"required":["calls","total_tokens","cost"]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["id","persona","base_url","model_family","manager_user_id","manager_display_name","workspace_id","workspace_slug","workspace_name","user_id","display_name","username","created_at","updated_at","task_counts","memory_count","recent_tasks","llm_usage_24h"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"internal_coworkers_update","tags":["Internal"],"description":"Update coworker config (model family, execution mode).","x-cli":{"hidden":true,"command":"internal coworkers update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model_family":{"type":"string","enum":["openai","google","anthropic"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["ok"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/coworkers/coworkers/{id}/memories":{"get":{"operationId":"internal_coworkers_memories_get","tags":["Internal"],"description":"Paginated memory browser for a coworker.","x-cli":{"hidden":true,"command":"internal coworkers memories"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"default":0},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"coworker_id":{"type":"string","format":"uuid"},"memories":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"content":{"type":"string"},"created_at":{"type":"string"}},"required":["id","content","created_at"]}},"total":{"type":"integer","minimum":0},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["coworker_id","memories","total","limit","offset"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/coworkers/tasks/{id}":{"get":{"operationId":"internal_coworkers_task_get","tags":["Internal"],"description":"Coworker task detail with cycles, activities, and LLM usage.","x-cli":{"hidden":true,"command":"internal coworkers task get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"coworker_id":{"type":"string","format":"uuid"},"parent_task_id":{"type":["string","null"],"format":"uuid"},"title":{"type":"string"},"status":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","FAILED","CANCELLED","PAUSED"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"duration_ms":{"type":["integer","null"]},"error_message":{"type":["string","null"]},"objective":{"type":["string","null"]},"instructions":{"type":["string","null"]},"outcome":{},"coworker_persona":{"type":["string","null"]},"cycles":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"resolution":{"type":["string","null"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","status","resolution","started_at","completed_at","created_at"]}},"activities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"function_name":{"type":"string"},"function_arguments":{},"outcome":{},"status":{"type":"string"},"error_message":{"type":["string","null"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","function_name","status","error_message","started_at","completed_at","created_at"]}},"llm_usage":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"execution_turn_id":{"type":["string","null"],"format":"uuid"},"prompt_name":{"type":["string","null"]},"model_used":{"type":["string","null"]},"prompt_tokens":{"type":["integer","null"]},"completion_tokens":{"type":["integer","null"]},"reasoning_tokens":{"type":["integer","null"]},"total_tokens":{"type":["integer","null"]},"cost":{"type":["string","null"]},"latency_ms":{"type":["integer","null"]},"finish_reason":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","execution_turn_id","prompt_name","model_used","prompt_tokens","completion_tokens","reasoning_tokens","total_tokens","cost","latency_ms","finish_reason","created_at"]}},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["id","coworker_id","parent_task_id","title","status","started_at","completed_at","duration_ms","error_message","objective","instructions","coworker_persona","cycles","activities","llm_usage"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/coworkers/tasks/{id}/action":{"post":{"operationId":"internal_coworkers_task_action","tags":["Internal"],"description":"Pause, resume, or cancel a running coworker task.","x-cli":{"hidden":true,"command":"internal coworkers task action"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["pause","resume","cancel"]}},"required":["action"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["ok"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/coworkers/execution":{"get":{"operationId":"internal_coworkers_execution_get","tags":["Internal"],"description":"Cross-workspace execution dashboard (running, pending, recent failures).","x-cli":{"hidden":true,"command":"internal coworkers execution"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"running_tasks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"coworker_id":{"type":"string","format":"uuid"},"parent_task_id":{"type":["string","null"],"format":"uuid"},"title":{"type":"string"},"status":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","FAILED","CANCELLED","PAUSED"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"duration_ms":{"type":["integer","null"]},"error_message":{"type":["string","null"]},"coworker_persona":{"type":["string","null"]},"claimed_by":{"type":["string","null"]}},"required":["id","coworker_id","parent_task_id","title","status","started_at","completed_at","duration_ms","error_message","coworker_persona","claimed_by"]}},"pending_count":{"type":"integer","minimum":0},"paused_count":{"type":"integer","minimum":0},"recent_failures":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"coworker_id":{"type":"string","format":"uuid"},"parent_task_id":{"type":["string","null"],"format":"uuid"},"title":{"type":"string"},"status":{"type":"string","enum":["PENDING","RUNNING","COMPLETED","FAILED","CANCELLED","PAUSED"]},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"duration_ms":{"type":["integer","null"]},"error_message":{"type":["string","null"]},"coworker_persona":{"type":["string","null"]}},"required":["id","coworker_id","parent_task_id","title","status","started_at","completed_at","duration_ms","error_message","coworker_persona"]}},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["running_tasks","pending_count","paused_count","recent_failures"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/coworkers/llm-usage":{"get":{"operationId":"internal_coworkers_llm_usage_get","tags":["Internal"],"description":"Token + cost rollup by model over the chosen window.","x-cli":{"hidden":true,"command":"internal coworkers llm-usage"},"parameters":[{"schema":{"type":"string","enum":["1h","24h","7d","all"],"default":"24h"},"required":false,"name":"window","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"window":{"type":"string","enum":["1h","24h","7d","all"]},"by_model":{"type":"array","items":{"type":"object","properties":{"model_used":{"type":["string","null"]},"calls":{"type":"integer","minimum":0},"prompt_tokens":{"type":"integer","minimum":0},"completion_tokens":{"type":"integer","minimum":0},"total_tokens":{"type":"integer","minimum":0},"total_cost":{"type":"string"},"avg_latency_ms":{"type":["integer","null"]}},"required":["model_used","calls","prompt_tokens","completion_tokens","total_tokens","total_cost","avg_latency_ms"]}},"total_calls":{"type":"integer","minimum":0},"total_tokens":{"type":"integer","minimum":0},"total_cost":{"type":"string"},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["window","by_model","total_calls","total_tokens","total_cost"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/coworkers/dispatch":{"post":{"operationId":"internal_coworkers_dispatch_send","tags":["Internal"],"description":"Manually dispatch a coworker with a payload for admin testing.","x-cli":{"hidden":true,"command":"internal coworkers dispatch"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"coworker_id":{"type":"string","format":"uuid"},"payload":{"type":"object","additionalProperties":{}}},"required":["coworker_id","payload"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"task_id":{"type":"string","format":"uuid"},"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}},"required":["task_id"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/domains":{"get":{"operationId":"internal_domains_list","tags":["Internal"],"description":"Internal-staff list of every workspace_domains row across all workspaces, joined with workspace name + slug. Filter by `?status=` and search by workspace/domain via `?q=`. Auth + caller email must be on INTERNAL_ADMIN_EMAILS.","x-cli":{"hidden":true,"command":"internal domains list"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"q","in":"query"}],"responses":{"200":{"description":"List of domains across all workspaces","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"workspace_name":{"type":"string"},"workspace_slug":{"type":"string"},"domain":{"type":"string"},"domain_type":{"type":"string"},"status":{"type":"string"},"verified":{"type":"boolean"},"is_default":{"type":["boolean","null"]},"dns_records_count":{"type":"integer","minimum":0},"last_setup_error":{"type":["string","null"]},"last_setup_attempt_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"ses_console_url":{"type":["string","null"]}},"required":["id","workspace_id","workspace_name","workspace_slug","domain","domain_type","status","verified","is_default","dns_records_count","last_setup_error","last_setup_attempt_at","created_at","updated_at","ses_console_url"]}},"total":{"type":"integer","minimum":0}},"required":["data","total"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Failed to list domains","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/domains/{id}/retry":{"post":{"operationId":"internal_domains_retry","tags":["Internal"],"description":"Re-run completeSesSetup for one domain. Used to unstick rows where the inline + scheduler attempts both failed.","x-cli":{"hidden":true,"command":"internal domains retry"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Retry completed (success may be true or false)","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"success":{"type":"boolean"},"domain":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"workspace_name":{"type":"string"},"workspace_slug":{"type":"string"},"domain":{"type":"string"},"domain_type":{"type":"string"},"status":{"type":"string"},"verified":{"type":"boolean"},"is_default":{"type":["boolean","null"]},"dns_records_count":{"type":"integer","minimum":0},"last_setup_error":{"type":["string","null"]},"last_setup_attempt_at":{"type":["string","null"]},"created_at":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"ses_console_url":{"type":["string","null"]}},"required":["id","workspace_id","workspace_name","workspace_slug","domain","domain_type","status","verified","is_default","dns_records_count","last_setup_error","last_setup_attempt_at","created_at","updated_at","ses_console_url"]}},"required":["id","success","domain"]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Retry failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/domains/{id}":{"delete":{"operationId":"internal_domains_delete","tags":["Internal"],"description":"Hard-delete a workspace_domains row. Does not touch SES — staff cleans up the SES identity via the AWS console.","x-cli":{"hidden":true,"command":"internal domains delete"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Domain row deleted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["id","deleted"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Delete failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/module-availability":{"get":{"operationId":"get_module_availability","tags":["Admin"],"description":"Which productivity modules are enabled for the caller's workspace: module key → boolean. Bootstrap gate for nav + routes.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ModuleAvailabilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/assessments/grid":{"get":{"operationId":"internal_assessments_grid_get","tags":["Internal"],"description":"The corpus-wide assessment grid in one response: the run column list (id, startedAt, label, environment, resultCount, caseCount) plus the five-depth skillTree → level → branch → skill → test node tree across every skill tree, each node carrying per-run {passed, total} and each leaf its per-run result pointer. Authentication required + caller email must be on the INTERNAL_ADMIN_EMAILS allowlist (empty env = feature off).","x-cli":{"hidden":true,"command":"internal assessments grid"},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssessmentGrid"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/assessments/results/{id}":{"get":{"operationId":"internal_assessments_result_get","tags":["Internal"],"description":"One assessment result joined to the case version it ran against: the judge evaluation, the version's criteria, triggering message and fixtures, plus environment, commit and timings. Authentication required + caller email must be on the INTERNAL_ADMIN_EMAILS allowlist (empty env = feature off).","x-cli":{"hidden":true,"command":"internal assessments result"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssessmentResultDetail"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/assessments/results/{id}/siblings":{"get":{"operationId":"internal_assessments_result_siblings_get","tags":["Internal"],"description":"The same case's results across runs — one entry per run holding a result for that case (latest per run), newest run first, anchor run included. Authentication required + caller email must be on the INTERNAL_ADMIN_EMAILS allowlist (empty env = feature off).","x-cli":{"hidden":true,"command":"internal assessments result-siblings"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssessmentResultSiblings"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/internal/assessments/cases/{id}":{"patch":{"operationId":"internal_assessments_case_patch","tags":["Internal"],"description":"Edit an assessment test case. Content fields (triggeringMessage, criteria, fixtures) append a new immutable version row and repoint current_version_id in one transaction — the prior version is never mutated, so every result keeps the exact version it ran against. Case-row fields (testName, branch, status) update in place without creating a version. Authentication required + caller email must be on the INTERNAL_ADMIN_EMAILS allowlist (empty env = feature off).","x-cli":{"hidden":true,"command":"internal assessments case-edit"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssessmentCasePatch"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssessmentCasePatchResult"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/analytics/{type}/{id}/export":{"get":{"operationId":"analytics_saved_report_export","tags":["Analytics"],"description":"Export a saved report's computed result. The body is raw: an `application/json` object for `format=json` (default) or a `text/csv` string for `format=csv`. `dashboards` cannot be exported (400) — export the individual reports instead.","parameters":[{"schema":{"type":"string","enum":["insights","funnels","retentions","cohorts","dashboards"],"description":"Saved-report type. `dashboards` cannot be exported (400)."},"required":true,"description":"Saved-report type. `dashboards` cannot be exported (400).","name":"type","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["json","csv"],"description":"Export format (default `json`)."},"required":false,"description":"Export format (default `json`).","name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsExportBody"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/analytics/dashboards/{id}/share":{"get":{"operationId":"analytics_dashboard_share_get","tags":["Analytics"],"description":"Without `token`: check whether a dashboard has a public share link (auth required). With `token`: resolve the public share token and return the read-only dashboard payload (no auth).","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Public share token. When present, the response is the read-only shared-dashboard payload instead of the share status."},"required":false,"description":"Public share token. When present, the response is the read-only shared-dashboard payload instead of the share status.","name":"token","in":"query"},{"schema":{"type":"string","description":"Legacy alias for `token`; used only when `token` is absent."},"required":false,"description":"Legacy alias for `token`; used only when `token` is absent.","name":"share","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AnalyticsDashboardShareStatus"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/analytics/users":{"get":{"operationId":"analytics_users_list","tags":["Analytics"],"description":"List analytics user profiles (paginated, searchable). Returns traits, first_seen, last_identified.","x-tool":{"expose":["assistant","mcp"]},"parameters":[{"schema":{"type":"string","description":"Substring match on analytics_user_id."},"required":false,"description":"Substring match on analytics_user_id.","name":"search","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size (1-200, default 50)."},"required":false,"description":"Page size (1-200, default 50).","name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Page offset (default 0)."},"required":false,"description":"Page offset (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AnalyticsUsersResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/analytics/users/aggregates":{"get":{"operationId":"analytics_users_aggregates","tags":["Analytics"],"description":"List analytics user profiles from the materialized view (faster at high volume, nightly refresh). Falls back to direct read when MV is unavailable.","x-tool":{"expose":["assistant","mcp"]},"parameters":[{"schema":{"type":"string","description":"Substring match on analytics_user_id."},"required":false,"description":"Substring match on analytics_user_id.","name":"search","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size (1-200, default 50)."},"required":false,"description":"Page size (1-200, default 50).","name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Page offset (default 0)."},"required":false,"description":"Page offset (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AnalyticsUsersResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/analytics/users/{userId}":{"get":{"operationId":"analytics_user_timeline","tags":["Analytics"],"description":"Get a user's event timeline with session grouping (30-min inactivity split). Walks the alias graph (depth 5) to include all prior identities.","x-tool":{"expose":["assistant","mcp"]},"parameters":[{"schema":{"type":"string"},"required":true,"name":"userId","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Page size (1-200, default 50)."},"required":false,"description":"Page size (1-200, default 50).","name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Page offset (default 0)."},"required":false,"description":"Page offset (default 0).","name":"offset","in":"query"},{"schema":{"type":"string","description":"ISO 8601 lower bound (inclusive)."},"required":false,"description":"ISO 8601 lower bound (inclusive).","name":"date_from","in":"query"},{"schema":{"type":"string","description":"ISO 8601 upper bound (inclusive)."},"required":false,"description":"ISO 8601 upper bound (inclusive).","name":"date_to","in":"query"},{"schema":{"type":"string","description":"Filter to a single event name."},"required":false,"description":"Filter to a single event name.","name":"event_type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AnalyticsUserTimelineResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/analytics/deletion-history":{"get":{"operationId":"analytics_deletion_history","tags":["Analytics"],"description":"List past GDPR deletion audit entries. Admin-only.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"Page size (1-100, default 50)."},"required":false,"description":"Page size (1-100, default 50).","name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"description":"Page offset (default 0)."},"required":false,"description":"Page offset (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AnalyticsDeletionHistoryResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/integrations/github/install":{"get":{"operationId":"integration_github_install","tags":["Integrations"],"description":"Admin-only. Returns a 302 redirect to the GitHub App installation page with a HMAC-signed `state` carrying `userId` + `workspaceId` so the callback can attribute the install correctly. When `GITHUB_APP_SLUG` is unconfigured, redirects to `/admin?integration_error=...` instead so the admin UI surfaces the misconfiguration.","x-cli":{"hidden":true,"command":"integrations github install"},"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/integrations/github/callback":{"get":{"operationId":"integration_github_callback","tags":["Integrations"],"description":"Public OAuth redirect target. Exchanges `installation_id` for an installation access token, fetches account metadata, and creates/updates the integration record. Always responds with a 302 to `/admin/integrations` — successes carry `?github=connected`, failures carry `?github_error=...`.","x-cli":{"hidden":true,"command":"integrations github callback"},"parameters":[{"schema":{"type":"string","description":"GitHub App installation ID assigned during installation. Numeric; parsed to int after presence check."},"required":false,"description":"GitHub App installation ID assigned during installation. Numeric; parsed to int after presence check.","name":"installation_id","in":"query"},{"schema":{"type":"string","description":"GitHub-supplied install vs request flag (`install` | `update`). Stored on the integration record."},"required":false,"description":"GitHub-supplied install vs request flag (`install` | `update`). Stored on the integration record.","name":"setup_action","in":"query"},{"schema":{"type":"string","description":"Base64url-JSON wrapper {payload, sig} signed with `JWT_SECRET`. Carries the originating `userId` + `workspaceId` so the callback can attribute the install to the right workspace."},"required":false,"description":"Base64url-JSON wrapper {payload, sig} signed with `JWT_SECRET`. Carries the originating `userId` + `workspaceId` so the callback can attribute the install to the right workspace.","name":"state","in":"query"}],"responses":{"302":{"description":"Redirect to /admin/integrations with success or error query"}}}},"/api/integrations/slack/install":{"get":{"operationId":"integration_slack_install","tags":["Integrations"],"description":"Admin-only. Returns a 302 redirect to Slack's OAuth consent page with a HMAC-signed `state` carrying `userId` + `workspaceId` so the callback can attribute the install correctly. When `SLACK_CLIENT_ID` is unconfigured, redirects to `/admin?integration_error=...` instead so the admin UI surfaces the misconfiguration.","x-cli":{"hidden":true,"command":"integrations slack install"},"responses":{"200":{"description":"OK"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/integrations/slack/callback":{"get":{"operationId":"integration_slack_callback","tags":["Integrations"],"description":"Public OAuth redirect target. Exchanges the `code` for a bot token, fetches workspace info, and creates/updates the integration record. Always responds with a 302 to `/admin/integrations` — successes carry `?slack=connected`, failures carry `?slack_error=...`.","x-cli":{"hidden":true,"command":"integrations slack callback"},"parameters":[{"schema":{"type":"string","description":"Authorization code Slack returns after the user approves the app. Absent when the user denies."},"required":false,"description":"Authorization code Slack returns after the user approves the app. Absent when the user denies.","name":"code","in":"query"},{"schema":{"type":"string","description":"Base64url-JSON wrapper {payload, sig} signed with `JWT_SECRET`. Carries the originating `userId` + `workspaceId` so the callback can attribute the install to the right workspace."},"required":false,"description":"Base64url-JSON wrapper {payload, sig} signed with `JWT_SECRET`. Carries the originating `userId` + `workspaceId` so the callback can attribute the install to the right workspace.","name":"state","in":"query"},{"schema":{"type":"string","description":"Slack-supplied error code when the user denies. Surfaced to the admin UI via `?slack_error=` redirect."},"required":false,"description":"Slack-supplied error code when the user denies. Surfaced to the admin UI via `?slack_error=` redirect.","name":"error","in":"query"}],"responses":{"302":{"description":"Redirect to /admin/integrations with success or error query"}}}},"/api/zoom/status":{"get":{"operationId":"zoom_status","tags":["Integrations"],"description":"Whether the Zoom integration is configured on this deployment and whether the caller has connected a Zoom account.","x-cli":{"command":"zoom status","output":{"format":"object"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ZoomStatusResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/zoom/auth-url":{"get":{"operationId":"zoom_auth_url","tags":["Integrations"],"description":"Start the Zoom OAuth connect flow. Returns the consent URL to open in a browser.","x-cli":{"command":"zoom auth-url","output":{"format":"object"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ZoomAuthUrlResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/zoom/connection":{"delete":{"operationId":"zoom_disconnect","tags":["Integrations"],"description":"Disconnect the caller's Zoom account.","x-cli":{"command":"zoom disconnect","confirm":true,"output":{"format":"object"}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ZoomDisconnectResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/zoom/meetings":{"post":{"operationId":"zoom_create_meeting","tags":["Integrations"],"description":"Create an instant Zoom meeting on the caller's connected account and return its join URL.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"zoom create-meeting","output":{"format":"object"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZoomMeetingCreateBody"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ZoomMeetingResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/zoom/callback":{"get":{"operationId":"zoom_callback","tags":["Integrations"],"description":"Public OAuth redirect target. Exchanges the `code` for tokens and stores the caller's Zoom connection. Always responds with a 302 to /settings/profile — successes carry `?zoom=connected`, failures carry `?zoom_error=...`.","x-cli":{"hidden":true,"command":"zoom callback"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"code","in":"query"},{"schema":{"type":"string"},"required":false,"name":"state","in":"query"},{"schema":{"type":"string"},"required":false,"name":"error","in":"query"}],"responses":{"302":{"description":"Redirect to /settings/profile with success or error query"}}}},"/api/dev/test-provision/integration":{"post":{"operationId":"dev_test_provision_integration","tags":["Dev"],"description":"Dev-only. Bypasses real OAuth and writes the post-handshake integration row + emits `integration.connected` (and optionally `integration.event_received`). Returns 404 when NODE_ENV=production.","x-cli":{"hidden":true,"command":"dev test-provision integration"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string","enum":["slack","github"]},"fire_event_received":{"type":"boolean","default":true},"fake_team_name":{"type":"string"}},"required":["provider"]}}}},"responses":{"201":{"description":"Test integration provisioned","content":{"application/json":{"schema":{"type":"object","properties":{"integration_id":{"type":"string","format":"uuid"},"provider":{"type":"string"},"is_new":{"type":"boolean"}},"required":["integration_id","provider","is_new"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Admin role required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Dev test-provision routes are not available in production","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Failed to provision test integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/dev/test-provision/verify-domain":{"post":{"operationId":"dev_test_provision_verify_domain","tags":["Dev"],"description":"Dev-only. Flips a workspace_domains row to verified=true and fires the custom_domain_configured ladder bonus emit (workspace.custom_domain_verified). Returns 404 when NODE_ENV=production.","x-cli":{"hidden":true,"command":"dev test-provision verify-domain"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"domain_id":{"type":"string","format":"uuid"}},"required":["domain_id"]}}}},"responses":{"200":{"description":"Test domain verification flipped","content":{"application/json":{"schema":{"type":"object","properties":{"domain_id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"verified":{"type":"boolean","enum":[true]}},"required":["domain_id","domain","verified"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Admin role required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Dev test-provision routes are not available in production","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Failed to verify test domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/dev/test-provision/emit-plan-changed":{"post":{"operationId":"dev_test_provision_emit_plan_changed","tags":["Dev"],"description":"Dev-only. Emits `billing.plan_changed` to the workspace's owner/admin members so connected WS clients receive a `notification.new` push. Returns 404 in production.","x-cli":{"hidden":true,"command":"dev test-provision emit-plan-changed"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"old_plan_tier":{"type":"string","enum":["free","pro"],"default":"free"},"new_plan_tier":{"type":"string","enum":["free","pro"],"default":"pro"}}}}}},"responses":{"200":{"description":"Event emitted","content":{"application/json":{"schema":{"type":"object","properties":{"recipients":{"type":"integer","minimum":0}},"required":["recipients"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Admin role required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Dev test-provision routes are not available in production","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/identity/onboarding-agent":{"post":{"operationId":"create_onboarding_agent","tags":["Identity"],"description":"Complete the guided create-agent flow for an account that signed up through `intent=invite-agent`. Provisions ONE agent into the caller's own workspace via the same service `POST /api/admin/users/provision-agent` uses, and returns its key — shown once, `Cache-Control: no-store`. The account's stored signup intent is the authority: 409 `agent_onboarding_not_pending` when the account never carried the intent or has already spent it, so a replayed final step provisions nothing. 400 carries the naming rule's own reason when the display name is refused.","x-cli":{"hidden":true,"command":"identity onboarding-agent","output":{"format":"object"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"display_name":{"type":"string","minLength":1,"description":"The agent's name, as typed in the flow. Letters, numbers, spaces, hyphens, underscores and periods; 1-60 characters; must start and end alphanumeric and carry at least two alphanumerics. Refused with the reason rather than mangled — the name becomes a display name and, slugified, an email local-part."}},"required":["display_name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OnboardingAgentResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/identity/api-keys":{"get":{"operationId":"list_identity_api_keys","tags":["Identity"],"description":"List the calling user's own API keys. Scoped to `c.var.user.id` — does not return keys belonging to other users in the same workspace. Admins managing other users' keys should use `GET /api/admin/api-keys`.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"identity api-keys list","aliases":["identity api-keys ls"],"output":{"columns":["id","name","key_prefix","scopes","expires_at","last_used_at"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/IdentityApiKeysListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_identity_api_key","tags":["Identity"],"description":"Create a new API key for the calling user. Returns the plaintext key under `raw_key` once — caller must save it immediately (server sends `Cache-Control: no-store`). Rate-limited to 10 ops/hour per user in production.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"identity api-keys create","output":{"successMessage":"API key created: {key.id}"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"scopes":{"type":"array","items":{"type":"string"}},"rate_limit":{"type":"integer","minimum":1,"maximum":10000},"expires_at":{"type":["string","null"]},"confirm_wildcard":{"type":"boolean"}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/IdentityApiKeyWithSecretResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/identity/api-keys/{id}/rotate":{"post":{"operationId":"rotate_identity_api_key","tags":["Identity"],"description":"Rotate the calling user's own API key. Mints a fresh plaintext key and stores the previous hash with a 24-hour grace window so in-flight requests keep working. Returns the new plaintext under `raw_key` once. Rate-limited to 10 ops/hour per user in production. 404 if the key doesn't belong to the calling user.","x-tool":{"expose":["assistant"],"annotations":{"destructive":true}},"x-cli":{"command":"identity api-keys rotate"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/IdentityApiKeyWithSecretResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/identity/api-keys/{id}":{"patch":{"operationId":"update_identity_api_key","tags":["Identity"],"description":"Update name, scopes, or `rate_limit` on the calling user's own API key. Returns the updated key. 404 if the key doesn't belong to the calling user.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"identity api-keys update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"scopes":{"type":"array","items":{"type":"string"}},"rate_limit":{"type":"integer","minimum":1,"maximum":10000},"confirm_wildcard":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/IdentityApiKeyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"revoke_identity_api_key","tags":["Identity"],"description":"Revoke (permanently delete) one of the calling user's own API keys. 404 if the key doesn't belong to the calling user. Returns 204 No Content on success.","x-tool":{"expose":["assistant","mcp"]},"x-cli":{"command":"identity api-keys revoke","confirm":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/automations/stats":{"get":{"operationId":"get_automations_stats","tags":["Automations"],"description":"Workspace automation run statistics over a recent window (`range` = 7d/14d/30d, default 7d): total/success/failed run counts, per-status breakdown, top failing workflows, a per-day series, an hour×day-of-week heatmap, and a quota snapshot.","x-cli":{"command":"automations stats"},"parameters":[{"schema":{"type":"string"},"required":false,"name":"range","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationsStatsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/run":{"post":{"operationId":"automations_run","tags":["Automations"],"description":"Manually dispatch a workflow with a caller-supplied trigger payload. The payload is bound as the entry node's output (any node with no incoming edges — a webhook / scheduleTrigger / event / email / manualTrigger node, or any other root) and flows down the DAG. Trigger TYPE is metadata for *automatic* invocation (cron / webhook ingress / event bus); manual dispatch works for any workflow with at least one node. Returns the new run's id and terminal status (or `suspended` if a delay/until_event node parked the run). Pass `_test_mode: true` in the body to dry-run instead — actions are stubbed and `trigger_source='test'` is recorded; the dedicated `automations_test` route is the preferred path for test runs because it accepts `pinData` for upstream-output overrides.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations run"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationRunResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/test":{"post":{"operationId":"automations_test","tags":["Automations"],"description":"Dry-run a workflow against a caller-supplied payload. Action nodes (`create_task`, `send_email`, `chat_assistant`, …) are stubbed: they return success with empty outputs WITHOUT invoking the real handler, so authors can verify filters / branches / expressions without producing real-world side effects. The payload binds to the workflow's entry node (any node with no incoming edges — `manualTrigger`, `webhook`, `scheduleTrigger`, `event`, `email`, or any other root); trigger TYPE is metadata for automatic invocation only and does not gate test dispatch. The optional `pinData` map keys node NAMES to output values that override evaluation entirely — useful for seeding realistic upstream shapes when only part of the DAG is being tested. Test runs are recorded with `trigger_source='test'` (filtered out of the default run-history list). Test mode bypasses the `active` flag so disabled drafts can be tested. (Spec Pat11.)","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations test"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payload":{"type":"object","additionalProperties":{},"description":"Trigger payload forwarded to the manualTrigger node, identical semantics to `automations_run`'s body. Defaults to `{}` when omitted."},"pinData":{"type":"object","additionalProperties":{},"description":"Per-node-name output overrides. When a node's NAME appears here, the dispatcher records the pinned value as that node's output and routes downstream WITHOUT evaluating the node — action handlers don't run, filter predicates don't fire, expressions don't resolve. n8n compat: same shape and semantics as n8n's `pinData{}` field."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationRunResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations":{"post":{"operationId":"automations_create","tags":["Automations"],"description":"Create a new workflow. The body's `workflow` JSONB is stored verbatim with `workflow_version = 1`; subsequent PATCHes write a new immutable snapshot to `automation_workflow_versions` and increment the version. Defaults: `active=false` (draft), `visibility=private`, `shared_with=[]`, `tags=[]`. The created row is returned with its assigned `id`.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations create"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationCreateInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationSaveResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"A saved workflow with optional advisory node-type warnings."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"automations_list","tags":["Automations"],"description":"List workflows in the active workspace. Supports `?active=true|false`, `?trigger_type=manualTrigger|webhook|event|scheduleTrigger|email`, and `?tag=foo` filters per Pat13. Pagination: `?limit=` (1-200, default 100), `?offset=`. Newest first.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations list","output":{"columns":["id","name","active","workflow_version"]}},"parameters":[{"schema":{"type":"string","description":"`true` or `false` to filter by enabled state."},"required":false,"description":"`true` or `false` to filter by enabled state.","name":"active","in":"query"},{"schema":{"type":"string","description":"Filter to workflows containing at least one node of this trigger type (`manualTrigger` / `webhook` / `event` / `scheduleTrigger` / `email`)."},"required":false,"description":"Filter to workflows containing at least one node of this trigger type (`manualTrigger` / `webhook` / `event` / `scheduleTrigger` / `email`).","name":"trigger_type","in":"query"},{"schema":{"type":"string","description":"Filter to workflows carrying this tag."},"required":false,"description":"Filter to workflows carrying this tag.","name":"tag","in":"query"},{"schema":{"type":"string","description":"Page size (1-200, default 100)."},"required":false,"description":"Page size (1-200, default 100).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Page offset (default 0)."},"required":false,"description":"Page offset (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/node-types":{"get":{"operationId":"automations_node_types_list","tags":["Automations"],"description":"Unified node-type catalog: ten hand-coded primitives (5 triggers + 5 DAG-control) plus every registered route carrying `x-tool.expose: ['automations']` (Pat2). The UI palette reads this live to render the node picker — adding a new action route makes it appear here on next server boot with zero automations-module code changes. No node type is flagged `deferred` at HEAD; the `code` primitive executes user JS in the WASM isolate. The `:type` route returns the full record including the parameter input schema.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"automations node-types list","output":{"format":"table","columns":["type","label","category","deferred"]}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NodeTypeListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Unified node-type catalog. UI palette reads this live to render the node-picker tree. Per Pat2 the palette groups action entries by their `module` field (lowercased OpenAPI tag)."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/node-types/{type}":{"get":{"operationId":"automations_node_types_get","tags":["Automations"],"description":"Full record for a single node-type, including the parameter input schema (JSON Schema, draft-07-ish, converted from zod for primitives; null for actions in v1 — fetch the route's request body schema from `/api/openapi.json` instead, using `operation_id`/`http_method`/`http_path` from this response). Returns 404 when the type isn't in the catalog.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"automations node-types get"},"parameters":[{"schema":{"type":"string","minLength":1,"description":"Node-type identifier — a primitive name (e.g., `webhook`, `filter`) for the ten hand-coded primitives, or a route's `operationId` (e.g., `create_task`, `crm_deal_stage_move`) for an action."},"required":true,"description":"Node-type identifier — a primitive name (e.g., `webhook`, `filter`) for the ten hand-coded primitives, or a route's `operationId` (e.g., `create_task`, `crm_deal_stage_move`) for an action.","name":"type","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/NodeTypeDetail"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Full record for a single node type, including the parameter input schema. Returned by `GET /api/automations/node-types/:type`."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/import":{"post":{"operationId":"automations_import","tags":["Automations"],"description":"Import a workflow from a third-party tool. `?source=n8n` (the only supported source for v1) accepts an n8n workflow JSON document as `multipart/form-data` with a `file` field. The handler walks every node, normalizes each `node.type` via the n8n alias table (audit §12.2.7), and runs the three-tier expression translator (audit §12.3.2) against every `={{ ... }}` parameter. The translated workflow is stored verbatim — original n8n type strings are kept on disk so `automations_export?format=n8n` round-trips cleanly; the dispatcher normalizes via `resolveNodeType()` at runtime. The response is the import-review pane: counts of clean / Tier-B-`code`-fallback / Tier-C-unsupported expressions, the list of unsupported nodes (n8n types with no native equivalent — e.g., `n8n-nodes-base.slack`), and the detail rows backing each count. The created row is always `active=false` — the user reviews unsupported nodes and Tier-B fallbacks before enabling.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"automations import"},"parameters":[{"schema":{"type":"string","enum":["n8n"],"description":"Third-party source. Only `n8n` is supported in v1."},"required":true,"description":"Third-party source. Only `n8n` is supported in v1.","name":"source","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Optional override for the imported workflow's name. Defaults to the n8n file's `name` field, or `Imported workflow` if missing."},"required":false,"description":"Optional override for the imported workflow's name. Defaults to the n8n file's `name` field, or `Imported workflow` if missing.","name":"name","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationImportInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationImportResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Body of a successful `POST /api/automations/import?source=n8n` response. Carries the import-review pane data: which expressions translated cleanly, which fell back to `code`, which were flagged unsupported."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/formatters/set":{"post":{"operationId":"formatter_set","tags":["Automations"],"description":"Set a flat map of fields on the node output. Native equivalent of the n8n `Set` node — alias `n8n-nodes-base.set → formatter_set` (Pat8). Pure passthrough: `parameters.values` is resolved upstream by the dispatcher's `resolveActionParameters` walker, so JSONLogic rules referencing `{var: \"<UpstreamNode>.<field>\"}` produce the literal value the handler echoes back. Downstream nodes reference the result via `{var: \"<NodeName>.values.<key>\"}`. Spec line 41: formatters are `formatter_*` operationIds.","x-tool":{"expose":["all"]},"x-cli":{"command":"automations formatters set","hidden":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"values":{"type":"object","additionalProperties":{},"description":"Key-value map of fields to set on the node's output. Each value may be a literal (string/number/bool/array/object) OR a JSONLogic rule the dispatcher resolves against the node's inputs before invocation. The handler is a passthrough — no per-key validation; downstream consumers (or the workflow author's own filter/branch nodes) own the typing."}},"required":["values"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FormatterSetResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/http/request":{"post":{"operationId":"http_request","tags":["Automations"],"description":"Perform a bounded, SSRF-guarded HTTP request and return its status, headers, and auto-parsed body. This action is available only inside Automations workflows.","x-tool":{"expose":["automations"]},"x-cli":{"command":"automations http request","hidden":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Public HTTP or HTTPS URL to request."},"method":{"type":"string","enum":["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"],"default":"GET","description":"HTTP method. Defaults to GET."},"headers":{"type":"object","additionalProperties":{"type":"string"},"default":{},"description":"Static request headers as a name-to-value map."},"body":{"description":"Optional request body. Strings are sent verbatim; other JSON values are serialized as JSON."}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationHttpRequestResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Outbound response status, headers, and content-type-aware body for downstream nodes."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/runs/{runId}":{"get":{"operationId":"automations_runs_get","tags":["Automations"],"description":"Get a single run by id. The full row including `step_outputs` (per-node outputs, capped at 4 KB per node), `trigger_payload` (capped at 64 KB), `meta` (lineage/cancellation envelope), and the terminal status with optional `error`. 404 if the run lives in another workspace.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations runs get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"runId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowRun"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"A single workflow run row."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/runs/{runId}/cancel":{"post":{"operationId":"automations_runs_cancel","tags":["Automations"],"description":"Cancel a running or suspended run. Marks `workflow_runs.status='cancelled'` and stamps `meta.cancelledBy` + `meta.cancelledAt`. If the run is suspended (parked on `delay`/`until`/`until_event`), the matching `workflow_scheduled_runs` row is marked `cancelled` so the scheduler tick will not reclaim it. Idempotent — calling on an already-cancelled run is a no-op return. Terminal-status runs (`success`/`filtered`/`failed`/`depth_exceeded`) cannot be cancelled and return 400.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations runs cancel","confirm":true,"output":{"successMessage":"Run {runId} cancelled."}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"runId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowRunCancelResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/runs/{runId}/retry":{"post":{"operationId":"automations_runs_retry","tags":["Automations"],"description":"Re-dispatch a workflow with the original run's `trigger_payload`. Creates a NEW `workflow_runs` row (the parent row is preserved as historical evidence) and records lineage in the new row's `meta.parentRunId`. The retry uses the workflow's CURRENT version, not the version-at-dispatch of the parent — to replay against the historical version, restore that version first via `automations_versions_restore`. Workflows without a `manualTrigger` node currently cannot be retried via this route (event/webhook/schedule/email-driven runs require their original trigger source); 400 in those cases.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations runs retry"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"runId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowRunRetryResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/enable":{"post":{"operationId":"automations_enable","tags":["Automations"],"description":"Enable a workflow. Flips `active=true` so the engine starts dispatching on the workflow's triggers (event listeners, scheduler ticks, webhook ingest). Idempotent — calling on an already-enabled workflow is a no-op return. Emits `automation.workflow_enabled` to the audit log. Workspace-level quota: at most 20 active workflows per workspace (spec P20); attempting to enable past the cap returns 422.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations enable"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Automation"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"A workflow row. `workflow_version` is the live cursor; immutable snapshots live in `automation_workflow_versions`. Returned by every CRUD route."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/disable":{"post":{"operationId":"automations_disable","tags":["Automations"],"description":"Disable a workflow. Flips `active=false`. The dispatcher and scheduler will refuse to start new runs on this workflow until it's re-enabled; in-flight runs (suspended on a delay) continue to completion when their wake-time fires per audit §12.6.5 — disabling does not cancel suspended runs. Emits `automation.workflow_disabled` to the audit log.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations disable"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Automation"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"A workflow row. `workflow_version` is the live cursor; immutable snapshots live in `automation_workflow_versions`. Returned by every CRUD route."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/duplicate":{"post":{"operationId":"automations_duplicate","tags":["Automations"],"description":"Deep-copy a workflow into a new row in the same workspace. The duplicate starts as `active=false` (draft) regardless of the source's state. **Webhook ingest keys are NOT shared** — for every `webhook` trigger node in the source workflow, the duplicate gets a freshly-generated 32-byte key, a new `automation_webhook_keys` row, and a new SHA-256 hash on the duplicate's webhook node `parameters.ingestKeyHash`. This is the security boundary: a leaked source URL never grants access to the duplicate. Plaintext keys for the duplicate are NOT returned here — call `/duplicate/:newId/rotate-key` if the caller needs them surfaced. Emits `automation.workflow_duplicated` to the audit log.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations duplicate"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Automation"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"A workflow row. `workflow_version` is the live cursor; immutable snapshots live in `automation_workflow_versions`. Returned by every CRUD route."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/rotate-key":{"post":{"operationId":"automations_rotate_key","tags":["Automations"],"description":"Rotate the webhook ingest key on a workflow's `webhook` trigger node. Generates a new 32-byte key, replaces the SHA-256 hash on the trigger node's `parameters.ingestKeyHash`, deletes the old `automation_webhook_keys` row(s) for this workflow and inserts a new one, then **returns the plaintext key exactly ONCE in the response body**. The previous key is invalidated immediately — any in-flight HTTP requests with the old key resolve to 404. Workflows with no webhook trigger node return 400. Emits `automation.webhook_key_rotated` to the audit log.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations rotate-key","confirm":true,"output":{"successMessage":"Webhook ingest key rotated for workflow {id}. Old key invalidated immediately."}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationRotateKeyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/runs":{"get":{"operationId":"automations_runs_list","tags":["Automations"],"description":"List runs for one workflow, newest first. Filters: `?status=` (one of `success`/`filtered`/`failed`/`suspended`/`cancelled`/`depth_exceeded`); `?trigger_source=` (one of `manual`/`event`/`webhook`/`schedule`/`email`/`test`); time-range `?started_after=` and `?started_before=` (ISO 8601). Pagination: `?limit=` (1-200, default 50), `?offset=`. Tenant isolation via the workspace-scoped DB proxy — runs from other workspaces are invisible. Returns the parent automation's runs even if the automation row was soft-touched (renamed/disabled); a deleted automation cascades its runs to deletion (see `automations_delete`). Test-mode runs (`trigger_source='test'`) are included by default — use `?trigger_source=manual` etc. to exclude them.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations runs","output":{"columns":["id","status","trigger_source","duration_ms","started_at"]}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Filter by terminal status (`success`/`filtered`/`failed`/`suspended`/`cancelled`/`depth_exceeded`)."},"required":false,"description":"Filter by terminal status (`success`/`filtered`/`failed`/`suspended`/`cancelled`/`depth_exceeded`).","name":"status","in":"query"},{"schema":{"type":"string","description":"Filter by trigger source (`manual`/`event`/`webhook`/`schedule`/`email`/`test`)."},"required":false,"description":"Filter by trigger source (`manual`/`event`/`webhook`/`schedule`/`email`/`test`).","name":"trigger_source","in":"query"},{"schema":{"type":"string","description":"ISO 8601 lower bound (inclusive)."},"required":false,"description":"ISO 8601 lower bound (inclusive).","name":"started_after","in":"query"},{"schema":{"type":"string","description":"ISO 8601 upper bound (inclusive)."},"required":false,"description":"ISO 8601 upper bound (inclusive).","name":"started_before","in":"query"},{"schema":{"type":"string","description":"Page size (1-200, default 50)."},"required":false,"description":"Page size (1-200, default 50).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Page offset (default 0)."},"required":false,"description":"Page offset (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowRunListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/runs/heatmap":{"get":{"operationId":"automations_runs_heatmap","tags":["Automations"],"description":"Hourly run-count buckets for the activity heatmap on the run-history page (audit §2.5 CJ11). Aggregates `workflow_runs` rows by `date_trunc('hour', started_at)` over the requested window. Bounds default to the trailing 7 days; pass `?started_after=` / `?started_before=` (ISO 8601) to override. The window is capped at 90 days server-side. Empty hours are absent from the response — the UI zero-fills locally so the wire payload stays compact. Tenant isolation via the workspace-scoped DB proxy; cross-tenant ids return 404.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations runs heatmap","output":{"columns":["hour","count"]}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"ISO 8601 lower bound (inclusive). Default: 7 days before now. Maximum window is 90 days; longer windows are clamped server-side."},"required":false,"description":"ISO 8601 lower bound (inclusive). Default: 7 days before now. Maximum window is 90 days; longer windows are clamped server-side.","name":"started_after","in":"query"},{"schema":{"type":"string","description":"ISO 8601 upper bound (inclusive). Default: now."},"required":false,"description":"ISO 8601 upper bound (inclusive). Default: now.","name":"started_before","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WorkflowRunHeatmapResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/versions":{"get":{"operationId":"automations_versions_list","tags":["Automations"],"description":"List immutable workflow snapshots for one workflow, newest first. Each PATCH that changed the `workflow` JSONB appends one row here; create seeds v1; duplicate seeds v1 on the new row. Pagination via `?limit=` (1-200, default 50) + `?offset=`. The list returns one row per snapshot — to fetch a snapshot's body, call `GET /:id/versions/:version`. The parent automation must exist in the active workspace; cross-tenant ids 404.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations versions list","output":{"columns":["version","edited_by","edit_summary","created_at"]}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Page size (1-200, default 50)."},"required":false,"description":"Page size (1-200, default 50).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Page offset (default 0)."},"required":false,"description":"Page offset (default 0).","name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationWorkflowVersionListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/versions/{version}":{"get":{"operationId":"automations_versions_get","tags":["Automations"],"description":"Fetch one immutable workflow snapshot by its version number. Returns the full `workflow` JSONB plus the version metadata. 404 if either the parent workflow or the requested version doesn't exist in the active workspace.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations versions get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^\\d+$"},"required":true,"name":"version","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationWorkflowVersion"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"An immutable workflow snapshot. Append-only; never mutated or deleted (apart from cascade on parent automation delete)."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/versions/{version}/restore":{"post":{"operationId":"automations_versions_restore","tags":["Automations"],"description":"Restore a workflow to a historical version. **Byte-copy semantics, NOT JSON-merge:** the historical `workflow` JSONB is copied verbatim into a new row at the next version number AND written to `automations.workflow`. The original historical row is preserved — restore is non-destructive. In-flight runs continue against their `workflow_version_at_dispatch` pin so live rollbacks don't corrupt running dispatches. The new row's `edit_summary` is auto-filled with `Restored from v<source>`; the response carries both the updated parent workflow and the freshly-appended version row.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations versions restore","confirm":true,"output":{"successMessage":"Workflow {id} restored to version {version}."}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^\\d+$"},"required":true,"name":"version","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationWorkflowVersionRestoreResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/invoke":{"post":{"operationId":"automations_invoke","tags":["Automations"],"description":"Dispatch a child workflow with depth-incremented envelope. Used by the `automations_invoke` action node (wired into `evaluateNode` so workflows can call other workflows). Differs from `automations_run` in two ways: (1) accepts a `parent_depth` field that the route increments by 1 before dispatching the child run — `automations_run` always pins depth to 0; (2) records `meta.parentRunId` if `parent_run_id` is provided, for cross-workflow lineage. Spec P16 caps the depth chain at 3; calling with `parent_depth >= 3` produces a child run that immediately short-circuits with `status='depth_exceeded'`. Like `automations_run`, the child workflow must contain a `manualTrigger` node (the dispatch entry-point); workflows authored without one are not invokable. Node-type identity is the operationId verbatim: workflows reference this action as `type: \"automations_invoke\"` (the n8n `executeWorkflow` alias resolves to it); node types are never derived or renamed — labels are display-only.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations invoke"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payload":{"type":"object","additionalProperties":{},"description":"Trigger payload forwarded verbatim to the child workflow's `manualTrigger` node. Defaults to `{}` when omitted."},"parent_depth":{"type":"integer","minimum":0,"maximum":100,"description":"`_automation_depth` envelope value of the invoking parent run. The child run dispatches with `_automation_depth = parent_depth + 1`. Defaults to `0` (top-level invocation). Spec P16 caps the chain at depth 3 — `parent_depth >= 3` produces a child run that immediately short-circuits with `status='depth_exceeded'`."},"parent_run_id":{"type":"string","format":"uuid","description":"Run id of the invoking parent workflow. Recorded on the child run's `meta.parentRunId` for lineage. Optional — top-level invocations omit it."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationRunResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/export":{"get":{"operationId":"automations_export","tags":["Automations"],"description":"Export a workflow. `?format=native` (default) returns the raw `workflow` JSONB exactly as stored — re-importing produces a byte-identical row (lossless self-round-trip). `?format=n8n` returns an n8n-shaped JSON document with JSONLogic expressions translated back to `={{ ... }}` strings via the inverse-Tier-A subset (audit §12.3.2). Sub-rules outside that subset emit `null` and the response carries the `X-Automations-Lossy-Translation` header so consumers know the round-trip is approximate. The native format is the engine's authoritative shape; n8n format is for handoff to n8n self-hosted instances.","x-tool":{"expose":["assistant"]},"x-cli":{"command":"automations export","output":{"format":"raw"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"`native` (default) returns the raw JSONB; `n8n` returns an n8n-shaped JSON document."},"required":false,"description":"`native` (default) returns the raw JSONB; `n8n` returns an n8n-shaped JSON document.","name":"format","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationExportNativeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Body of a successful `GET /api/automations/:id/export` response, either format. Native-format export carries the workflow JSONB verbatim — re-importing produces a byte-identical row."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/permissions":{"get":{"operationId":"automations_permissions_list","tags":["Automations"],"description":"List users who have been granted access via shared_with.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations permissions list","output":{"columns":["userId","role"]}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationPermissionsListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"automations_permissions_set","tags":["Automations"],"description":"Grant viewer or editor access to a workspace user via shared_with.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations permissions set"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"type":"string","enum":["viewer","editor"]}},"required":["user_id","role"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationSetPermissionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/permissions/{userId}":{"delete":{"operationId":"automations_permissions_remove","tags":["Automations"],"description":"Revoke a user's shared_with access.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations permissions remove","confirm":true,"output":{"format":"none"}},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"userId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/DeletedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}/visibility":{"patch":{"operationId":"automations_visibility","tags":["Automations"],"description":"Change workflow visibility (private / workspace).","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations visibility"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"visibility":{"type":"string"}},"required":["visibility"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationVisibilityResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/automations/{id}":{"get":{"operationId":"automations_get","tags":["Automations"],"description":"Fetch one workflow by id.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations get"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Automation"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"A workflow row. `workflow_version` is the live cursor; immutable snapshots live in `automation_workflow_versions`. Returned by every CRUD route."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"automations_update","tags":["Automations"],"description":"Partially update a workflow. Only fields in the body are written; omitted fields keep their prior value. **If `workflow` is included**, the engine appends a new immutable row to `automation_workflow_versions` AND increments `automations.workflow_version` per spec P21 — running runs continue against the version they started at (their `workflow_version_at_dispatch` pin) so live edits never corrupt in-flight executions.","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations update"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationUpdateInput"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationSaveResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"A saved workflow with optional advisory node-type warnings."}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"automations_delete","tags":["Automations"],"description":"Hard-delete a workflow. Cascading FKs drop `automation_workflow_versions`, `workflow_runs`, `workflow_scheduled_runs`, and `automation_webhook_keys` rows tied to this id. There is no soft-delete / undo for v1 — UI surfaces a confirm dialog (Pat13).","x-tool":{"expose":["automations","assistant"]},"x-cli":{"command":"automations delete"},"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"No content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/.well-known/automations-ips":{"get":{"operationId":"automations_well_known_ips","tags":["Automations"],"description":"Published egress IP ranges for corporate-firewall allowlists. **No auth required** — meant to be fetched by external network operators without credentials. The ranges are best-effort: GCP Cloud Run egress is not strictly static, so the response carries a `note` disclaimer and a `last_verified` date. Consumers should periodically re-fetch this endpoint OR the upstream `https://www.gstatic.com/ipranges/cloud.json` for the freshest list. v1.1 adds a static-egress NAT (out of engine scope) which will collapse the list to a small fixed set.","x-cli":{"command":"automations well-known-ips","hidden":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AutomationsWellKnownIpsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}],"description":"Public response of `GET /.well-known/automations-ips`. No auth required — corporate firewalls fetch this without credentials to populate their allowlists for inbound webhook senders that Ambiguous routes through (Slack, Sentry, etc.)."}}}}}}},"/api/llm":{"post":{"operationId":"llm","tags":["Llm"],"description":"Run an LLM call from within an Automations workflow. Body: `{ prompt, output_schema?, model?, max_output_tokens?, temperature? }`. When `output_schema` is set, the response is the parsed typed JSON; when unset, the response is `{ text: string }`. Each successful invocation debits one `ai_actions` quota row. The route is registry-derived per AUTOMATIONS.md Pat2 and surfaces in `GET /api/automations/node-types` as `{ type: \"llm\", category: \"action\" }`. Automations-only by structural design — `x-tool.expose` is exactly `[\"automations\"]`.","x-tool":{"expose":["automations"]},"x-cli":{"command":"llm run","hidden":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"prompt":{"type":"string","minLength":1,"description":"LLM prompt template. Supports `={{ ... }}` JSONLogic interpolation against upstream `step_outputs`."},"output_schema":{"type":"object","additionalProperties":{},"description":"Optional JSON Schema. When set, the response is the parsed typed JSON; when unset, the response is `{ text: string }`."},"model":{"type":"string","description":"Optional model id (e.g. `gpt-5.4-mini`). Defaults to the workspace's configured assistant model."},"max_output_tokens":{"type":"integer","exclusiveMinimum":0,"maximum":8192,"description":"Optional max output tokens. Cap: 8192."},"temperature":{"type":"number","minimum":0,"maximum":2,"description":"Optional sampling temperature in [0, 2]."}},"required":["prompt"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]},{"type":"object","additionalProperties":{}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Unprocessable entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/retention":{"get":{"operationId":"get_sign_retention","tags":["Sign"],"description":"Read the workspace signed-document retention period. null means indefinite retention (LEGAL.md L8).","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignRetentionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_sign_retention","tags":["Sign"],"description":"Set the workspace signed-document retention period to an integer 1-9999 days, or null for indefinite retention. Admin-only (SIGN.md P8).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"retention_days":{"type":["integer","null"],"description":"Days a terminal signed document is retained before it enters the purge queue. Integer 1-9999, or null for indefinite retention."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignRetentionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/purge-queue":{"get":{"operationId":"list_sign_purge_queue","tags":["Sign"],"description":"List signed documents whose retention period elapsed and that are awaiting purge, soonest first. Each is restorable until its purge_after (LEGAL.md L8).","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignPurgeQueueResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/templates":{"get":{"operationId":"list_sign_templates","tags":["Sign"],"description":"List reusable signing templates.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignTemplateListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"create_sign_template","tags":["Sign"],"description":"Create a reusable signing template from field layout and signer roles.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"source_pdf_file_id":{"type":"string","format":"uuid"},"fields":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["signature","initial","text","date","checkbox","number","file"]},"page":{"type":"number"},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"},"required":{"type":"boolean"},"defaultValue":{"type":"string"},"signerRole":{"type":"string"}},"required":["type","page","x","y","w","h","required","signerRole"],"additionalProperties":false}},"signer_roles":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string"},"label":{"type":"string"},"orderIndex":{"type":"number"}},"required":["role","label","orderIndex"],"additionalProperties":false}}},"required":["title"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignTemplateWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/templates/{id}/use":{"post":{"operationId":"use_sign_template","tags":["Sign"],"description":"Create a new draft document from a template, populating fields with placeholder signer roles.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignDocumentWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign":{"post":{"operationId":"create_sign_document","tags":["Sign"],"description":"Create a draft signing document.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"source_type":{"type":"string","enum":["pdf","doc"]},"source_doc_id":{"type":"string","format":"uuid"},"source_pdf_file_id":{"type":"string","format":"uuid"},"signer_ordering":{"type":"string","enum":["parallel","sequential"]},"expires_at":{"type":"string"},"message":{"type":"string"}},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignDocumentWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"list_sign_documents","tags":["Sign"],"description":"List signing documents in the workspace.","parameters":[{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignDocumentListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}":{"get":{"operationId":"get_sign_document","tags":["Sign"],"description":"Get a signing document with signers and fields.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignDocumentWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"update_sign_document","tags":["Sign"],"description":"Update a draft signing document.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"signer_ordering":{"type":"string","enum":["parallel","sequential"]},"expires_at":{"type":["string","null"]},"message":{"type":["string","null"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignDocumentWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"delete_sign_document","tags":["Sign"],"description":"Delete a draft or void an active signing document.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/retention":{"patch":{"operationId":"update_sign_document_retention","tags":["Sign"],"description":"Override the retention period for one signed document, or null to defer to the workspace period. Admin-only — a document's own owner cannot shorten its retention (SIGN.md P8).","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"retention_days":{"type":["integer","null"],"description":"Days a terminal signed document is retained before it enters the purge queue. Integer 1-9999, or null for indefinite retention."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignDocumentRetentionResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/restore-from-purge":{"post":{"operationId":"restore_sign_document_from_purge","tags":["Sign"],"description":"Take one document back out of the purge queue during its recoverable window. Admin-only, same authority as the period itself (SIGN.md P8). 409 when the document is not queued.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignRestoreFromPurgeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/signers":{"post":{"operationId":"sign_add_signer","tags":["Sign"],"description":"Add a signer or CC recipient. Rejects agent users as signers (LEGAL.md L1).","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"},"role":{"type":"string","enum":["signer","cc"]},"order_index":{"type":"integer"},"user_id":{"type":"string","format":"uuid"}},"required":["email","name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignSignerWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/signers/order":{"put":{"operationId":"sign_reorder_signers","tags":["Sign"],"description":"Atomically set the sequential signing order: the full ordered list of the document's signer-role ids. Draft only.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"signer_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1}},"required":["signer_ids"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignSignersListResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/fields":{"post":{"operationId":"sign_add_field","tags":["Sign"],"description":"Add a signature field to a signing document.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"signer_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["signature","initial","text","date","checkbox","number","file"]},"page":{"type":"integer","minimum":1},"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1},"w":{"type":"number","minimum":0,"maximum":1},"h":{"type":"number","minimum":0,"maximum":1},"required":{"type":"boolean"},"default_value":{"type":"string"}},"required":["signer_id","type","page","x","y","w","h"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignFieldWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/fields/{field_id}":{"patch":{"operationId":"sign_update_field","tags":["Sign"],"description":"Reposition or resize a field on a draft signing document. The field id is stable — repositioning never re-creates the field.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"field_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"x":{"type":"number","minimum":0,"maximum":1},"y":{"type":"number","minimum":0,"maximum":1},"w":{"type":"number","minimum":0,"maximum":1},"h":{"type":"number","minimum":0,"maximum":1}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignFieldWrappedResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"sign_remove_field","tags":["Sign"],"description":"Remove a field from a signing document.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"field_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/signers/{signer_id}":{"delete":{"operationId":"sign_remove_signer","tags":["Sign"],"description":"Remove a signer or CC recipient from a draft signing document.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"signer_id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/prepare-send":{"post":{"operationId":"sign_prepare_send","tags":["Sign"],"description":"Prepare a document for sending. Validates signers and renders PDF preview. Transitions draft → preview_pending.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignPrepareResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/confirm-send":{"post":{"operationId":"sign_confirm_send","tags":["Sign"],"description":"Confirm and dispatch a prepared document. Mints capability tokens and sends invite emails. Agent callers rejected (LEGAL.md L2).","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"rendered_pdf_drive_file_id":{"type":"string","format":"uuid"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignConfirmResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/void":{"post":{"operationId":"sign_void_document","tags":["Sign"],"description":"Void an active signing document. Invalidates all capability tokens.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignVoidResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/revert-to-draft":{"post":{"operationId":"sign_revert_to_draft","tags":["Sign"],"description":"Revert a preview_pending or out document back to draft for editing. An out document is revertible only while no signer has signed; reverting deactivates every signing link until the document is re-sent.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignVoidResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/certificate":{"get":{"operationId":"sign_get_certificate","tags":["Sign"],"description":"Download the Certificate of Completion for a completed document.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignSuccessResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sign/{id}/verify":{"get":{"operationId":"sign_verify_document","tags":["Sign"],"description":"Verify the integrity and signature of a completed document.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignVerifyResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/documents/{id}/sign-references":{"get":{"operationId":"sign_get_references","tags":["Sign"],"description":"List signing documents that use this document as a source.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SignReferencesResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/documents/{id}/verify-password":{"post":{"operationId":"public_document_verify_password","tags":["Public"],"description":"Verify the link password for a password-protected public document. Returns 200 `{valid: true}` on success and on documents without a password (no-op idempotent). 401 on wrong password, 410 on expired link, 404 on missing/private documents.","x-cli":{"hidden":true,"command":"public docs verify-password"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string","minLength":1,"description":"Plaintext password from the link's password gate."}},"required":["password"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VerifyPasswordResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/documents/{id}":{"get":{"operationId":"public_document_get","tags":["Public"],"description":"Public read-only access to a document with `visibility: link` or `public`. Password protection: pass the password via `X-Link-Password` header (NOT a query param — Finding 6). Expired links return 410 Gone.","x-cli":{"hidden":true,"command":"public docs get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PublicDocument"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLinkPasswordError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/wiki/pages/{id}/verify-password":{"post":{"operationId":"public_wiki_page_verify_password","tags":["Public"],"description":"Verify the link password for a password-protected public wiki page (canonical D102 path).","x-cli":{"hidden":true,"command":"public wiki verify-password"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VerifyPasswordResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/wiki/pages/{id}":{"get":{"operationId":"public_wiki_page_get","tags":["Public"],"description":"Public read-only access to a wiki page whose parent space's visibility is `link` or `public`. Password protection follows the same `X-Link-Password` header pattern as documents.","x-cli":{"hidden":true,"command":"public wiki get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PublicWikiPage"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/wiki/{id}/verify-password":{"post":{"operationId":"public_wiki_legacy_verify_password","tags":["Public"],"description":"Legacy alias for the canonical wiki verify-password route.","x-cli":{"hidden":true,"command":"public wiki verify-password-legacy"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VerifyPasswordResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/wiki/{id}":{"get":{"operationId":"public_wiki_legacy_get","tags":["Public"],"description":"Legacy alias for `/api/public/wiki/pages/:id`. New integrations should use the canonical path. Kept for backward compatibility with the existing `PublicDocumentPage` frontend.","x-cli":{"hidden":true,"command":"public wiki get-legacy"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PublicWikiPage"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/drive/{id}/verify-password":{"post":{"operationId":"public_drive_verify_password","tags":["Public"],"description":"Verify the link password for a password-protected public file. Mirrors the documents verify-password flow.","x-cli":{"hidden":true,"command":"public drive verify-password"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string","minLength":1,"description":"Plaintext password from the link's password gate."}},"required":["password"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/VerifyPasswordResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/drive/{id}/content":{"get":{"operationId":"public_drive_get_content","tags":["Public"],"description":"Public binary-download proxy for a Drive file with `visibility: link` or `public`. Streams bytes from GCS through the API so the request never hits the AuthGuard. Password protection: pass via `X-Link-Password` header. 401 on missing/wrong password, 404 on missing/private files, 410 on expired links.","x-cli":{"hidden":true,"command":"public drive content"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicDriveBinaryBody"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLinkPasswordError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/drive/{id}":{"get":{"operationId":"public_drive_get","tags":["Public"],"description":"Public read-only access to a Drive file with `visibility: link` or `public`. Returns metadata + a `download_url`. Password protection: pass via `X-Link-Password` header.","x-cli":{"hidden":true,"command":"public drive get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PublicFile"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLinkPasswordError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/slides/{id}":{"get":{"operationId":"public_slides_get","tags":["Public"],"description":"Public read-only access to a slide deck with `visibility: link` or `public`. Returns the full deck JSON (slides, settings, masterSlides). Password protection: pass the password via `X-Link-Password` header. Expired links return 410 Gone.","x-cli":{"hidden":true,"command":"public slides get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PublicSlides"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLinkPasswordError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/sheets/{id}/range":{"get":{"operationId":"public_sheet_get_range","tags":["Public"],"description":"Public cross-sheet range fetch (`IMPORTRANGE`) on a sheet with `visibility: link` or `public`. Query knobs (`spec` required, `orientation` ∈ {ROWS, COLUMNS}, `valueRenderOption` ∈ {STORED, FORMULA, EVALUATED}) and response shape mirror the authenticated `/api/sheets/{id}/range`. `EVALUATED` runs the server-side formula engine on every formula cell in the range. Password-protected sheets require the password via the `X-Link-Password` header; expired links return 410 Gone.","x-cli":{"hidden":true,"command":"public sheets range"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Range spec, e.g. `Sheet1!A1:D10` (required at runtime)."},"required":false,"description":"Range spec, e.g. `Sheet1!A1:D10` (required at runtime).","name":"spec","in":"query"},{"schema":{"type":"string","description":"`ROWS` (default) or `COLUMNS`."},"required":false,"description":"`ROWS` (default) or `COLUMNS`.","name":"orientation","in":"query"},{"schema":{"type":"string","description":"`STORED` (default), `FORMULA`, or `EVALUATED`."},"required":false,"description":"`STORED` (default), `FORMULA`, or `EVALUATED`.","name":"valueRenderOption","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RangeResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicLinkPasswordError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/assistant/conversations/{id}":{"get":{"operationId":"public_assistant_conversation_get","tags":["Public"],"description":"Public read-only view of an assistant conversation, gated by the stateless HMAC share token minted at POST /api/assistant/conversations/{id}/share. Pass the token via `?token=…`. Returns a Level-1 projection (title + message id/role/content/created_at only — never timeline / thinking_level / has_tool_errors). Invalid or tampered tokens return 401.","x-cli":{"hidden":true,"command":"public assistant conversation get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"Signed HMAC share token minted by the resource owner."},"required":true,"description":"Signed HMAC share token minted by the resource owner.","name":"token","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AssistantSharedConversation"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/scheduler/bookings/{cancelToken}":{"get":{"operationId":"public_scheduler_booking_get","tags":["Public"],"description":"Fetch a booking by its cancel-token. Powers the public cancel/reschedule page that the booking confirmation email links to.","x-cli":{"hidden":true,"command":"public scheduler booking get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"cancelToken","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/FullBookingResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/scheduler/bookings/{cancelToken}/cancel":{"post":{"operationId":"public_scheduler_booking_cancel","tags":["Public"],"description":"Cancel a booking via its cancel-token (no authentication). Records optional `reason` and updates the linked calendar event.","x-cli":{"hidden":true,"command":"public scheduler booking cancel"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"cancelToken","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":["string","null"],"description":"Optional human-readable reason recorded on the booking."}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CancelBookingResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/scheduler/{workspaceSlug}/{userSlug}/{linkSlug}":{"get":{"operationId":"public_scheduler_link_get","tags":["Public"],"description":"Fetch the public booking page for a scheduler link. Resolves `workspace.slug → user.slug → link.slug` to scope the lookup; returns null-equivalent 404 when any segment misses.","x-cli":{"hidden":true,"command":"public scheduler get"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"linkSlug","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PublicSchedulerLinkResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/scheduler/{workspaceSlug}/{userSlug}/{linkSlug}/slots":{"get":{"operationId":"public_scheduler_slots","tags":["Public"],"description":"List available booking slots for a scheduler link on a given day (`?date=YYYY-MM-DD`). Honors min-notice / max-advance / availability_hours / timezone configured on the link.","x-cli":{"hidden":true,"command":"public scheduler slots"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"linkSlug","in":"path"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"YYYY-MM-DD."},"required":true,"description":"YYYY-MM-DD.","name":"date","in":"query"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"notify","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SchedulerSlotsResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/scheduler/{workspaceSlug}/{userSlug}/{linkSlug}/book":{"post":{"operationId":"public_scheduler_book","tags":["Public"],"description":"Create a booking for a scheduler link. Returns the new booking + a `cancel_token` the guest can use to view or cancel without authentication. Auto-creates a CRM contact when `link.auto_create_contact` is set.","x-cli":{"hidden":true,"command":"public scheduler book"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"userSlug","in":"path"},{"schema":{"type":"string"},"required":true,"name":"linkSlug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"start_at":{"type":"string","description":"ISO 8601 start timestamp from one of the available slots."},"guest_name":{"type":"string","minLength":1},"guest_email":{"type":"string","format":"email"},"guest_phone":{"type":["string","null"]},"notes":{"type":["string","null"]}},"required":["start_at","guest_name","guest_email"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/BookingResponse"},{"type":"object","properties":{"entities":{"$ref":"#/components/schemas/EntityReferenceMap"},"entities_truncated":{"type":"boolean","enum":[true],"description":"Present only when the reference walk hit its cap; the resolved subset is still returned."}}}]}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/public/sequences/track/{tokenWithExt}":{"get":{"operationId":"public_sequences_track_open","tags":["Public"],"description":"Email-open tracking pixel. Decodes the token, records an `email_opened` event for the matching enrollment, and returns a 1x1 transparent PNG with no-cache headers so mail clients refetch on every open.","x-cli":{"hidden":true,"command":"public sequences track"},"parameters":[{"schema":{"type":"string","description":"Tracking token with optional `.png` or `.gif` suffix."},"required":true,"description":"Tracking token with optional `.png` or `.gif` suffix.","name":"tokenWithExt","in":"path"}],"responses":{"200":{"description":"OK"}}}},"/api/public/workspace/{workspaceId}/logo":{"get":{"operationId":"public_workspace_logo","tags":["Public"],"description":"Serve the workspace logo from GCS via a public proxy. Used by emails, external share pages, and the in-app WorkspaceSwitcher. Storage key resolves from `workspace_settings.workspace_logo_storage_key`.","x-cli":{"hidden":true,"command":"public workspace logo"},"parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"path"}],"responses":{"200":{"description":"OK"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"webhooks":{},"security":[{"bearerAuth":[]}]}