# Knobase workspace management contract This file is the canonical LLM contract for workspace management. Source: https://knobase.com/docs/llms-management.txt OpenAPI: https://knobase.com/docs/management/openapi.json Publisher serving contract: https://knobase.com/docs/llms.txt MCP resource: https://knobase.com/api/mcp REST resource: https://knobase.com/api ## Credential classes (never mix) - A. KNOBASE_API_KEY (kb_…) — POST /v1/offers/decide and serving events only. Never for dashboard, OAuth, MCP, browsers, or agents managing a workspace. - B. Dashboard cookie session — humans only. Not a transferable agent credential. High-impact dashboard writes create a confirmation; the human approves once on a hosted page or inline sheet. - C. User-delegated management OAuth token — short-lived, refresh rotation + reuse revocation (refreshTokenReuseInterval: 0), bound to user + client + grant + scopes. REST audience knobase.management.rest or {origin}/api. MCP audience knobase.management.mcp or {origin}/api/mcp. Raw serving keys are never returned to REST or MCP. Setup tokens (kb_setup_…) cannot call serving or management paths. ## Auth Authorization: Bearer Writes require Idempotency-Key. PATCH requires If-Match or version. Workspace id is in the path or X-Knobase-Workspace-Id. Do not infer it from a serving key or JWT hint alone. Runtime authorization: verify token (Better Auth JWKS; HS256 only in automated tests) → load oauth_workspace_grant → current membership → RBAC ∩ scopes → audit. Tokens do not authorize by embedding workspace_ids. OAuth 2.1 AS is Better Auth mcp()+jwt()+cimd() at /api/auth/oauth2/*. PKCE S256 required for public clients. DCR is off. Consent requires an explicit workspace checkbox. Knobase does not default to the first membership. GET /oauth/authorize may 302 to /api/auth/oauth2/authorize. POST /oauth/token and /oauth/revoke return 410 and are not advertised in discovery. Agent Lab completes Authorization Code + PKCE on /api/auth/oauth2/*. HS256 /oauth/token issuance is gone. ## Implemented management endpoints - GET /v1/me - GET /v1/workspaces - GET /v1/workspaces/{workspace_id} - GET|POST /v1/workspaces/{workspace_id}/products - GET|PATCH /v1/workspaces/{workspace_id}/products/{id} - POST /v1/workspaces/{workspace_id}/products/{id}/archive - GET|POST /v1/workspaces/{workspace_id}/campaigns - GET|PATCH /v1/workspaces/{workspace_id}/campaigns/{id} - POST /v1/workspaces/{workspace_id}/campaigns/{id}/pause - POST /v1/workspaces/{workspace_id}/campaigns/{id}/resume - POST /v1/workspaces/{workspace_id}/campaigns/{id}/mark-ready - POST /v1/workspaces/{workspace_id}/campaigns/{id}/budget - POST /v1/workspaces/{workspace_id}/emergency-pause - GET /v1/workspaces/{workspace_id}/offers - GET /v1/workspaces/{workspace_id}/offers/{id} - GET|POST /v1/workspaces/{workspace_id}/apps - GET|PATCH /v1/workspaces/{workspace_id}/apps/{id} - GET /v1/workspaces/{workspace_id}/apps/{id}/keys - POST /v1/workspaces/{workspace_id}/apps/{id}/keys/rotate - GET|PATCH /v1/workspaces/{workspace_id}/apps/{id}/policy - GET /v1/workspaces/{workspace_id}/analytics/overview - GET /v1/workspaces/{workspace_id}/analytics/products - GET /v1/workspaces/{workspace_id}/analytics/campaigns - GET /v1/workspaces/{workspace_id}/analytics/offers - GET /v1/workspaces/{workspace_id}/requests - GET /v1/workspaces/{workspace_id}/decisions/{id} - GET|POST /v1/confirmations - GET /v1/confirmations/{id} - POST /v1/confirmations/{id}/approve (dashboard session only) - POST /v1/confirmations/{id}/reject (dashboard session only) - POST /api/mcp (canonical Streamable HTTP MCP; GET/DELETE rejected) GET /mcp is a marketing page only. ## MCP tools list_workspaces, get_me, get_workspace, list_products, get_product, create_product_draft, update_product, archive_product, list_campaigns, get_campaign, create_campaign_draft, update_campaign_draft, pause_campaign, resume_campaign, mark_campaign_ready, request_emergency_pause, change_campaign_budget, list_offers, get_offer, list_apps, get_app, create_app, update_app, get_analytics_overview, get_analytics_products, get_analytics_campaigns, get_analytics_offers, update_sensitive_policy, list_requests, get_decision, list_confirmations, get_confirmation, rotate_serving_key. Confirmation tools return confirmation_id only. There is no approve_confirmation tool. ## Campaign honesty mark-ready sets test_ready (internal compatibility may still store sandbox_ready) and returns live_delivery: false. Public copy is Test mode / Test-ready, never Sandbox. A Campaign requires at least one Product to create or mark test-ready. Production serving without a Campaign is rejected. There is no live activate. POST .../activate returns NOT_SUPPORTED. Offers are immutable snapshots created only after serve: true. No offer CRUD. No-fill decisions create no snapshot, redirect, or click. ## Confirmations Agents may create pending confirmations via REST or MCP. They cannot approve them. REST/MCP returns confirmation_required with confirmation_id, payload_hash, and approval_url. Humans approve once on /confirmations/{id} or the dashboard. The same OAuth/MCP token cannot self-approve. Confirmation list/get never expose raw serving keys or secrets. ## Unavailable to agents billing write, payout/tax/bank, member/role write, reviewer, integrity override, raw context, personalization/adult, live activate, mutable offer CRUD, serving-key-as-login, unauthenticated public draft create in production, self-approval. ## Roles Legacy member migrates to viewer, never campaign_manager. Viewer cannot create or modify campaigns.