{"openapi":"3.0.0","info":{"version":"1.0.0","title":"RevealUI API","description":"REST API for RevealUI application with OpenAPI 3.0 specification"},"servers":[{"url":"http://localhost:3004","description":"Production"}],"paths":{"/.well-known/agent.json":{"get":{"responses":{"200":{"description":"Agent card","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Platform-level agent card","tags":["a2a"]}},"/.well-known/agents/{id}/agent.json":{"get":{"responses":{"200":{"description":"Agent card","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid agent ID format","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Per-agent discovery card","tags":["a2a"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","description":"Agent ID"},"required":true,"description":"Agent ID"}]}},"/.well-known/marketplace.json":{"get":{"responses":{"200":{"description":"Marketplace metadata","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"string"},"platform":{"type":"string"},"registryUrl":{"type":"string"},"publishUrl":{"type":"string"},"revenueShare":{"type":"object","properties":{"platform":{"type":"number"},"developer":{"type":"number"}},"required":["platform","developer"]},"paymentMethods":{"type":"array","items":{"type":"string"}},"servers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"string"},"pricePerCallUsdc":{"type":"string"},"invokeUrl":{"type":"string"}},"required":["id","name","description","category","pricePerCallUsdc","invokeUrl"]}}},"required":["version","platform","registryUrl","publishUrl","revenueShare","paymentMethods","servers"]}}}}},"summary":"MCP Marketplace discovery metadata","tags":["a2a"]}},"/.well-known/payment-methods.json":{"get":{"responses":{"200":{"description":"Payment methods","content":{"application/json":{"schema":{}}}},"404":{"description":"x402 payments not enabled","content":{"application/json":{"schema":{}}}}},"summary":"x402 payment methods discovery","tags":["a2a"]}},"/.well-known/mcp.json":{"get":{"responses":{"200":{"description":"MCP server manifest","content":{"application/json":{"schema":{}}}}},"summary":"MCP server discovery manifest","tags":["a2a"]}},"/a2a/agents":{"get":{"responses":{"200":{"description":"Agent card list","content":{"application/json":{"schema":{"type":"object","properties":{"agents":{"type":"array","items":{}}},"required":["agents"]}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}}},"summary":"List all registered agents as A2A agent cards","tags":["a2a"]},"post":{"responses":{"201":{"description":"Agent registered","content":{"application/json":{"schema":{"type":"object","properties":{"card":{}},"required":["card"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"409":{"description":"Agent already registered","content":{"application/json":{"schema":{}}}}},"summary":"Register a new agent from an AgentDefinition","tags":["a2a"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/a2a/agents/{id}":{"get":{"responses":{"200":{"description":"Agent card","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid agent ID format","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a single agent card by ID","tags":["a2a"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","description":"Agent ID"},"required":true,"description":"Agent ID"}]},"put":{"responses":{"200":{"description":"Updated agent card","content":{"application/json":{"schema":{"type":"object","properties":{"card":{}},"required":["card"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Update an agent's mutable fields","tags":["a2a"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","description":"Agent ID"},"required":true,"description":"Agent ID"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"systemPrompt":{"type":"string"},"model":{"type":"string"},"temperature":{"type":"number"},"maxTokens":{"type":"number"},"capabilities":{}}}}}}},"delete":{"responses":{"200":{"description":"Agent retired","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Invalid agent ID format","content":{"application/json":{"schema":{}}}},"403":{"description":"Built-in agents cannot be retired or AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Retire (unregister) an agent","tags":["a2a"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","description":"Agent ID"},"required":true,"description":"Agent ID"}]}},"/a2a/agents/{id}/def":{"get":{"responses":{"200":{"description":"Agent definition","content":{"application/json":{"schema":{"type":"object","properties":{"def":{}},"required":["def"]}}}},"400":{"description":"Invalid agent ID format","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Get full agent definition (admin only)","tags":["a2a"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","description":"Agent ID"},"required":true,"description":"Agent ID"}]}},"/a2a/agents/{id}/tasks":{"get":{"responses":{"200":{"description":"Task history","content":{"application/json":{"schema":{"type":"object","properties":{"tasks":{"type":"array","items":{}}},"required":["tasks"]}}}},"400":{"description":"Invalid agent ID format","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}}},"summary":"Get task history for an agent","tags":["a2a"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","description":"Agent ID"},"required":true,"description":"Agent ID"}]}},"/a2a/stream/{taskId}":{"get":{"responses":{"200":{"description":"SSE event stream","content":{"text/event-stream":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}}},"summary":"SSE stream for a running task","tags":["a2a"],"parameters":[{"name":"taskId","in":"path","schema":{"type":"string","description":"Task ID"},"required":true,"description":"Task ID"}]}},"/a2a":{"post":{"responses":{"200":{"description":"JSON-RPC response","content":{"application/json":{"schema":{}}}},"400":{"description":"Parse error or invalid request","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}}},"summary":"A2A JSON-RPC dispatcher","tags":["a2a"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/health":{"get":{"responses":{"200":{"description":"Service is alive","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"timestamp":{"type":"string"},"version":{"type":"string"},"service":{"type":"string"},"uptime":{"type":"number"}},"required":["status","timestamp","version","service","uptime"]}}}}},"summary":"Liveness probe","description":"Instant response with no dependencies. Kubernetes/load balancers use this to decide whether to restart the pod.","tags":["health"]}},"/health/live":{"get":{"responses":{"200":{"description":"Service is alive","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"timestamp":{"type":"string"},"version":{"type":"string"},"service":{"type":"string"},"uptime":{"type":"number"}},"required":["status","timestamp","version","service","uptime"]}}}}},"summary":"Liveness probe (alias)","description":"Alias for the root liveness probe  -  used by Playwright smoke tests and some load balancer conventions.","tags":["health"]}},"/health/ready":{"get":{"responses":{"200":{"description":"Service is ready","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"timestamp":{"type":"string"},"uptime":{"type":"number"},"checks":{}},"required":["status","timestamp","uptime","checks"]}}}},"503":{"description":"Service is not ready","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"timestamp":{"type":"string"},"uptime":{"type":"number"},"checks":{}},"required":["status","timestamp","uptime","checks"]}}}}},"summary":"Readiness probe","description":"Runs all registered health checks. Returns 200 when ready to serve traffic, 503 when a critical check fails.","tags":["health"]}},"/health/metrics":{"get":{"responses":{"200":{"description":"Prometheus-compatible metrics in text/plain format"},"401":{"description":"Unauthorized  -  missing or invalid metrics secret"}},"summary":"Prometheus metrics","description":"Exposes all application metrics collected by the core MetricsCollector in Prometheus text format. Requires METRICS_SECRET or CRON_SECRET authentication.","tags":["health"]}},"/health/metrics/json":{"get":{"responses":{"200":{"description":"Metrics as JSON","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized  -  missing or invalid metrics secret"}},"summary":"Metrics (JSON)","description":"Metrics in JSON format  -  useful for internal dashboards and debugging. Requires METRICS_SECRET or CRON_SECRET authentication.","tags":["health"]}},"/api/errors":{"post":{"responses":{"202":{"description":"Error accepted for processing","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true}},"required":["success"]}}}},"400":{"description":"Invalid JSON or payload","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}},"403":{"description":"Forbidden  -  invalid or missing internal token","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Capture client-side error","description":"Accepts structured error payloads from admin client-side and any other app that cannot write to the DB directly. Requires X-Internal-Token header.","tags":["errors"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"level":{"type":"string","enum":["warn","error","fatal"],"default":"error"},"message":{"type":"string","maxLength":2000},"stack":{"type":"string","maxLength":10000},"app":{"type":"string","maxLength":50},"context":{"type":"string","maxLength":50},"environment":{"type":"string","maxLength":50},"url":{"type":"string","maxLength":2000},"requestId":{"type":"string","maxLength":255},"metadata":{"type":"object","additionalProperties":{}}},"required":["message","app"]}}}}}},"/api/gdpr/consent":{"get":{"responses":{"200":{"description":"List of user consents","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"consents":{"type":"array","items":{}}},"required":["success","consents"]}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"List all consents for the authenticated user","tags":["gdpr"]}},"/api/gdpr/consent/grant":{"post":{"responses":{"200":{"description":"Consent granted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"consent":{}},"required":["success","consent"]}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Grant consent for a specific type","tags":["gdpr"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["necessary","functional","analytics","marketing","personalization"]},"expiresIn":{"type":"integer","exclusiveMinimum":0}},"required":["type"]}}}}}},"/api/gdpr/consent/revoke":{"post":{"responses":{"200":{"description":"Consent revoked","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Invalid request or cannot revoke necessary consent","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Revoke consent for a specific type","tags":["gdpr"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"type":{}},"required":["type"]}}}}}},"/api/gdpr/consent/check/{type}":{"get":{"responses":{"200":{"description":"Consent check result","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"type":{"type":"string"},"granted":{"type":"boolean"}},"required":["success","type","granted"]}}}},"400":{"description":"Invalid consent type","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Check if a specific consent type is active","tags":["gdpr"],"parameters":[{"name":"type","in":"path","schema":{"type":"string","enum":["necessary","functional","analytics","marketing","personalization"],"example":"analytics"},"required":true,"example":"analytics"}]}},"/api/gdpr/deletion":{"post":{"responses":{"201":{"description":"Deletion request created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"request":{}},"required":["success","request"]}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Request data deletion (right to be forgotten)","tags":["gdpr"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"string","enum":["personal","sensitive","financial","health","behavioral"]}},"reason":{"type":"string","maxLength":1000}}}}}}},"get":{"responses":{"200":{"description":"List of deletion requests","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"requests":{"type":"array","items":{}}},"required":["success","requests"]}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"List the authenticated user's deletion requests","tags":["gdpr"]}},"/api/gdpr/deletion/{id}":{"get":{"responses":{"200":{"description":"Deletion request details","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"request":{}},"required":["success","request"]}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}},"404":{"description":"Deletion request not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Get a specific deletion request by ID","tags":["gdpr"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","example":"req_abc123"},"required":true,"example":"req_abc123"}]}},"/api/gdpr/admin/stats":{"get":{"responses":{"200":{"description":"Consent statistics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"stats":{}},"required":["success","stats"]}}}},"403":{"description":"Admin access required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Aggregate consent statistics (admin only)","tags":["gdpr"]}},"/api/logs":{"post":{"responses":{"202":{"description":"Log entry accepted","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"}},"required":["received"]}}}},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Forbidden  -  missing or invalid X-Internal-Token","content":{"application/json":{"schema":{}}}}},"summary":"Ingest a structured log entry","description":"Accepts warn/error/fatal log entries from apps that cannot write to the DB directly. Rate-limited.","tags":["observability"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"level":{"type":"string","enum":["warn","error","fatal"]},"message":{"type":"string","maxLength":2000},"app":{"type":"string","maxLength":50},"environment":{"type":"string","maxLength":50},"requestId":{"type":"string","maxLength":255},"data":{"type":"object","additionalProperties":{}}},"required":["level","message","app"]}}}}}},"/api/license/verify":{"post":{"responses":{"200":{"description":"License verification result","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean","description":"Whether the license is valid"},"reason":{"type":"string","enum":["valid","expired","revoked","support_expired","invalid","misconfigured"],"description":"Why the license is invalid or degraded. \"expired\": JWT past expiry or DB status expired. \"revoked\": explicitly revoked in the DB (chargeback, refund, cancellation). \"support_expired\": perpetual license with expired support contract (basic admin still valid, premium features downgraded). \"invalid\": bad signature or malformed JWT. \"misconfigured\": server public key not configured.","example":"revoked"},"tier":{"type":"string","enum":["free","pro","max","enterprise"],"description":"License tier","example":"pro"},"customerId":{"type":"string","nullable":true,"description":"Customer ID from the license","example":"cus_abc123"},"features":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Feature flags enabled by this license"},"maxSites":{"type":"number","nullable":true,"description":"Maximum sites allowed","example":5},"maxUsers":{"type":"number","nullable":true,"description":"Maximum users allowed","example":25},"expiresAt":{"type":"string","nullable":true,"description":"License expiration (ISO 8601)","example":"2027-02-16T00:00:00.000Z"},"supportExpiresAt":{"type":"string","nullable":true,"description":"Support contract expiration for perpetual licenses (ISO 8601)","example":"2027-04-03T00:00:00.000Z"},"supportExpired":{"type":"boolean","description":"Whether the support contract has expired (perpetual licenses only)","example":false}},"required":["valid","tier","customerId","features","maxSites","maxUsers","expiresAt"]}}}},"400":{"description":"Missing license key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Invalid license key"}},"required":["error"]}}}}},"summary":"Verify a license key","description":"Validates a JWT license key and returns the tier, features, and limits.","tags":["license"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"licenseKey":{"type":"string","minLength":1,"description":"JWT license key to verify","example":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."}},"required":["licenseKey"]}}}}}},"/api/license/generate":{"post":{"responses":{"201":{"description":"License key generated","content":{"application/json":{"schema":{"type":"object","properties":{"licenseKey":{"type":"string","description":"Signed JWT license key"},"tier":{"type":"string","enum":["pro","max","enterprise"],"description":"License tier"},"customerId":{"type":"string","description":"Customer ID"}},"required":["licenseKey","tier","customerId"]}}}},"401":{"description":"Unauthorized  -  missing or invalid admin API key","content":{"application/json":{"schema":{}}}},"500":{"description":"Server error  -  missing private key configuration","content":{"application/json":{"schema":{}}}}},"summary":"Generate a license key (admin only)","description":"Creates a signed JWT license key for a customer. Requires REVEALUI_LICENSE_PRIVATE_KEY and admin API key.","tags":["license"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tier":{"type":"string","enum":["pro","max","enterprise"],"description":"License tier to generate","example":"pro"},"customerId":{"type":"string","minLength":1,"description":"Stripe customer ID or internal customer identifier","example":"cus_abc123"},"domains":{"type":"array","items":{"type":"string","maxLength":253},"maxItems":100,"description":"Licensed domains (optional)","example":["example.com","app.example.com"]},"maxSites":{"type":"integer","exclusiveMinimum":0,"maximum":10000,"description":"Maximum sites (defaults: Pro=5, Enterprise=unlimited)","example":5},"maxUsers":{"type":"integer","exclusiveMinimum":0,"maximum":1000000,"description":"Maximum users (defaults: Pro=25, Enterprise=unlimited)","example":25},"expiresInDays":{"type":"integer","exclusiveMinimum":0,"maximum":3650,"description":"License duration in days (default: 365, max: 10 years)","example":365}},"required":["tier","customerId"]}}}}}},"/api/license/features":{"get":{"responses":{"200":{"description":"Feature comparison by tier","content":{"application/json":{"schema":{"type":"object","properties":{"free":{"type":"object","additionalProperties":{"type":"boolean"}},"pro":{"type":"object","additionalProperties":{"type":"boolean"}},"enterprise":{"type":"object","additionalProperties":{"type":"boolean"}}},"required":["free","pro","enterprise"]}}}}},"summary":"List features by tier","description":"Returns which features are available at each license tier.","tags":["license"]}},"/api/billing/checkout":{"post":{"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Stripe checkout URL to redirect to"}},"required":["url"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Create a checkout session","description":"Creates a Stripe checkout session for subscription purchase. Requires authentication.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"priceId":{"type":"string","minLength":1,"description":"Stripe price ID for the subscription","example":"price_abc123"},"tier":{"type":"string","enum":["pro","max","enterprise"],"description":"License tier (defaults to pro)","example":"pro"}}}}}}}},"/api/billing/portal":{"post":{"responses":{"200":{"description":"Portal session created","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Stripe billing portal URL"}},"required":["url"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Create a billing portal session","description":"Creates a Stripe billing portal session for subscription management.","tags":["billing"]}},"/api/billing/subscription":{"get":{"responses":{"200":{"description":"Current subscription status","content":{"application/json":{"schema":{"type":"object","properties":{"tier":{"type":"string","enum":["free","pro","max","enterprise"],"description":"Current license tier"},"status":{"type":"string","description":"License status","example":"active"},"expiresAt":{"type":"string","nullable":true,"description":"Expiration date (ISO 8601)"},"licenseKey":{"type":"string","nullable":true,"description":"JWT license key"},"graceUntil":{"type":"string","nullable":true,"description":"Grace period end date (ISO 8601), present during past_due"}},"required":["tier","status","expiresAt","licenseKey"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Get subscription status","description":"Returns the current user's license tier, status, and expiration.","tags":["billing"]}},"/api/billing/invoices":{"get":{"responses":{"200":{"description":"List of invoices","content":{"application/json":{"schema":{"type":"object","properties":{"invoices":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Stripe invoice ID","example":"in_abc123"},"number":{"type":"string","nullable":true,"description":"Invoice number","example":"INV-0001"},"status":{"type":"string","description":"Invoice status","example":"paid"},"amountDue":{"type":"number","description":"Amount due in cents","example":4900},"amountPaid":{"type":"number","description":"Amount paid in cents","example":4900},"currency":{"type":"string","description":"Currency code","example":"usd"},"created":{"type":"string","description":"Created date (ISO 8601)"},"periodStart":{"type":"string","description":"Billing period start (ISO 8601)"},"periodEnd":{"type":"string","description":"Billing period end (ISO 8601)"},"pdfUrl":{"type":"string","nullable":true,"description":"URL to download invoice PDF"},"hostedUrl":{"type":"string","nullable":true,"description":"URL to view invoice online"}},"required":["id","number","status","amountDue","amountPaid","currency","created","periodStart","periodEnd","pdfUrl","hostedUrl"]}},"hasMore":{"type":"boolean","description":"Whether more invoices exist"}},"required":["invoices","hasMore"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"List invoices","description":"Returns the current user's Stripe invoices with amounts, status, and PDF download links.","tags":["billing"],"parameters":[{"name":"limit","in":"query","schema":{"type":"string","description":"Max invoices to return (1-100, default 10)","example":"10"},"description":"Max invoices to return (1-100, default 10)","example":"10"},{"name":"starting_after","in":"query","schema":{"type":"string","description":"Cursor for pagination (Stripe invoice ID)","example":"in_abc"},"description":"Cursor for pagination (Stripe invoice ID)","example":"in_abc"}]}},"/api/billing/upgrade":{"post":{"responses":{"200":{"description":"Subscription upgraded  -  Stripe will fire customer.subscription.updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"subscriptionId":{"type":"string","description":"Stripe subscription ID that was updated"}},"required":["success","subscriptionId"]}}}},"400":{"description":"No active subscription or no billing account","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Upgrade subscription tier","description":"Upgrades an active subscription to a new price/tier mid-cycle. Prorations are created automatically. Requires an existing active subscription.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"priceId":{"type":"string","minLength":1,"description":"Stripe price ID for the target tier","example":"price_enterprise_monthly"},"targetTier":{"type":"string","enum":["pro","max","enterprise"],"description":"Tier to upgrade to","example":"max"}},"required":["targetTier"]}}}}}},"/api/billing/downgrade":{"post":{"responses":{"200":{"description":"Subscription scheduled for cancellation at end of billing period","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"effectiveAt":{"type":"string","description":"When the downgrade takes effect (ISO 8601)"}},"required":["success","effectiveAt"]}}}},"400":{"description":"No active subscription found","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Downgrade to free tier","description":"Cancels the active subscription at the end of the current billing period. The user retains Pro/Enterprise access until then.","tags":["billing"]}},"/api/billing/pause":{"post":{"responses":{"200":{"description":"Subscription paused","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"resumesAt":{"type":"string","nullable":true,"description":"When billing resumes (ISO 8601)"}},"required":["success","resumesAt"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Pause subscription","description":"Pauses billing for the current subscription. Access is retained during the pause period.","tags":["billing"]}},"/api/billing/resume":{"post":{"responses":{"200":{"description":"Subscription resumed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Resume subscription","description":"Resumes billing for a paused subscription.","tags":["billing"]}},"/api/billing/checkout-perpetual":{"post":{"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Create a perpetual license checkout session","description":"Creates a one-time Stripe payment session for a perpetual license. Includes 1 year of support. Requires authentication.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"priceId":{"type":"string","minLength":1,"description":"Stripe price ID for the perpetual license product","example":"price_pro_perpetual"},"tier":{"type":"string","enum":["pro","max","enterprise"],"description":"Perpetual license tier","example":"pro"},"githubUsername":{"type":"string","description":"GitHub username for revealui-pro team access provisioning","example":"octocat"}},"required":["tier"]}}}}}},"/api/billing/checkout-support-renewal":{"post":{"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}},"404":{"description":"No perpetual license found for this tier","content":{"application/json":{"schema":{}}}}},"summary":"Create a support renewal checkout session","description":"Creates a one-time Stripe payment session to renew the annual support contract on a perpetual license. Requires authentication and an existing perpetual license.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"priceId":{"type":"string","minLength":1,"description":"Stripe price ID for the support renewal product","example":"price_renewal_pro"},"tier":{"type":"string","enum":["pro","max","enterprise"],"description":"Perpetual license tier whose support to renew","example":"pro"}},"required":["tier"]}}}}}},"/api/billing/checkout-credits":{"post":{"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Create a credit bundle checkout session","description":"Creates a one-time Stripe payment session for an agent task credit bundle. Credits never expire and stack with the monthly tier allowance. Requires authentication.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"priceId":{"type":"string","minLength":1,"description":"Stripe price ID for the credit bundle product","example":"price_credits_standard"},"bundle":{"type":"string","enum":["starter","standard","scale"],"description":"Credit bundle name","example":"standard"}},"required":["bundle"]}}}}}},"/api/billing/credits":{"get":{"responses":{"200":{"description":"Credit balance","content":{"application/json":{"schema":{"type":"object","properties":{"balance":{"type":"number","description":"Remaining prepaid credits"},"totalPurchased":{"type":"number","description":"Lifetime credits purchased"}},"required":["balance","totalPurchased"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Get current credit balance","description":"Returns the authenticated user's prepaid agent task credit balance.","tags":["billing"]}},"/api/billing/usage":{"get":{"responses":{"200":{"description":"Current cycle usage","content":{"application/json":{"schema":{"type":"object","properties":{"used":{"type":"number","description":"Tasks executed this billing cycle"},"quota":{"type":"number","description":"Maximum tasks for this tier (-1 = unlimited)"},"overage":{"type":"number","description":"Tasks beyond the tier quota"},"cycleStart":{"type":"string","description":"Start of current billing cycle (ISO 8601)"},"resetAt":{"type":"string","description":"When the cycle resets (start of next month, ISO 8601)"}},"required":["used","quota","overage","cycleStart","resetAt"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Agent task usage","description":"Returns agent task usage for the current billing cycle.","tags":["billing"]}},"/api/billing/support-renewal-check":{"post":{"responses":{"200":{"description":"Reminders sent","content":{"application/json":{"schema":{"type":"object","properties":{"reminded":{"type":"number","description":"Number of reminder emails sent"}},"required":["reminded"]}}}},"403":{"description":"Invalid cron secret","content":{"application/json":{"schema":{}}}}},"summary":"Send support renewal reminders (internal cron)","description":"Finds perpetual licenses whose support contract expires within 30 days and sends reminder emails. Protected by X-Cron-Secret.","tags":["billing"]}},"/api/billing/report-agent-overage":{"post":{"responses":{"200":{"description":"Overage reported","content":{"application/json":{"schema":{"type":"object","properties":{"reported":{"type":"number"},"skipped":{"type":"number"}},"required":["reported","skipped"]}}}},"401":{"description":"Invalid cron secret","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Report agent task overage to Stripe (internal cron)","description":"Reads overage from the previous billing cycle and emits Stripe Billing Meter events. Protected by X-Cron-Secret.","tags":["billing"]}},"/api/billing/sweep-expired-licenses":{"post":{"responses":{"200":{"description":"Sweep complete","content":{"application/json":{"schema":{"type":"object","properties":{"expired":{"type":"number","description":"Number of licenses transitioned to expired"},"supportExpired":{"type":"number","description":"Number of perpetual licenses with newly expired support"}},"required":["expired","supportExpired"]}}}},"403":{"description":"Invalid cron secret","content":{"application/json":{"schema":{}}}}},"summary":"Sweep expired licenses (internal cron)","description":"Marks non-perpetual licenses whose expiresAt is in the past as expired, and perpetual licenses whose supportExpiresAt is in the past as support_expired. Clears caches so changes take effect immediately. Protected by X-Cron-Secret.","tags":["billing"]}},"/api/billing/refund":{"post":{"responses":{"200":{"description":"Refund created","content":{"application/json":{"schema":{"type":"object","properties":{"refundId":{"type":"string","description":"Stripe refund ID","example":"re_abc123"},"status":{"type":"string","description":"Refund status","example":"succeeded"},"amount":{"type":"number","description":"Amount refunded in cents","example":4900},"currency":{"type":"string","description":"Currency code","example":"usd"}},"required":["refundId","status","amount","currency"]}}}},"400":{"description":"Invalid request (missing payment reference)","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}},"403":{"description":"Admin access required","content":{"application/json":{"schema":{}}}}},"summary":"Issue a refund","description":"Creates a Stripe refund for a payment intent or charge. Admin-only. Full or partial refunds supported. License revocation is handled automatically by the charge.refunded webhook.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"paymentIntentId":{"type":"string","minLength":1,"description":"Stripe PaymentIntent ID to refund. Provide either this or chargeId.","example":"pi_abc123"},"chargeId":{"type":"string","minLength":1,"description":"Stripe Charge ID to refund. Provide either this or paymentIntentId.","example":"ch_abc123"},"amount":{"type":"integer","exclusiveMinimum":0,"description":"Amount to refund in cents. Omit for full refund.","example":4900},"reason":{"type":"string","enum":["duplicate","fraudulent","requested_by_customer"],"description":"Reason for the refund (Stripe enum)","example":"requested_by_customer"}}}}}}}},"/api/billing/metrics":{"get":{"responses":{"200":{"description":"Revenue metrics snapshot","content":{"application/json":{"schema":{"type":"object","properties":{"activeSubscriptions":{"type":"number","description":"Count of active subscriptions"},"totalCustomers":{"type":"number","description":"Count of unique Stripe customers"},"mrr":{"type":"number","description":"Estimated monthly recurring revenue in cents"},"tierBreakdown":{"type":"object","properties":{"pro":{"type":"number","description":"Active pro subscriptions"},"max":{"type":"number","description":"Active max subscriptions"},"enterprise":{"type":"number","description":"Active enterprise subscriptions"}},"required":["pro","max","enterprise"]},"recentEvents":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"Billing event type"},"tier":{"type":"string","description":"Associated tier (if determinable)"},"createdAt":{"type":"string","description":"When the event was processed (ISO 8601)"}},"required":["type","tier","createdAt"]}}},"required":["activeSubscriptions","totalCustomers","mrr","tierBreakdown","recentEvents"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}},"403":{"description":"Admin access required","content":{"application/json":{"schema":{}}}}},"summary":"Revenue metrics (admin)","description":"Returns aggregate revenue metrics for the admin dashboard. Requires admin or owner role.","tags":["billing"],"parameters":[{"name":"from","in":"query","schema":{"type":"string","format":"date-time","description":"Start of date range for recent events (ISO 8601). Defaults to 30 days ago."},"description":"Start of date range for recent events (ISO 8601). Defaults to 30 days ago."},{"name":"to","in":"query","schema":{"type":"string","format":"date-time","description":"End of date range for recent events (ISO 8601). Defaults to now."},"description":"End of date range for recent events (ISO 8601). Defaults to now."}]}},"/api/webhooks/stripe":{"post":{"responses":{"200":{"description":"Webhook event received and processed","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean","const":true},"duplicate":{"type":"boolean"}},"required":["received"]}}}},"400":{"description":"Missing signature or invalid webhook","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Webhook processing failed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Webhook service unavailable (Stripe env vars misconfigured)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Stripe webhook handler","description":"Receives Stripe webhook events for subscription lifecycle, license management, disputes, and refunds. Requires raw body access for signature verification.","tags":["webhooks"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"data":{"type":"object","properties":{"object":{}},"required":["object"]},"created":{"type":"number"},"livemode":{"type":"boolean"}},"required":["id","type","data","created","livemode"]}}}}}},"/api/provenance":{"get":{"responses":{"200":{"description":"Provenance list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CodeProvenance"}}},"required":["success","data"]}}}}},"summary":"List provenance entries","tags":["provenance"],"parameters":[{"name":"authorType","in":"query","schema":{"type":"string","example":"ai_generated"},"example":"ai_generated"},{"name":"reviewStatus","in":"query","schema":{"type":"string","example":"unreviewed"},"example":"unreviewed"},{"name":"filePathPrefix","in":"query","schema":{"type":"string","example":"packages/core"},"example":"packages/core"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"example":100},"example":100},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"example":0},"example":0}]},"post":{"responses":{"201":{"description":"Provenance entry created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/CodeProvenance"}},"required":["success","data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{}}}}},"summary":"Create a provenance entry","tags":["provenance"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"filePath":{"type":"string","minLength":1,"maxLength":1000},"authorType":{"type":"string","enum":["ai_generated","human_written","ai_assisted","mixed"]},"functionName":{"type":"string","maxLength":200},"lineStart":{"type":"integer","minimum":0},"lineEnd":{"type":"integer","minimum":0},"aiModel":{"type":"string"},"aiSessionId":{"type":"string"},"gitCommitHash":{"type":"string"},"gitAuthor":{"type":"string"},"confidence":{"type":"number","minimum":0,"maximum":1},"linesOfCode":{"type":"integer","minimum":0},"metadata":{"type":"object","additionalProperties":{}}},"required":["filePath","authorType"]}}}}}},"/api/provenance/stats":{"get":{"responses":{"200":{"description":"Provenance statistics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"byAuthorType":{"type":"array","items":{"type":"object","properties":{"authorType":{"type":"string"},"count":{"type":"number"},"totalLines":{"type":"number"}},"required":["authorType","count","totalLines"]}},"byReviewStatus":{"type":"array","items":{"type":"object","properties":{"reviewStatus":{"type":"string"},"count":{"type":"number"}},"required":["reviewStatus","count"]}}},"required":["byAuthorType","byReviewStatus"]}},"required":["success","data"]}}}}},"summary":"Get provenance statistics","tags":["provenance"]}},"/api/provenance/file/{filePath}":{"get":{"responses":{"200":{"description":"File provenance","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CodeProvenance"}}},"required":["success","data"]}}}}},"summary":"Get provenance for a specific file","tags":["provenance"],"parameters":[{"name":"filePath","in":"path","schema":{"type":"string","example":"packages/core/src/index.ts"},"required":true,"example":"packages/core/src/index.ts"}]}},"/api/provenance/{id}":{"get":{"responses":{"200":{"description":"Provenance entry found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/CodeProvenance"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Get a provenance entry by ID","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]},"patch":{"responses":{"200":{"description":"Provenance entry updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/CodeProvenance"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a provenance entry","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"filePath":{"type":"string","minLength":1,"maxLength":1000},"functionName":{"type":"string","maxLength":200,"nullable":true},"lineStart":{"type":"integer","minimum":0,"nullable":true},"lineEnd":{"type":"integer","minimum":0,"nullable":true},"authorType":{"type":"string","enum":["ai_generated","human_written","ai_assisted","mixed"]},"aiModel":{"type":"string","nullable":true},"aiSessionId":{"type":"string","nullable":true},"gitCommitHash":{"type":"string","nullable":true},"gitAuthor":{"type":"string","nullable":true},"confidence":{"type":"number","minimum":0,"maximum":1},"reviewStatus":{"type":"string","enum":["unreviewed","human_reviewed","ai_reviewed","human_and_ai_reviewed"]},"linesOfCode":{"type":"integer","minimum":0},"metadata":{"type":"object","additionalProperties":{}}}}}}}},"delete":{"responses":{"200":{"description":"Provenance entry deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}}},"summary":"Delete a provenance entry","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/provenance/{id}/review":{"post":{"responses":{"201":{"description":"Review added","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/CodeReview"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{}}}}},"summary":"Add a review to a provenance entry","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reviewType":{"type":"string","enum":["human_review","ai_review","human_approval","ai_suggestion"]},"status":{"type":"string","enum":["approved","rejected","needs_changes","informational"]},"reviewerId":{"type":"string"},"comment":{"type":"string"},"metadata":{"type":"object","additionalProperties":{}}},"required":["reviewType","status"]}}}}}},"/api/provenance/{id}/reviews":{"get":{"responses":{"200":{"description":"Review list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CodeReview"}}},"required":["success","data"]}}}}},"summary":"List reviews for a provenance entry","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/tickets/boards":{"get":{"responses":{"200":{"description":"Board list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Board"}}},"required":["success","data"]}}}}},"summary":"List all boards","tags":["boards"]},"post":{"responses":{"201":{"description":"Board created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Board"}},"required":["success","data"]}}}}},"summary":"Create a board","tags":["boards"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"slug":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":1000},"isDefault":{"type":"boolean"}},"required":["name","slug"]}}}}}},"/api/tickets/boards/{id}":{"get":{"responses":{"200":{"description":"Board found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Board"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Get a board by ID","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]},"patch":{"responses":{"200":{"description":"Board updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Board"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a board","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"slug":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":1000}}}}}}},"delete":{"responses":{"200":{"description":"Board deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}}},"summary":"Delete a board","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/tickets/boards/{boardId}/columns":{"get":{"responses":{"200":{"description":"Columns list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/BoardColumn"}}},"required":["success","data"]}}}}},"summary":"List columns for a board","tags":["boards"],"parameters":[{"name":"boardId","in":"path","schema":{"type":"string","example":"board-001"},"required":true,"example":"board-001"}]},"post":{"responses":{"201":{"description":"Column created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/BoardColumn"}},"required":["success","data"]}}}}},"summary":"Create a column","tags":["boards"],"parameters":[{"name":"boardId","in":"path","schema":{},"required":true,"example":"board-001"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"slug":{"type":"string","minLength":1,"maxLength":100},"position":{"type":"integer","minimum":0},"wipLimit":{"type":"integer","minimum":1},"color":{"type":"string","maxLength":20}},"required":["name","slug","position"]}}}}}},"/api/tickets/columns/{id}":{"patch":{"responses":{"200":{"description":"Column updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/BoardColumn"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Update a column","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"slug":{"type":"string","minLength":1,"maxLength":100},"position":{"type":"integer","minimum":0},"wipLimit":{"type":"integer","minimum":1,"nullable":true},"color":{"type":"string","maxLength":20,"nullable":true}}}}}}},"delete":{"responses":{"200":{"description":"Column deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}}},"summary":"Delete a column","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/tickets/boards/{boardId}/tickets":{"get":{"responses":{"200":{"description":"Ticket list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}}},"required":["success","data"]}}}}},"summary":"List tickets for a board","tags":["tickets"],"parameters":[{"name":"boardId","in":"path","schema":{"type":"string","example":"board-001"},"required":true,"example":"board-001"},{"name":"status","in":"query","schema":{"type":"string","enum":["open","in_progress","in_review","done","closed"],"example":"open"},"example":"open"},{"name":"priority","in":"query","schema":{"type":"string","enum":["urgent","high","medium","low"],"example":"high"},"example":"high"},{"name":"type","in":"query","schema":{"type":"string","enum":["task","bug","feature","improvement","epic"],"example":"task"},"example":"task"},{"name":"assigneeId","in":"query","schema":{"type":"string"}},{"name":"columnId","in":"query","schema":{"type":"string"}}]},"post":{"responses":{"201":{"description":"Ticket created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Ticket"}},"required":["success","data"]}}}}},"summary":"Create a ticket","tags":["tickets"],"parameters":[{"name":"boardId","in":"path","schema":{},"required":true,"example":"board-001"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"object","additionalProperties":{}},"columnId":{"type":"string"},"parentTicketId":{"type":"string"},"status":{"type":"string","enum":["open","in_progress","in_review","done","closed"]},"priority":{"type":"string","enum":["urgent","high","medium","low"]},"type":{"type":"string","enum":["task","bug","feature","improvement","epic"]},"assigneeId":{"type":"string"},"reporterId":{"type":"string"},"dueDate":{"type":"string","format":"date-time"},"estimatedEffort":{"type":"integer","minimum":0}},"required":["title"]}}}}}},"/api/tickets/tickets/{id}":{"get":{"responses":{"200":{"description":"Ticket found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Ticket"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Get a ticket by ID","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]},"patch":{"responses":{"200":{"description":"Ticket updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Ticket"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a ticket","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"object","additionalProperties":{}},"status":{"type":"string","enum":["open","in_progress","in_review","done","closed"]},"priority":{"type":"string","enum":["urgent","high","medium","low"]},"type":{"type":"string","enum":["task","bug","feature","improvement","epic"]},"assigneeId":{"type":"string","nullable":true},"reporterId":{"type":"string","nullable":true},"columnId":{"type":"string","nullable":true},"dueDate":{"type":"string","format":"date-time","nullable":true},"estimatedEffort":{"type":"integer","minimum":0,"nullable":true},"sortOrder":{"type":"number"}}}}}}},"delete":{"responses":{"200":{"description":"Ticket deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}}},"summary":"Delete a ticket","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/tickets/tickets/{id}/move":{"post":{"responses":{"200":{"description":"Ticket moved","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Ticket"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Move a ticket to a different column","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"columnId":{"type":"string"},"sortOrder":{"type":"integer","minimum":0}},"required":["columnId","sortOrder"]}}}}}},"/api/tickets/tickets/{id}/subtasks":{"get":{"responses":{"200":{"description":"Subtask list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}}},"required":["success","data"]}}}}},"summary":"Get subtasks for a ticket","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/tickets/tickets/{id}/comments":{"get":{"responses":{"200":{"description":"Comment list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/TicketComment"}}},"required":["success","data"]}}}}},"summary":"List comments for a ticket","tags":["comments"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]},"post":{"responses":{"201":{"description":"Comment created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/TicketComment"}},"required":["success","data"]}}}}},"summary":"Add a comment to a ticket","tags":["comments"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"object","additionalProperties":{}},"authorId":{"type":"string"}},"required":["body"]}}}}}},"/api/tickets/comments/{id}":{"patch":{"responses":{"200":{"description":"Comment updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/TicketComment"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Update a comment","tags":["comments"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"object","additionalProperties":{}}},"required":["body"]}}}}},"delete":{"responses":{"200":{"description":"Comment deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}}},"summary":"Delete a comment","tags":["comments"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/tickets/labels":{"get":{"responses":{"200":{"description":"Label list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/TicketLabel"}}},"required":["success","data"]}}}}},"summary":"List all labels","tags":["labels"]},"post":{"responses":{"201":{"description":"Label created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/TicketLabel"}},"required":["success","data"]}}}}},"summary":"Create a label","tags":["labels"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"slug":{"type":"string","minLength":1,"maxLength":100},"color":{"type":"string","maxLength":20},"description":{"type":"string","maxLength":500}},"required":["name","slug"]}}}}}},"/api/tickets/labels/{id}":{"patch":{"responses":{"200":{"description":"Label updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/TicketLabel"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Update a label","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"slug":{"type":"string","minLength":1,"maxLength":100},"color":{"type":"string","maxLength":20},"description":{"type":"string","maxLength":500}}}}}}},"delete":{"responses":{"200":{"description":"Label deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}}},"summary":"Delete a label","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/tickets/tickets/{id}/labels":{"post":{"responses":{"201":{"description":"Label assigned","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"id":{"type":"string"},"ticketId":{"type":"string"},"labelId":{"type":"string"}},"required":["id","ticketId","labelId"]}},"required":["success","data"]}}}}},"summary":"Assign a label to a ticket","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"labelId":{"type":"string"}},"required":["labelId"]}}}}},"get":{"responses":{"200":{"description":"Labels for ticket","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/TicketLabel"}}},"required":["success","data"]}}}}},"summary":"Get labels for a ticket","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/tickets/tickets/{id}/labels/{labelId}":{"delete":{"responses":{"200":{"description":"Label removed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}}},"summary":"Remove a label from a ticket","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true},{"name":"labelId","in":"path","schema":{"type":"string"},"required":true}]}},"/api/agent-tasks":{"post":{"responses":{"200":{"description":"Agent task completed within the sync/poll window","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"ticketId":{"type":"string"},"agentOutput":{"type":"string","nullable":true},"status":{"type":"string"},"jobId":{"type":"string"},"ticketNumber":{"type":"number"}},"required":["success","ticketId","agentOutput","status","ticketNumber"]}}}},"202":{"description":"Dispatch enqueued but still running at the poll-window timeout. Caller polls the statusUrl.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"ticketId":{"type":"string"},"ticketNumber":{"type":"number"},"jobId":{"type":"string"},"statusUrl":{"type":"string"},"message":{"type":"string"}},"required":["success","ticketId","jobId","statusUrl","message"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}}},"summary":"Submit a natural language task for an agent to execute","description":"Creates a ticket from the instruction, dispatches an AI agent with admin tools to resolve it, and returns the result. When durable dispatch is enabled and the agent takes longer than ~22 s, returns 202 with a jobId the caller can poll at /status.","tags":["agent-tasks"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"instruction":{"type":"string","minLength":1,"maxLength":2000,"example":"Publish the Q3 product launch blog post and update the homepage hero"},"boardId":{"type":"string","description":"Board to create the ticket on"},"priority":{"type":"string","enum":["low","medium","high","critical"],"default":"medium"}},"required":["instruction","boardId"]}}}}}},"/api/agent-tasks/{ticketId}/dispatch":{"post":{"responses":{"200":{"description":"Agent dispatch completed within the sync/poll window","content":{"application/json":{"schema":{"type":"object","properties":{"success":{},"ticketId":{},"agentOutput":{},"status":{},"jobId":{}},"required":["success","ticketId","agentOutput","status"]}}}},"202":{"description":"Dispatch enqueued but still running at the poll-window timeout","content":{"application/json":{"schema":{"type":"object","properties":{"success":{},"ticketId":{},"ticketNumber":{},"jobId":{},"statusUrl":{},"message":{}},"required":["success","ticketId","jobId","statusUrl","message"]}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"404":{"description":"Ticket not found","content":{"application/json":{"schema":{}}}}},"summary":"Dispatch an agent for an existing ticket","tags":["agent-tasks"],"parameters":[{"name":"ticketId","in":"path","schema":{"type":"string"},"required":true}]}},"/api/agent-tasks/{ticketId}/status":{"get":{"responses":{"200":{"description":"Dispatch status","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"ticketId":{"type":"string"},"jobId":{"type":"string","nullable":true},"status":{"type":"string","enum":["idle","pending","running","completed","failed"]},"output":{"type":"string","nullable":true},"error":{"type":"string","nullable":true},"attemptsMade":{"type":"number","nullable":true},"nextAttemptAt":{"type":"string","nullable":true}},"required":["success","ticketId","jobId","status","output","error","attemptsMade","nextAttemptAt"]}}}},"404":{"description":"Ticket not found","content":{"application/json":{"schema":{}}}}},"summary":"Fetch the canonical dispatch status for a ticket","description":"Returns the current state of the most recent dispatch job for a ticket. `status = idle` means no job was ever queued (legacy sync dispatch or ticket never dispatched). Safe to poll; returns 200 even when nothing is in flight.","tags":["agent-tasks"],"parameters":[{"name":"ticketId","in":"path","schema":{"type":"string"},"required":true}]}},"/api/agent-stream/elicit":{"post":{"responses":{"200":{"description":"Elicitation resolved","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true}},"required":["success"]}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}},"403":{"description":"Session belongs to a different user","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}},"404":{"description":"No pending elicitation matching the supplied ids","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Submit an elicitation response for an in-flight agent run","description":"Resolves a pending `elicitation/create` request issued by an MCP server during an agent-stream run. The client provides `{ sessionId, elicitationId, action, content? }`; the server maps the session to the pending handler promise and resolves it.","tags":["agent"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string","format":"uuid"},"elicitationId":{"type":"string","minLength":1,"maxLength":128},"action":{"type":"string","enum":["accept","decline","cancel"]},"content":{"type":"object","additionalProperties":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]}}},"required":["sessionId","elicitationId","action"]}}}}}},"/api/agent-stream":{"post":{"responses":{"200":{"description":"SSE stream of agent execution events (text/event-stream)"},"400":{"description":"Missing instruction or invalid provider","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"},"code":{"type":"string"}},"required":["success","error","code"]}}}}},"summary":"Stream agent execution via SSE","description":"Streams agent execution events in real-time using Server-Sent Events. Client-side: use fetch + ReadableStream (not EventSource  -  it does not support POST).","tags":["agent"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"instruction":{"type":"string"},"boardId":{"type":"string"},"workspaceId":{"type":"string"},"priority":{"type":"string"},"provider":{"type":"string"},"model":{"type":"string"},"mode":{"type":"string","enum":["admin","coding"],"default":"admin"}},"required":["instruction"]}}}}}},"/api/mcp/usage":{"get":{"responses":{"200":{"description":"Usage aggregations for the caller’s account","content":{"application/json":{"schema":{"type":"object","properties":{"range":{"type":"string","enum":["24h","7d","30d"],"default":"24h"},"since":{"type":"string"},"accountId":{"type":"string","nullable":true},"meters":{"type":"array","items":{"type":"object","properties":{"meterName":{"type":"string"},"total":{"type":"integer","minimum":0},"successCount":{"type":"integer","minimum":0},"errorCount":{"type":"integer","minimum":0},"unknownCount":{"type":"integer","minimum":0},"durationCount":{"type":"integer","minimum":0},"p50Ms":{"type":"number","nullable":true},"p95Ms":{"type":"number","nullable":true}},"required":["meterName","total","successCount","errorCount","unknownCount","durationCount","p50Ms","p95Ms"]}}},"required":["since","accountId","meters"]}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}},"409":{"description":"Caller has no resolvable account membership","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Aggregate MCP usage for the caller’s account","description":"Returns per-`meterName` totals, success / error / unknown counts (unknown = pre-A.3 row with NULL `errored`), duration counts, and p50 / p95 duration buckets in milliseconds. Filtered by the caller’s `accountId` (resolved from `entitlementMiddleware`) and the requested time range.","tags":["mcp"],"parameters":[{"name":"range","in":"query","schema":{}}]}},"/api/content/posts":{"get":{"responses":{"200":{"description":"Post list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Post"}},"totalDocs":{"type":"number"},"totalPages":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","totalDocs","totalPages","limit","offset"]}}}}},"summary":"List posts","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"status","in":"query","schema":{"type":"string","enum":["draft","published","archived"],"example":"published"},"example":"published"},{"name":"authorId","in":"query","schema":{"type":"string"}}]},"post":{"responses":{"201":{"description":"Post created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Post"}},"required":["success","data"]}}}},"400":{"description":"Content validation failed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"errors":{"type":"array","items":{"type":"string"}}},"required":["success"]}}}}},"summary":"Create a post","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"slug":{"type":"string","minLength":1,"maxLength":200},"excerpt":{"type":"string","maxLength":1000},"content":{},"featuredImageId":{"type":"string"},"authorId":{"type":"string"},"status":{"type":"string","enum":["draft","published","archived"]},"meta":{"type":"object","additionalProperties":{}},"categories":{"type":"array","items":{"type":"string"}}},"required":["title","slug"]}}}}}},"/api/content/posts/{id}":{"get":{"responses":{"200":{"description":"Post found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Post"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Get a post by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{"type":"string","example":"abc123"},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Post updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Post"}},"required":["success","data"]}}}},"400":{"description":"Content validation failed","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a post","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"slug":{},"excerpt":{"type":"string","maxLength":1000,"nullable":true},"content":{},"featuredImageId":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","published","archived"]},"published":{"type":"boolean"},"meta":{"type":"object","additionalProperties":{},"nullable":true},"categories":{"type":"array","items":{"type":"string"}},"publishedAt":{"type":"string","format":"date-time","nullable":true}}}}}}},"delete":{"responses":{"200":{"description":"Post deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a post","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/content/posts/slug/{slug}":{"get":{"responses":{"200":{"description":"Post found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Post"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a post by slug","tags":["content"],"parameters":[{"name":"slug","in":"path","schema":{"type":"string","example":"my-post"},"required":true,"example":"my-post"}]}},"/api/content/media":{"post":{"responses":{"201":{"description":"Media uploaded","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Media"}},"required":["success","data"]}}}},"400":{"description":"Invalid file","content":{"application/json":{"schema":{}}}},"413":{"description":"File too large","content":{"application/json":{"schema":{}}}}},"summary":"Upload a media file","tags":["content"],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"format":"binary"},"alt":{"type":"string","maxLength":500}}}}}}},"get":{"responses":{"200":{"description":"Media list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Media"}},"totalDocs":{"type":"number"},"totalPages":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","totalDocs","totalPages","limit","offset"]}}}}},"summary":"List media","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"mimeType","in":"query","schema":{"type":"string","example":"image"},"example":"image"}]}},"/api/content/media/{id}":{"get":{"responses":{"200":{"description":"Media found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Media"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a media item by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Media updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Media"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update media metadata","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"alt":{"type":"string","maxLength":500,"nullable":true},"focalPoint":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"],"nullable":true}}}}}}},"delete":{"responses":{"200":{"description":"Media deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a media item","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/content/sites":{"get":{"responses":{"200":{"description":"Site list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Site"}},"totalDocs":{"type":"number"},"totalPages":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","totalDocs","totalPages","limit","offset"]}}}}},"summary":"List sites","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"status","in":"query","schema":{"type":"string","enum":["draft","published","archived","maintenance"],"example":"published"},"example":"published"}]},"post":{"responses":{"201":{"description":"Site created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Site"}},"required":["success","data"]}}}}},"summary":"Create a site","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"slug":{},"description":{"type":"string","maxLength":1000},"status":{"type":"string","enum":["draft","published","archived","maintenance"]}},"required":["name","slug"]}}}}}},"/api/content/sites/{id}":{"get":{"responses":{"200":{"description":"Site found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Site"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a site by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Site updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Site"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a site","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"slug":{},"description":{"type":"string","maxLength":1000,"nullable":true},"status":{"type":"string","enum":["draft","published","archived","maintenance"]},"favicon":{"type":"string","nullable":true}}}}}}},"delete":{"responses":{"200":{"description":"Site deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a site","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/content/sites/{siteId}/pages":{"get":{"responses":{"200":{"description":"Page list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Page"}}},"required":["success","data"]}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{}}}}},"summary":"List pages for a site","tags":["content"],"parameters":[{"name":"siteId","in":"path","schema":{"type":"string","example":"site-abc"},"required":true,"example":"site-abc"},{"name":"status","in":"query","schema":{"type":"string","enum":["draft","published","scheduled","archived"],"example":"published"},"example":"published"}]},"post":{"responses":{"201":{"description":"Page created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Page"}},"required":["success","data"]}}}},"400":{"description":"Content validation failed","content":{"application/json":{"schema":{}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{}}}}},"summary":"Create a page","tags":["content"],"parameters":[{"name":"siteId","in":"path","schema":{},"required":true,"example":"site-abc"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"slug":{},"path":{"type":"string","minLength":1,"maxLength":500},"status":{"type":"string","enum":["draft","published","scheduled","archived"]},"parentId":{"type":"string"},"templateId":{"type":"string"},"blocks":{"type":"array","items":{}},"seo":{"type":"object","additionalProperties":{}}},"required":["title","slug","path"]}}}}}},"/api/content/pages/{id}":{"get":{"responses":{"200":{"description":"Page found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Page"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a page by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Page updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Page"}},"required":["success","data"]}}}},"400":{"description":"Content validation failed","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a page","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"slug":{},"path":{"type":"string","minLength":1,"maxLength":500},"status":{"type":"string","enum":["draft","published","scheduled","archived"]},"parentId":{"type":"string","nullable":true},"templateId":{"type":"string","nullable":true},"blocks":{"type":"array","items":{}},"seo":{"type":"object","additionalProperties":{},"nullable":true},"publishedAt":{"type":"string","format":"date-time","nullable":true}}}}}}},"delete":{"responses":{"200":{"description":"Page deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a page","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/content/search":{"get":{"responses":{"200":{"description":"Search results sorted by relevance","content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string"},"type":{"type":"string","enum":["posts","pages","all"]},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string","nullable":true},"slug":{"type":"string","nullable":true},"type":{"type":"string","enum":["post","page"]},"status":{"type":"string","nullable":true},"rank":{"type":"number"},"createdAt":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","title","slug","type","status","rank","createdAt"]}},"totalDocs":{"type":"number"},"totalPages":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["query","type","results","totalDocs","totalPages","limit","offset"]}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Full-text search across published content","description":"Uses PostgreSQL full-text search with plainto_tsquery. Searches published posts and/or pages.","tags":["content"],"parameters":[{"name":"q","in":"query","schema":{"type":"string","minLength":2,"maxLength":200},"required":true},{"name":"type","in":"query","schema":{"type":"string","enum":["posts","pages","all"],"default":"all"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}}]}},"/api/content/users":{"get":{"responses":{"200":{"description":"Paginated user list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/User"}},"docs":{"type":"array","items":{"$ref":"#/components/schemas/User"},"description":"Alias for data (admin dashboard compat)"},"totalDocs":{"type":"number"},"totalPages":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"pagingCounter":{"type":"number"},"hasPrevPage":{"type":"boolean"},"hasNextPage":{"type":"boolean"},"prevPage":{"type":"number","nullable":true},"nextPage":{"type":"number","nullable":true}},"required":["success","data","docs","totalDocs","totalPages","page","limit","pagingCounter","hasPrevPage","hasNextPage","prevPage","nextPage"]}}}}},"summary":"List users (admin-only)","tags":["content"],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":10}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"role","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}}]}},"/api/content/users/{id}":{"get":{"responses":{"200":{"description":"User found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/User"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a user by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"User updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/User"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a user","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"email":{"type":"string","format":"email"},"role":{"type":"string"},"status":{"type":"string"},"avatarUrl":{"type":"string","nullable":true}}}}}}},"delete":{"responses":{"200":{"description":"User deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a user (soft-delete)","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/content/products":{"get":{"responses":{"200":{"description":"Product list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Product"}},"totalDocs":{"type":"number"},"totalPages":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","totalDocs","totalPages","limit","offset"]}}}}},"summary":"List products","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"status","in":"query","schema":{"type":"string","enum":["draft","published","archived"],"example":"published"},"example":"published"}]},"post":{"responses":{"201":{"description":"Product created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Product"}},"required":["success","data"]}}}}},"summary":"Create a product","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"slug":{},"description":{"type":"string","maxLength":2000},"priceInCents":{"type":"integer","minimum":0},"currency":{"type":"string"},"stripeProductId":{"type":"string"},"stripePriceId":{"type":"string"},"active":{"type":"boolean"},"status":{"type":"string","enum":["draft","published","archived"]},"images":{"type":"array","items":{"type":"string"}},"metadata":{"type":"object","additionalProperties":{}}},"required":["title","slug"]}}}}}},"/api/content/products/{id}":{"get":{"responses":{"200":{"description":"Product found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Product"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a product by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Product updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Product"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a product","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"slug":{},"description":{"type":"string","maxLength":2000,"nullable":true},"priceInCents":{"type":"integer","minimum":0,"nullable":true},"currency":{"type":"string"},"stripeProductId":{"type":"string","nullable":true},"stripePriceId":{"type":"string","nullable":true},"active":{"type":"boolean"},"status":{"type":"string","enum":["draft","published","archived"]},"images":{"type":"array","items":{"type":"string"},"nullable":true},"metadata":{"type":"object","additionalProperties":{},"nullable":true}}}}}}},"delete":{"responses":{"200":{"description":"Product deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"message":{"type":"string"}},"required":["success","message"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a product","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/content/orders":{"get":{"responses":{"200":{"description":"Order list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"totalDocs":{"type":"number"},"totalPages":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","totalDocs","totalPages","limit","offset"]}}}}},"summary":"List orders","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"]}}]},"post":{"responses":{"201":{"description":"Order created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Order"}},"required":["success","data"]}}}}},"summary":"Create an order","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{},"minItems":1,"maxItems":100},"currency":{"type":"string"},"shippingAddress":{"type":"object","additionalProperties":{}},"metadata":{"type":"object","additionalProperties":{}}},"required":["items"]}}}}}},"/api/content/orders/{id}":{"get":{"responses":{"200":{"description":"Order found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Order"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get an order by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Order updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Order"}},"required":["success","data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update order status","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"]},"metadata":{"type":"object","additionalProperties":{},"nullable":true}},"required":["status"]}}}}}},"/api/content/batch/create":{"post":{"responses":{"200":{"description":"Batch create results","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["created","updated","deleted","error"]},"error":{"type":"string"}},"required":["id","status"]}}},"required":["success","results"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}}},"summary":"Batch create items in a collection","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"collection":{"type":"string","example":"posts"},"items":{"type":"array","items":{"type":"object","additionalProperties":{}},"minItems":1}},"required":["collection","items"]}}}}}},"/api/content/batch/update":{"post":{"responses":{"200":{"description":"Batch update results","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{}}}}},"summary":"Batch update items in a collection","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"collection":{"type":"string","example":"posts"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"minItems":1}},"required":["collection","items"]}}}}}},"/api/content/batch/delete":{"post":{"responses":{"200":{"description":"Batch delete results","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{}}}}},"summary":"Batch delete items in a collection","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"collection":{"type":"string","example":"posts"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"minItems":1}},"required":["collection","items"]}}}}}},"/api/content/export/{collection}":{"get":{"responses":{"200":{"description":"Export data","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"collection":{"type":"string"},"count":{"type":"number"},"data":{"type":"array","items":{"type":"object","additionalProperties":{}}}},"required":["success","collection","count","data"]}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Invalid collection","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}},"403":{"description":"Admin access required","content":{"application/json":{"schema":{}}}}},"summary":"Export collection data as JSON or CSV","description":"Admin-only bulk export endpoint. Supported collections: posts, pages, users, sites, media. Limited to 10,000 rows per request.","tags":["content"],"parameters":[{"name":"collection","in":"path","schema":{"type":"string","example":"posts"},"required":true,"example":"posts"},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv"],"default":"json"}},{"name":"status","in":"query","schema":{"type":"string"}}]}},"/api/rag/workspaces/{workspaceId}/index/{collection}":{"post":{"responses":{"200":{"description":"Indexing completed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"collection":{"type":"string"},"workspaceId":{"type":"string"},"total":{"type":"number"},"indexed":{"type":"number"},"failed":{"type":"number"},"status":{"type":"string"}},"required":["success","jobId","collection","workspaceId","total","indexed","failed","status"]}}}},"400":{"description":"Invalid collection name","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"502":{"description":"Admin fetch error","content":{"application/json":{"schema":{}}}}},"summary":"Trigger RAG indexing for an admin collection","tags":["rag"],"parameters":[{"name":"workspaceId","in":"path","schema":{"type":"string","description":"Workspace ID"},"required":true,"description":"Workspace ID"},{"name":"collection","in":"path","schema":{"type":"string","description":"Admin collection name"},"required":true,"description":"Admin collection name"}]}},"/api/rag/workspaces/{workspaceId}/documents":{"get":{"responses":{"200":{"description":"Document list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"documents":{"type":"array","items":{}},"total":{"type":"number"}},"required":["success","documents","total"]}}}}},"summary":"List documents in a workspace","tags":["rag"],"parameters":[{"name":"workspaceId","in":"path","schema":{"type":"string","description":"Workspace ID"},"required":true,"description":"Workspace ID"}]}},"/api/rag/workspaces/{workspaceId}/documents/{documentId}":{"delete":{"responses":{"200":{"description":"Document deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"documentId":{"type":"string"}},"required":["success","documentId"]}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}}},"summary":"Delete a RAG document","tags":["rag"],"parameters":[{"name":"workspaceId","in":"path","schema":{"type":"string","description":"Workspace ID"},"required":true,"description":"Workspace ID"},{"name":"documentId","in":"path","schema":{"type":"string","description":"Document ID"},"required":true,"description":"Document ID"}]}},"/api/rag/workspaces/{workspaceId}/status":{"get":{"responses":{"200":{"description":"Workspace RAG status","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"workspaceId":{"type":"string"},"totalDocuments":{"type":"number"},"indexedDocuments":{"type":"number"},"pendingDocuments":{"type":"number"},"lastIndexedAt":{"type":"string","nullable":true}},"required":["success","workspaceId","totalDocuments","indexedDocuments","pendingDocuments","lastIndexedAt"]}}}}},"summary":"Get workspace RAG indexing status","tags":["rag"],"parameters":[{"name":"workspaceId","in":"path","schema":{"type":"string","description":"Workspace ID"},"required":true,"description":"Workspace ID"}]}},"/api/admin/logs":{"get":{"responses":{"200":{"description":"Paginated app logs","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"timestamp":{"type":"string"},"level":{"type":"string"},"message":{"type":"string"},"app":{"type":"string"},"environment":{"type":"string"},"requestId":{"type":"string","nullable":true},"userId":{"type":"string","nullable":true},"data":{"nullable":true}},"required":["id","timestamp","level","message","app","environment","requestId","userId","data"]}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","total","limit","offset"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List application logs (admin-only)","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"app","in":"query","schema":{"type":"string"}},{"name":"level","in":"query","schema":{"type":"string"}}]}},"/api/admin/errors":{"get":{"responses":{"200":{"description":"Paginated error events","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"timestamp":{"type":"string"},"level":{"type":"string"},"message":{"type":"string"},"stack":{"type":"string","nullable":true},"app":{"type":"string"},"context":{"type":"string","nullable":true},"environment":{"type":"string"},"url":{"type":"string","nullable":true},"userId":{"type":"string","nullable":true},"requestId":{"type":"string","nullable":true},"metadata":{"nullable":true}},"required":["id","timestamp","level","message","stack","app","context","environment","url","userId","requestId","metadata"]}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","total","limit","offset"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List error events (admin-only)","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}}]}},"/api/admin/audit":{"get":{"responses":{"200":{"description":"Paginated audit log entries","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"timestamp":{"type":"string"},"eventType":{"type":"string"},"severity":{"type":"string"},"agentId":{"type":"string"},"taskId":{"type":"string","nullable":true},"sessionId":{"type":"string","nullable":true},"payload":{},"policyViolations":{"type":"array","items":{"type":"string"}}},"required":["id","timestamp","eventType","severity","agentId","taskId","sessionId","payload","policyViolations"]}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","total","limit","offset"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List audit log entries (admin-only)","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"severity","in":"query","schema":{"type":"string"}},{"name":"agentId","in":"query","schema":{"type":"string"}},{"name":"eventType","in":"query","schema":{"type":"string"}},{"name":"dateFrom","in":"query","schema":{"type":"string","format":"date-time","description":"ISO 8601 lower bound (inclusive) on `timestamp`."},"description":"ISO 8601 lower bound (inclusive) on `timestamp`."},{"name":"dateTo","in":"query","schema":{"type":"string","format":"date-time","description":"ISO 8601 upper bound (inclusive) on `timestamp`."},"description":"ISO 8601 upper bound (inclusive) on `timestamp`."},{"name":"policyViolationId","in":"query","schema":{"type":"string","description":"Match entries whose `policy_violations` JSONB array contains this string. Useful for scoping to a single rule's violations."},"description":"Match entries whose `policy_violations` JSONB array contains this string. Useful for scoping to a single rule's violations."}]}},"/api/admin/webhooks":{"get":{"responses":{"200":{"description":"Paginated webhook events","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"eventType":{"type":"string"},"processedAt":{"type":"string"}},"required":["id","eventType","processedAt"]}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","total","limit","offset"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List processed webhook events (admin-only)","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"eventType","in":"query","schema":{"type":"string"}}]}},"/api/admin/jobs":{"get":{"responses":{"200":{"description":"Paginated jobs","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"state":{"type":"string"},"priority":{"type":"number"},"retryCount":{"type":"number"},"retryLimit":{"type":"number"},"lastError":{"type":"string","nullable":true},"lockedBy":{"type":"string","nullable":true},"lockedUntil":{"type":"string","nullable":true},"startAfter":{"type":"string"},"createdAt":{"type":"string"},"startedAt":{"type":"string","nullable":true},"completedAt":{"type":"string","nullable":true},"output":{"nullable":true},"data":{}},"required":["id","name","state","priority","retryCount","retryLimit","lastError","lockedBy","lockedUntil","startAfter","createdAt","startedAt","completedAt","output","data"]}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["success","data","total","limit","offset"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List durable-queue jobs (admin-only)","description":"Paginated view of the `jobs` table. Filterable by state (created/active/completed/failed/retry) and by handler name. Ordered newest-created first.","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"state","in":"query","schema":{"type":"string","enum":["created","active","completed","failed","retry"]}},{"name":"name","in":"query","schema":{"type":"string"}}]}},"/api/admin/jobs/summary":{"get":{"responses":{"200":{"description":"Queue summary","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"stateCounts":{"type":"object","properties":{"created":{"type":"number"},"active":{"type":"number"},"completed":{"type":"number"},"failed":{"type":"number"},"retry":{"type":"number"}},"required":["created","active","completed","failed","retry"]},"byHandler24h":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"completed":{"type":"number"},"failed":{"type":"number"},"running":{"type":"number"}},"required":["name","completed","failed","running"]}},"recentFailures":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"lastError":{"type":"string","nullable":true},"retryCount":{"type":"number"},"completedAt":{"type":"string","nullable":true}},"required":["id","name","lastError","retryCount","completedAt"]}},"timestamp":{"type":"string"}},"required":["success","stateCounts","byHandler24h","recentFailures","timestamp"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"Durable-queue aggregate stats (admin-only)","description":"Returns: current depth by state, per-handler counts over the last 24 hours (completed / failed / running), and the 10 most-recent failures. Intended for the admin jobs dashboard header.","tags":["admin","observability"]}},"/api/admin/inference/config":{"get":{"responses":{"200":{"description":"Config (per-site) or system default","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"workspaceId":{"type":"string"},"source":{"type":"string","enum":["configured","default"]},"provider":{"type":"string","enum":["groq","huggingface","inference-snaps","ollama"]},"model":{"type":"string","nullable":true},"baseURL":{"type":"string","nullable":true},"temperature":{"type":"number","nullable":true},"maxTokens":{"type":"number","nullable":true},"keyHint":{"type":"string","nullable":true},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true}},"required":["workspaceId","source","provider","model","baseURL","temperature","maxTokens","keyHint","createdAt","updatedAt"]}},"required":["success","data"]}}}}},"summary":"Read per-site inference config (Max tier)","tags":["admin","inference"],"parameters":[{"name":"workspaceId","in":"query","schema":{"type":"string","minLength":1},"required":true}]},"put":{"responses":{"200":{"description":"Config saved","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{}},"required":["success","data"]}}}}},"summary":"Upsert per-site inference config (Max tier)","tags":["admin","inference"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"workspaceId":{"type":"string","minLength":1},"provider":{"type":"string","enum":["groq","huggingface","inference-snaps","ollama"]},"apiKey":{"type":"string","minLength":1,"maxLength":4096},"model":{"type":"string","maxLength":120},"baseURL":{"type":"string","format":"uri"},"temperature":{"type":"number","minimum":0,"maximum":2},"maxTokens":{"type":"integer","exclusiveMinimum":0,"maximum":1000000}},"required":["workspaceId","provider"]}}}}},"delete":{"responses":{"200":{"description":"Config deleted; default returned","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{}},"required":["success","data"]}}}}},"summary":"Revert site to system default inference (Max tier)","tags":["admin","inference"],"parameters":[{"name":"workspaceId","in":"query","schema":{"type":"string","minLength":1},"required":true}]}},"/api/admin/coordination/sessions":{"get":{"responses":{"200":{"description":"Paginated coordination sessions","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"agentId":{"type":"string"},"agentName":{"type":"string","nullable":true},"env":{"type":"string","nullable":true},"task":{"type":"string"},"status":{"type":"string","enum":["active","ended","crashed"]},"pid":{"type":"integer","nullable":true},"startedAt":{"type":"string"},"endedAt":{"type":"string","nullable":true},"lastSeen":{"type":"string","nullable":true},"ageSeconds":{"type":"integer"},"isStale":{"type":"boolean"},"tools":{"type":"object","additionalProperties":{"type":"number"},"nullable":true}},"required":["id","agentId","agentName","env","task","status","pid","startedAt","endedAt","lastSeen","ageSeconds","isStale","tools"]}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"},"timestamp":{"type":"string"}},"required":["success","data","total","limit","offset","timestamp"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":false},"error":{"type":"string"}},"required":["success","error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List coordination sessions across the agent fleet (admin-only)","description":"Returns sessions from the Neon coordination_sessions table joined with agent info. Default scope is \"active\" (sessions with ended_at IS NULL). Empty result when no daemon writes have landed yet — the surface is intentionally tolerant of the no-data case so admins can deploy this before any daemon is configured.","tags":["admin","coordination"],"parameters":[{"name":"scope","in":"query","schema":{"type":"string","enum":["active","all"],"default":"active"}},{"name":"agentId","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":100}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}}]}},"/api/analytics/summary":{"get":{"responses":{"200":{"description":"Aggregated metrics for the period","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"accountId":{"type":"string"},"periodStartIso":{"type":"string"},"periodEndIso":{"type":"string"},"days":{"type":"number"},"totalEvents":{"type":"number"},"erroredEvents":{"type":"number"},"successRate":{"type":"number"},"totalDurationMs":{"type":"number"},"averageDurationMs":{"type":"number"},"uniqueMeters":{"type":"number"}},"required":["accountId","periodStartIso","periodEndIso","days","totalEvents","erroredEvents","successRate","totalDurationMs","averageDurationMs","uniqueMeters"]}},"required":["success","data"]}}}}},"summary":"Period totals for the authenticated user account","tags":["Analytics"],"parameters":[{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":30}}]}},"/api/analytics/by-meter":{"get":{"responses":{"200":{"description":"Breakdown by meter name, sorted by count desc","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"accountId":{"type":"string"},"days":{"type":"number"},"meters":{"type":"array","items":{"type":"object","properties":{"meter":{"type":"string"},"count":{"type":"number"},"errored":{"type":"number"},"successRate":{"type":"number"},"totalDurationMs":{"type":"number"},"averageDurationMs":{"type":"number"}},"required":["meter","count","errored","successRate","totalDurationMs","averageDurationMs"]}}},"required":["success","accountId","days","meters"]}}}}},"summary":"Per-meter breakdown for the authenticated user account","tags":["Analytics"],"parameters":[{"name":"days","in":"query","schema":{}}]}},"/api/analytics/by-source":{"get":{"responses":{"200":{"description":"Breakdown by source (system|user|agent|api), sorted by count desc","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"accountId":{"type":"string"},"days":{"type":"number"},"sources":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"count":{"type":"number"},"errored":{"type":"number"},"successRate":{"type":"number"},"totalDurationMs":{"type":"number"},"averageDurationMs":{"type":"number"}},"required":["source","count","errored","successRate","totalDurationMs","averageDurationMs"]}}},"required":["success","accountId","days","sources"]}}}}},"summary":"Per-source breakdown for the authenticated user account","tags":["Analytics"],"parameters":[{"name":"days","in":"query","schema":{}}]}},"/api/devkit/profiles":{"get":{"responses":{"200":{"description":"Profile metadata for all five available profiles","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"profiles":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["revealui","agents","claude","cursor","zed"]},"label":{"type":"string"},"description":{"type":"string"},"kind":{"type":"string","enum":["native","agent-skills","external-editor"]},"recommended":{"type":"boolean"}},"required":["id","label","description","kind"]}}},"required":["success","profiles"]}}}}},"summary":"List available DevKit profiles","tags":["DevKit"]}},"/api/devkit/profile/active":{"get":{"responses":{"200":{"description":"User selection (or null if unset)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"profileId":{"type":"string","enum":["revealui","agents","claude","cursor","zed"],"nullable":true}},"required":["profileId"]}},"required":["success","data"]}}}}},"summary":"Read the user's active DevKit profile","tags":["DevKit"]},"put":{"responses":{"200":{"description":"Profile selection saved","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"data":{}},"required":["success","data"]}}}}},"summary":"Set the user's active DevKit profile (Max tier)","tags":["DevKit"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"profileId":{"type":"string","enum":["revealui","agents","claude","cursor","zed"],"nullable":true}},"required":["profileId"]}}}}}},"/api/rotation/history":{"get":{"responses":{"200":{"description":"Credential events for the authenticated user, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","const":true},"days":{"type":"number"},"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"timestamp":{"type":"string"},"eventType":{"type":"string","enum":["credential:created","credential:rotated","credential:revoked"]},"credentialKind":{"type":"string"},"credentialId":{"type":"string"},"provider":{"type":"string"},"label":{"type":"string","nullable":true}},"required":["id","timestamp","eventType","credentialKind","credentialId","provider","label"]}}},"required":["success","days","entries"]}}}}},"summary":"Read the user's credential lifecycle history","tags":["Rotation"],"parameters":[{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":30}},{"name":"kind","in":"query","schema":{"type":"string","enum":["user_api_key"]}}]}},"/api/api-keys":{"post":{"responses":{"201":{"description":"Key stored successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"keyHint":{"type":"string","nullable":true}},"required":["id","keyHint"]}}}}},"summary":"Store an encrypted API key","tags":["API Keys"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string","enum":["groq","huggingface","inference-snaps","ollama"],"description":"LLM provider for this key","example":"ollama"},"apiKey":{"type":"string","minLength":8,"description":"The plaintext API key (never stored; encrypted before persisting)","example":"tok-..."},"label":{"type":"string","maxLength":80,"description":"Optional user-visible label for this key","example":"My inference endpoint key"},"setAsDefault":{"type":"boolean","description":"Set this provider as the default for the user's agents","example":true},"model":{"type":"string","description":"Preferred model for the default provider config","example":"claude-sonnet-4-6"}},"required":["provider","apiKey"]}}}}},"get":{"responses":{"200":{"description":"List of key summaries","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"keyHint":{"type":"string","nullable":true},"label":{"type":"string","nullable":true},"createdAt":{"type":"string"},"lastUsedAt":{"type":"string","nullable":true}},"required":["id","provider","keyHint","label","createdAt","lastUsedAt"]}}},"required":["keys"]}}}}},"summary":"List stored API keys (hints only, never plaintext)","tags":["API Keys"]}},"/api/api-keys/:id":{"delete":{"responses":{"200":{"description":"Key deleted","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}},"required":["deleted"]}}}},"404":{"description":"Key not found"}},"summary":"Delete a stored API key","tags":["API Keys"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}]}},"/api/api-keys/:id/rotate":{"post":{"responses":{"200":{"description":"Key rotated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"keyHint":{"type":"string","nullable":true}},"required":["id","keyHint"]}}}},"404":{"description":"Key not found"}},"summary":"Replace the plaintext for an existing API key slot","tags":["API Keys"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string","minLength":8,"description":"The new plaintext API key"}},"required":["apiKey"]}}}}}},"/api/ghcr/verify":{"post":{"responses":{"200":{"description":"Pull allowed","content":{"application/json":{"schema":{"type":"object","properties":{"allowed":{"type":"boolean","const":true},"tier":{"type":"string"},"accountId":{"type":"string"}},"required":["allowed","tier","accountId"]}}}},"401":{"description":"Missing or invalid webhook secret","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Pull denied  -  no valid entitlement","content":{"application/json":{"schema":{"type":"object","properties":{"allowed":{"type":"boolean","const":false},"reason":{"type":"string"}},"required":["allowed","reason"]}}}}},"summary":"Verify license for GHCR image pull","description":"Called by GitHub Packages webhook on Docker image pull. Validates the license key against account entitlements.","tags":["ghcr"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"licenseKey":{"type":"string","minLength":1},"image":{"type":"string"}},"required":["licenseKey"]}}}}}},"/api/ghcr/status":{"get":{"responses":{"200":{"description":"Access status","content":{"application/json":{"schema":{"type":"object","properties":{"hasAccess":{"type":"boolean"},"tier":{"type":"string"},"accountId":{"type":"string"}},"required":["hasAccess"]}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Check GHCR access status for authenticated user","description":"Returns whether the authenticated user has GHCR pull access.","tags":["ghcr"]}},"/api/maintenance/cleanup-orphans":{"post":{"responses":{"200":{"description":"Cleanup completed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"agentMemoriesDeleted":{"type":"number","description":"Number of orphaned agent memories deleted"},"ragDocumentsDeleted":{"type":"number","description":"Number of orphaned RAG documents deleted"},"ragChunksDeleted":{"type":"number","description":"Number of orphaned RAG chunks deleted"},"deletedSiteIds":{"type":"array","items":{"type":"string"},"description":"Site IDs whose orphaned data was cleaned up"},"dryRun":{"type":"boolean","description":"Whether this was a dry-run (no actual deletions)"}},"required":["agentMemoriesDeleted","ragDocumentsDeleted","ragChunksDeleted","deletedSiteIds","dryRun"]}}}},"403":{"description":"Invalid cron secret","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Cleanup failed","content":{"application/json":{"schema":{}}}}},"summary":"Clean up orphaned vector data (internal cron)","description":"Removes orphaned Supabase vector data (agent memories, RAG documents, RAG chunks) for sites that have been soft-deleted in NeonDB. Protected by X-Cron-Secret.","tags":["maintenance"]}},"/api/marketplace/servers":{"get":{"responses":{"200":{"description":"List of active servers","content":{"application/json":{"schema":{"type":"object","properties":{"servers":{"type":"array","items":{}},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["servers","limit","offset"]}}}}},"summary":"List active marketplace servers","tags":["marketplace"],"parameters":[{"name":"category","in":"query","schema":{"type":"string","enum":["coding","data","productivity","analysis","writing","other"]}},{"name":"limit","in":"query","schema":{"type":"string"}},{"name":"offset","in":"query","schema":{"type":"string"}}]},"post":{"responses":{"201":{"description":"Server published","content":{"application/json":{"schema":{"type":"object","properties":{"server":{}},"required":["server"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"issues":{}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"422":{"description":"Invalid URL","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Publish a new MCP server","tags":["marketplace"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":3,"maxLength":80},"description":{"type":"string","minLength":10,"maxLength":500},"url":{"type":"string","format":"uri"},"category":{"type":"string","enum":["coding","data","productivity","analysis","writing","other"],"default":"other"},"tags":{"type":"array","items":{"type":"string","maxLength":30},"maxItems":10,"default":[]},"pricePerCallUsdc":{"type":"string","default":"0.001"},"metadata":{"type":"object","additionalProperties":{},"default":{}}},"required":["name","description","url"]}}}}}},"/api/marketplace/servers/{id}":{"get":{"responses":{"200":{"description":"Server detail","content":{"application/json":{"schema":{"type":"object","properties":{"server":{}},"required":["server"]}}}},"400":{"description":"Invalid server ID","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Get single server detail","tags":["marketplace"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}]},"delete":{"responses":{"200":{"description":"Server unpublished","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Invalid server ID","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Unpublish own server","tags":["marketplace"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}]}},"/api/marketplace/servers/{id}/invoke":{"post":{"responses":{"200":{"description":"Proxied response from MCP server","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"402":{"description":"Payment required","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"x402Version":{"type":"number"},"accepts":{}},"required":["error"]}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream server unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Invoke an MCP server via marketplace proxy (x402 payment)","tags":["marketplace"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/marketplace/connect/onboard":{"post":{"responses":{"200":{"description":"Onboarding link created","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"stripeAccountId":{"type":"string"}},"required":["url","stripeAccountId"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Start Stripe Connect onboarding for developer","tags":["marketplace"]}},"/api/marketplace/connect/return":{"get":{"responses":{"200":{"description":"Onboarding flow completed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}},"required":["success","message"]}}}}},"summary":"Stripe Connect onboarding return callback","tags":["marketplace"]}},"/api/pricing":{"get":{"responses":{"200":{"description":"Pricing data","content":{"application/json":{"schema":{"type":"object","properties":{"subscriptions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"price":{"type":"string"},"period":{"type":"string"},"description":{"type":"string"},"features":{"type":"array","items":{"type":"string"}},"cta":{"type":"string"},"ctaHref":{"type":"string"},"highlighted":{"type":"boolean"}},"required":["id","name","description","features","cta","ctaHref","highlighted"]}},"credits":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"tasks":{"type":"string"},"price":{"type":"string"},"priceNote":{"type":"string"},"costPer":{"type":"string"},"description":{"type":"string"},"highlighted":{"type":"boolean"}},"required":["name","tasks","description","highlighted"]}},"perpetual":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"price":{"type":"string"},"priceNote":{"type":"string"},"renewal":{"type":"string"},"description":{"type":"string"},"features":{"type":"array","items":{"type":"string"}},"cta":{"type":"string"},"ctaHref":{"type":"string"},"comingSoon":{"type":"boolean"}},"required":["name","description","features","cta","ctaHref","comingSoon"]}},"services":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"price":{"type":"string"},"priceNote":{"type":"string"},"description":{"type":"string"},"includes":{"type":"array","items":{"type":"string"}},"deliverable":{"type":"string"},"cta":{"type":"string"},"ctaHref":{"type":"string"}},"required":["id","name","description","includes","deliverable","cta","ctaHref"]}}},"required":["subscriptions","credits","perpetual","services"]}}}}},"summary":"Get pricing data","description":"Returns subscription tiers, credit bundles, and perpetual license pricing. Prices sourced from Stripe when configured, otherwise server-side defaults.","tags":["pricing"]}},"/api/revmarket/agents":{"get":{"responses":{"200":{"description":"List of published agents","content":{"application/json":{"schema":{"type":"object","properties":{"agents":{"type":"array","items":{}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["agents","total","limit","offset"]}}}}},"summary":"Browse published marketplace agents","tags":["revmarket"],"parameters":[{"name":"category","in":"query","schema":{"type":"string","enum":["coding","writing","data","design","other"]}},{"name":"search","in":"query","schema":{"type":"string","maxLength":100}},{"name":"sortBy","in":"query","schema":{"type":"string","enum":["rating","taskCount","createdAt"]}},{"name":"limit","in":"query","schema":{"type":"string"}},{"name":"offset","in":"query","schema":{"type":"string"}}]},"post":{"responses":{"201":{"description":"Agent published","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{}},"required":["agent"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Publish a new marketplace agent","tags":["revmarket"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":3,"maxLength":80},"description":{"type":"string","minLength":10,"maxLength":500},"definition":{"type":"object","additionalProperties":{}},"category":{"type":"string","enum":["coding","writing","data","design","other"],"default":"other"},"tags":{"type":"array","items":{"type":"string","maxLength":30},"maxItems":10,"default":[]},"pricingModel":{"type":"string","enum":["per-task","per-minute","flat"],"default":"per-task"},"basePriceUsdc":{"type":"string","default":"0.10"},"maxExecutionSecs":{"type":"integer","minimum":10,"maximum":3600,"default":300},"resourceLimits":{"type":"object","properties":{"maxMemoryMb":{"type":"integer","minimum":64,"maximum":4096},"maxCpuPercent":{"type":"integer","minimum":5,"maximum":100}},"required":["maxMemoryMb","maxCpuPercent"],"default":{"maxMemoryMb":512,"maxCpuPercent":50}}},"required":["name","description","definition"]}}}}}},"/api/revmarket/agents/{id}":{"get":{"responses":{"200":{"description":"Agent detail","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{},"skills":{"type":"array","items":{}}},"required":["agent","skills"]}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Get agent detail with skills","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}]},"patch":{"responses":{"200":{"description":"Agent updated","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{}},"required":["agent"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Update own marketplace agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":3,"maxLength":80},"description":{"type":"string","minLength":10,"maxLength":500},"definition":{"type":"object","additionalProperties":{}},"category":{"type":"string","enum":["coding","writing","data","design","other"]},"tags":{"type":"array","items":{"type":"string","maxLength":30},"maxItems":10},"pricingModel":{"type":"string","enum":["per-task","per-minute","flat"]},"basePriceUsdc":{"type":"string"},"maxExecutionSecs":{"type":"integer","minimum":10,"maximum":3600},"status":{"type":"string","enum":["draft","published","suspended","deprecated"]}}}}}}},"delete":{"responses":{"200":{"description":"Agent unpublished","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Unpublish own marketplace agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}]}},"/api/revmarket/agents/{id}/skills":{"post":{"responses":{"201":{"description":"Skill added","content":{"application/json":{"schema":{"type":"object","properties":{"skill":{}},"required":["skill"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Add a skill to a marketplace agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":60},"description":{"type":"string","minLength":10,"maxLength":300},"inputSchema":{"type":"object","additionalProperties":{}},"outputSchema":{"type":"object","additionalProperties":{}},"examples":{"type":"array","items":{"type":"object","properties":{"input":{},"output":{}},"required":["input","output"]},"maxItems":5,"default":[]}},"required":["name","description"]}}}}}},"/api/revmarket/tasks":{"post":{"responses":{"201":{"description":"Task submitted","content":{"application/json":{"schema":{"type":"object","properties":{"task":{}},"required":["task"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"402":{"description":"Payment required (x402)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"x402Version":{"type":"number"},"accepts":{"type":"array","items":{}}},"required":["error"]}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Submit a task to the agent marketplace","tags":["revmarket"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"agentId":{"type":"string"},"skillName":{"type":"string","minLength":2,"maxLength":60},"input":{"type":"object","additionalProperties":{}},"priority":{"type":"integer","minimum":1,"maximum":5,"default":3},"paymentMethod":{"type":"string"}},"required":["skillName","input"]}}}}}},"/api/revmarket/tasks/{id}":{"get":{"responses":{"200":{"description":"Task detail","content":{"application/json":{"schema":{"type":"object","properties":{"task":{}},"required":["task"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Task not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Get task status and result","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}]}},"/api/revmarket/tasks/{id}/cancel":{"post":{"responses":{"200":{"description":"Task cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Task cannot be cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Task not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Cancel a pending or queued task","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}]}},"/api/revmarket/agents/{id}/reviews":{"post":{"responses":{"201":{"description":"Review submitted","content":{"application/json":{"schema":{"type":"object","properties":{"review":{}},"required":["review"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Leave a review for an agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"taskId":{"type":"string"},"rating":{"type":"integer","minimum":1,"maximum":5},"comment":{"type":"string","maxLength":500}},"required":["rating"]}}}}},"get":{"responses":{"200":{"description":"Reviews list","content":{"application/json":{"schema":{"type":"object","properties":{"reviews":{"type":"array","items":{}},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["reviews","limit","offset"]}}}}},"summary":"List reviews for an agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true},{"name":"limit","in":"query","schema":{"type":"string"}},{"name":"offset","in":"query","schema":{"type":"string"}}]}},"/api/revmarket/tasks/{id}/progress":{"get":{"responses":{"200":{"description":"Task progress","content":{"application/json":{"schema":{"type":"object","properties":{"taskId":{"type":"string"},"status":{"type":"string"},"progress":{"type":"number"},"message":{"type":"string"},"updatedAt":{"type":"string"}},"required":["taskId","status","progress","message","updatedAt"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Task not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Get task execution progress","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true}]}},"/api/revmarket/executor/status":{"get":{"responses":{"200":{"description":"Executor status","content":{"application/json":{"schema":{"type":"object","properties":{"running":{"type":"boolean"},"activeTasks":{"type":"number"},"maxConcurrent":{"type":"number"}},"required":["running","activeTasks","maxConcurrent"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}},"summary":"Get executor status (admin)","tags":["revmarket"]}},"//api/collab/update":{"post":{"responses":{"200":{"description":"Update applied successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollabUpdateResponse"}}}}},"summary":"Apply a Yjs binary update to a document","tags":["Collaboration"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollabUpdateRequest"}}}}}},"//api/collab/snapshot/{documentId}":{"get":{"responses":{"200":{"description":"Document snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollabSnapshotResponse"}}}}},"summary":"Get current Yjs document state as base64","tags":["Collaboration"],"parameters":[{"name":"documentId","in":"path","schema":{"type":"string","example":"doc-001"},"required":true,"example":"doc-001"}]}},"//api/collab/agent/connect":{"post":{"responses":{"200":{"description":"WebSocket connection details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConnectResponse"}}}}},"summary":"Get WebSocket URL for agent collaboration","tags":["Agent Collaboration"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConnectRequest"}}}}}},"//api/collab/agent/edit":{"post":{"responses":{"200":{"description":"Edit applied successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentEditResponse"}}}}},"summary":"Apply server-side edit to agent document","tags":["Agent Collaboration"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentEditRequest"}}}}}},"//api/collab/agent/snapshot/{documentId}":{"get":{"responses":{"200":{"description":"Agent document snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSnapshotResponse"}}}}},"summary":"Get agent document state and connected clients","tags":["Agent Collaboration"],"parameters":[{"name":"documentId","in":"path","schema":{"type":"string","example":"doc-001"},"required":true,"example":"doc-001"}]}},"/api/v1/errors":{"post":{"responses":{"202":{"description":"Error accepted for processing","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid JSON or payload","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden  -  invalid or missing internal token","content":{"application/json":{"schema":{}}}}},"summary":"Capture client-side error","description":"Accepts structured error payloads from admin client-side and any other app that cannot write to the DB directly. Requires X-Internal-Token header.","tags":["errors"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/gdpr/consent":{"get":{"responses":{"200":{"description":"List of user consents","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}}},"summary":"List all consents for the authenticated user","tags":["gdpr"]}},"/api/v1/gdpr/consent/grant":{"post":{"responses":{"200":{"description":"Consent granted","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}}},"summary":"Grant consent for a specific type","tags":["gdpr"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/gdpr/consent/revoke":{"post":{"responses":{"200":{"description":"Consent revoked","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid request or cannot revoke necessary consent","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}}},"summary":"Revoke consent for a specific type","tags":["gdpr"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/gdpr/consent/check/{type}":{"get":{"responses":{"200":{"description":"Consent check result","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid consent type","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}}},"summary":"Check if a specific consent type is active","tags":["gdpr"],"parameters":[{"name":"type","in":"path","schema":{},"required":true,"example":"analytics"}]}},"/api/v1/gdpr/deletion":{"post":{"responses":{"201":{"description":"Deletion request created","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}}},"summary":"Request data deletion (right to be forgotten)","tags":["gdpr"],"requestBody":{"content":{"application/json":{"schema":{}}}}},"get":{"responses":{"200":{"description":"List of deletion requests","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}}},"summary":"List the authenticated user's deletion requests","tags":["gdpr"]}},"/api/v1/gdpr/deletion/{id}":{"get":{"responses":{"200":{"description":"Deletion request details","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}},"404":{"description":"Deletion request not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a specific deletion request by ID","tags":["gdpr"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"req_abc123"}]}},"/api/v1/gdpr/admin/stats":{"get":{"responses":{"200":{"description":"Consent statistics","content":{"application/json":{"schema":{}}}},"403":{"description":"Admin access required","content":{"application/json":{"schema":{}}}}},"summary":"Aggregate consent statistics (admin only)","tags":["gdpr"]}},"/api/v1/logs":{"post":{"responses":{"202":{"description":"Log entry accepted","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden  -  missing or invalid X-Internal-Token","content":{"application/json":{"schema":{}}}}},"summary":"Ingest a structured log entry","description":"Accepts warn/error/fatal log entries from apps that cannot write to the DB directly. Rate-limited.","tags":["observability"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/license/verify":{"post":{"responses":{"200":{"description":"License verification result","content":{"application/json":{"schema":{}}}},"400":{"description":"Missing license key","content":{"application/json":{"schema":{}}}}},"summary":"Verify a license key","description":"Validates a JWT license key and returns the tier, features, and limits.","tags":["license"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/license/generate":{"post":{"responses":{"201":{"description":"License key generated","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized  -  missing or invalid admin API key","content":{"application/json":{"schema":{}}}},"500":{"description":"Server error  -  missing private key configuration","content":{"application/json":{"schema":{}}}}},"summary":"Generate a license key (admin only)","description":"Creates a signed JWT license key for a customer. Requires REVEALUI_LICENSE_PRIVATE_KEY and admin API key.","tags":["license"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/license/features":{"get":{"responses":{"200":{"description":"Feature comparison by tier","content":{"application/json":{"schema":{}}}}},"summary":"List features by tier","description":"Returns which features are available at each license tier.","tags":["license"]}},"/api/v1/billing/checkout":{"post":{"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Create a checkout session","description":"Creates a Stripe checkout session for subscription purchase. Requires authentication.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/billing/portal":{"post":{"responses":{"200":{"description":"Portal session created","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Create a billing portal session","description":"Creates a Stripe billing portal session for subscription management.","tags":["billing"]}},"/api/v1/billing/subscription":{"get":{"responses":{"200":{"description":"Current subscription status","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Get subscription status","description":"Returns the current user's license tier, status, and expiration.","tags":["billing"]}},"/api/v1/billing/invoices":{"get":{"responses":{"200":{"description":"List of invoices","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"List invoices","description":"Returns the current user's Stripe invoices with amounts, status, and PDF download links.","tags":["billing"],"parameters":[{"name":"limit","in":"query","schema":{},"description":"Max invoices to return (1-100, default 10)","example":"10"},{"name":"starting_after","in":"query","schema":{},"description":"Cursor for pagination (Stripe invoice ID)","example":"in_abc"}]}},"/api/v1/billing/upgrade":{"post":{"responses":{"200":{"description":"Subscription upgraded  -  Stripe will fire customer.subscription.updated","content":{"application/json":{"schema":{}}}},"400":{"description":"No active subscription or no billing account","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Upgrade subscription tier","description":"Upgrades an active subscription to a new price/tier mid-cycle. Prorations are created automatically. Requires an existing active subscription.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/billing/downgrade":{"post":{"responses":{"200":{"description":"Subscription scheduled for cancellation at end of billing period","content":{"application/json":{"schema":{}}}},"400":{"description":"No active subscription found","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Downgrade to free tier","description":"Cancels the active subscription at the end of the current billing period. The user retains Pro/Enterprise access until then.","tags":["billing"]}},"/api/v1/billing/pause":{"post":{"responses":{"200":{"description":"Subscription paused","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Pause subscription","description":"Pauses billing for the current subscription. Access is retained during the pause period.","tags":["billing"]}},"/api/v1/billing/resume":{"post":{"responses":{"200":{"description":"Subscription resumed","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Resume subscription","description":"Resumes billing for a paused subscription.","tags":["billing"]}},"/api/v1/billing/checkout-perpetual":{"post":{"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Create a perpetual license checkout session","description":"Creates a one-time Stripe payment session for a perpetual license. Includes 1 year of support. Requires authentication.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/billing/checkout-support-renewal":{"post":{"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}},"404":{"description":"No perpetual license found for this tier","content":{"application/json":{"schema":{}}}}},"summary":"Create a support renewal checkout session","description":"Creates a one-time Stripe payment session to renew the annual support contract on a perpetual license. Requires authentication and an existing perpetual license.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/billing/checkout-credits":{"post":{"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Create a credit bundle checkout session","description":"Creates a one-time Stripe payment session for an agent task credit bundle. Credits never expire and stack with the monthly tier allowance. Requires authentication.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/billing/credits":{"get":{"responses":{"200":{"description":"Credit balance","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Get current credit balance","description":"Returns the authenticated user's prepaid agent task credit balance.","tags":["billing"]}},"/api/v1/billing/usage":{"get":{"responses":{"200":{"description":"Current cycle usage","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Agent task usage","description":"Returns agent task usage for the current billing cycle.","tags":["billing"]}},"/api/v1/billing/support-renewal-check":{"post":{"responses":{"200":{"description":"Reminders sent","content":{"application/json":{"schema":{}}}},"403":{"description":"Invalid cron secret","content":{"application/json":{"schema":{}}}}},"summary":"Send support renewal reminders (internal cron)","description":"Finds perpetual licenses whose support contract expires within 30 days and sends reminder emails. Protected by X-Cron-Secret.","tags":["billing"]}},"/api/v1/billing/report-agent-overage":{"post":{"responses":{"200":{"description":"Overage reported","content":{"application/json":{"schema":{}}}},"401":{"description":"Invalid cron secret","content":{"application/json":{"schema":{}}}}},"summary":"Report agent task overage to Stripe (internal cron)","description":"Reads overage from the previous billing cycle and emits Stripe Billing Meter events. Protected by X-Cron-Secret.","tags":["billing"]}},"/api/v1/billing/sweep-expired-licenses":{"post":{"responses":{"200":{"description":"Sweep complete","content":{"application/json":{"schema":{}}}},"403":{"description":"Invalid cron secret","content":{"application/json":{"schema":{}}}}},"summary":"Sweep expired licenses (internal cron)","description":"Marks non-perpetual licenses whose expiresAt is in the past as expired, and perpetual licenses whose supportExpiresAt is in the past as support_expired. Clears caches so changes take effect immediately. Protected by X-Cron-Secret.","tags":["billing"]}},"/api/v1/billing/refund":{"post":{"responses":{"200":{"description":"Refund created","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid request (missing payment reference)","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}},"403":{"description":"Admin access required","content":{"application/json":{"schema":{}}}}},"summary":"Issue a refund","description":"Creates a Stripe refund for a payment intent or charge. Admin-only. Full or partial refunds supported. License revocation is handled automatically by the charge.refunded webhook.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/billing/metrics":{"get":{"responses":{"200":{"description":"Revenue metrics snapshot","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}},"403":{"description":"Admin access required","content":{"application/json":{"schema":{}}}}},"summary":"Revenue metrics (admin)","description":"Returns aggregate revenue metrics for the admin dashboard. Requires admin or owner role.","tags":["billing"],"parameters":[{"name":"from","in":"query","schema":{},"description":"Start of date range for recent events (ISO 8601). Defaults to 30 days ago."},{"name":"to","in":"query","schema":{},"description":"End of date range for recent events (ISO 8601). Defaults to now."}]}},"/api/v1/webhooks/stripe":{"post":{"responses":{"200":{"description":"Webhook event received and processed","content":{"application/json":{"schema":{}}}},"400":{"description":"Missing signature or invalid webhook","content":{"application/json":{"schema":{}}}},"500":{"description":"Webhook processing failed","content":{"application/json":{"schema":{}}}},"503":{"description":"Webhook service unavailable (Stripe env vars misconfigured)","content":{"application/json":{"schema":{}}}}},"summary":"Stripe webhook handler","description":"Receives Stripe webhook events for subscription lifecycle, license management, disputes, and refunds. Requires raw body access for signature verification.","tags":["webhooks"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/provenance":{"get":{"responses":{"200":{"description":"Provenance list","content":{"application/json":{"schema":{}}}}},"summary":"List provenance entries","tags":["provenance"],"parameters":[{"name":"authorType","in":"query","schema":{},"example":"ai_generated"},{"name":"reviewStatus","in":"query","schema":{},"example":"unreviewed"},{"name":"filePathPrefix","in":"query","schema":{},"example":"packages/core"},{"name":"limit","in":"query","schema":{},"example":100},{"name":"offset","in":"query","schema":{},"example":0}]},"post":{"responses":{"201":{"description":"Provenance entry created","content":{"application/json":{"schema":{}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{}}}}},"summary":"Create a provenance entry","tags":["provenance"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/provenance/stats":{"get":{"responses":{"200":{"description":"Provenance statistics","content":{"application/json":{"schema":{}}}}},"summary":"Get provenance statistics","tags":["provenance"]}},"/api/v1/provenance/file/{filePath}":{"get":{"responses":{"200":{"description":"File provenance","content":{"application/json":{"schema":{}}}}},"summary":"Get provenance for a specific file","tags":["provenance"],"parameters":[{"name":"filePath","in":"path","schema":{},"required":true,"example":"packages/core/src/index.ts"}]}},"/api/v1/provenance/{id}":{"get":{"responses":{"200":{"description":"Provenance entry found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a provenance entry by ID","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]},"patch":{"responses":{"200":{"description":"Provenance entry updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a provenance entry","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Provenance entry deleted","content":{"application/json":{"schema":{}}}}},"summary":"Delete a provenance entry","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/v1/provenance/{id}/review":{"post":{"responses":{"201":{"description":"Review added","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{}}}}},"summary":"Add a review to a provenance entry","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/provenance/{id}/reviews":{"get":{"responses":{"200":{"description":"Review list","content":{"application/json":{"schema":{}}}}},"summary":"List reviews for a provenance entry","tags":["provenance"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/v1/tickets/boards":{"get":{"responses":{"200":{"description":"Board list","content":{"application/json":{"schema":{}}}}},"summary":"List all boards","tags":["boards"]},"post":{"responses":{"201":{"description":"Board created","content":{"application/json":{"schema":{}}}}},"summary":"Create a board","tags":["boards"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/tickets/boards/{id}":{"get":{"responses":{"200":{"description":"Board found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a board by ID","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]},"patch":{"responses":{"200":{"description":"Board updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a board","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Board deleted","content":{"application/json":{"schema":{}}}}},"summary":"Delete a board","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/v1/tickets/boards/{boardId}/columns":{"get":{"responses":{"200":{"description":"Columns list","content":{"application/json":{"schema":{}}}}},"summary":"List columns for a board","tags":["boards"],"parameters":[{"name":"boardId","in":"path","schema":{},"required":true,"example":"board-001"}]},"post":{"responses":{"201":{"description":"Column created","content":{"application/json":{"schema":{}}}}},"summary":"Create a column","tags":["boards"],"parameters":[{"name":"boardId","in":"path","schema":{},"required":true,"example":"board-001"}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/tickets/columns/{id}":{"patch":{"responses":{"200":{"description":"Column updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a column","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Column deleted","content":{"application/json":{"schema":{}}}}},"summary":"Delete a column","tags":["boards"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/v1/tickets/boards/{boardId}/tickets":{"get":{"responses":{"200":{"description":"Ticket list","content":{"application/json":{"schema":{}}}}},"summary":"List tickets for a board","tags":["tickets"],"parameters":[{"name":"boardId","in":"path","schema":{},"required":true,"example":"board-001"},{"name":"status","in":"query","schema":{},"example":"open"},{"name":"priority","in":"query","schema":{},"example":"high"},{"name":"type","in":"query","schema":{},"example":"task"},{"name":"assigneeId","in":"query","schema":{}},{"name":"columnId","in":"query","schema":{}}]},"post":{"responses":{"201":{"description":"Ticket created","content":{"application/json":{"schema":{}}}}},"summary":"Create a ticket","tags":["tickets"],"parameters":[{"name":"boardId","in":"path","schema":{},"required":true,"example":"board-001"}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/tickets/tickets/{id}":{"get":{"responses":{"200":{"description":"Ticket found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a ticket by ID","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]},"patch":{"responses":{"200":{"description":"Ticket updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a ticket","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Ticket deleted","content":{"application/json":{"schema":{}}}}},"summary":"Delete a ticket","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/v1/tickets/tickets/{id}/move":{"post":{"responses":{"200":{"description":"Ticket moved","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Move a ticket to a different column","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/tickets/tickets/{id}/subtasks":{"get":{"responses":{"200":{"description":"Subtask list","content":{"application/json":{"schema":{}}}}},"summary":"Get subtasks for a ticket","tags":["tickets"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/v1/tickets/tickets/{id}/comments":{"get":{"responses":{"200":{"description":"Comment list","content":{"application/json":{"schema":{}}}}},"summary":"List comments for a ticket","tags":["comments"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]},"post":{"responses":{"201":{"description":"Comment created","content":{"application/json":{"schema":{}}}}},"summary":"Add a comment to a ticket","tags":["comments"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/tickets/comments/{id}":{"patch":{"responses":{"200":{"description":"Comment updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a comment","tags":["comments"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Comment deleted","content":{"application/json":{"schema":{}}}}},"summary":"Delete a comment","tags":["comments"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/v1/tickets/labels":{"get":{"responses":{"200":{"description":"Label list","content":{"application/json":{"schema":{}}}}},"summary":"List all labels","tags":["labels"]},"post":{"responses":{"201":{"description":"Label created","content":{"application/json":{"schema":{}}}}},"summary":"Create a label","tags":["labels"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/tickets/labels/{id}":{"patch":{"responses":{"200":{"description":"Label updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a label","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Label deleted","content":{"application/json":{"schema":{}}}}},"summary":"Delete a label","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/v1/tickets/tickets/{id}/labels":{"post":{"responses":{"201":{"description":"Label assigned","content":{"application/json":{"schema":{}}}}},"summary":"Assign a label to a ticket","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"get":{"responses":{"200":{"description":"Labels for ticket","content":{"application/json":{"schema":{}}}}},"summary":"Get labels for a ticket","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"550e8400-e29b-41d4-a716-446655440000"}]}},"/api/v1/tickets/tickets/{id}/labels/{labelId}":{"delete":{"responses":{"200":{"description":"Label removed","content":{"application/json":{"schema":{}}}}},"summary":"Remove a label from a ticket","tags":["labels"],"parameters":[{"name":"id","in":"path","schema":{},"required":true},{"name":"labelId","in":"path","schema":{},"required":true}]}},"/api/v1/agent-tasks":{"post":{"responses":{"200":{"description":"Agent task completed within the sync/poll window","content":{"application/json":{"schema":{}}}},"202":{"description":"Dispatch enqueued but still running at the poll-window timeout. Caller polls the statusUrl.","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}}},"summary":"Submit a natural language task for an agent to execute","description":"Creates a ticket from the instruction, dispatches an AI agent with admin tools to resolve it, and returns the result. When durable dispatch is enabled and the agent takes longer than ~22 s, returns 202 with a jobId the caller can poll at /status.","tags":["agent-tasks"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/agent-tasks/{ticketId}/dispatch":{"post":{"responses":{"200":{"description":"Agent dispatch completed within the sync/poll window","content":{"application/json":{"schema":{}}}},"202":{"description":"Dispatch enqueued but still running at the poll-window timeout","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"404":{"description":"Ticket not found","content":{"application/json":{"schema":{}}}}},"summary":"Dispatch an agent for an existing ticket","tags":["agent-tasks"],"parameters":[{"name":"ticketId","in":"path","schema":{},"required":true}]}},"/api/v1/agent-tasks/{ticketId}/status":{"get":{"responses":{"200":{"description":"Dispatch status","content":{"application/json":{"schema":{}}}},"404":{"description":"Ticket not found","content":{"application/json":{"schema":{}}}}},"summary":"Fetch the canonical dispatch status for a ticket","description":"Returns the current state of the most recent dispatch job for a ticket. `status = idle` means no job was ever queued (legacy sync dispatch or ticket never dispatched). Safe to poll; returns 200 even when nothing is in flight.","tags":["agent-tasks"],"parameters":[{"name":"ticketId","in":"path","schema":{},"required":true}]}},"/api/v1/agent-stream/elicit":{"post":{"responses":{"200":{"description":"Elicitation resolved","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}},"403":{"description":"Session belongs to a different user","content":{"application/json":{"schema":{}}}},"404":{"description":"No pending elicitation matching the supplied ids","content":{"application/json":{"schema":{}}}}},"summary":"Submit an elicitation response for an in-flight agent run","description":"Resolves a pending `elicitation/create` request issued by an MCP server during an agent-stream run. The client provides `{ sessionId, elicitationId, action, content? }`; the server maps the session to the pending handler promise and resolves it.","tags":["agent"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/agent-stream":{"post":{"responses":{"200":{"description":"SSE stream of agent execution events (text/event-stream)"},"400":{"description":"Missing instruction or invalid provider","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}}},"summary":"Stream agent execution via SSE","description":"Streams agent execution events in real-time using Server-Sent Events. Client-side: use fetch + ReadableStream (not EventSource  -  it does not support POST).","tags":["agent"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/mcp/usage":{"get":{"responses":{"200":{"description":"Usage aggregations for the caller’s account","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}},"409":{"description":"Caller has no resolvable account membership","content":{"application/json":{"schema":{}}}}},"summary":"Aggregate MCP usage for the caller’s account","description":"Returns per-`meterName` totals, success / error / unknown counts (unknown = pre-A.3 row with NULL `errored`), duration counts, and p50 / p95 duration buckets in milliseconds. Filtered by the caller’s `accountId` (resolved from `entitlementMiddleware`) and the requested time range.","tags":["mcp"],"parameters":[{"name":"range","in":"query","schema":{}}]}},"/api/v1/content/posts":{"get":{"responses":{"200":{"description":"Post list","content":{"application/json":{"schema":{}}}}},"summary":"List posts","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"status","in":"query","schema":{},"example":"published"},{"name":"authorId","in":"query","schema":{}}]},"post":{"responses":{"201":{"description":"Post created","content":{"application/json":{"schema":{}}}},"400":{"description":"Content validation failed","content":{"application/json":{"schema":{}}}}},"summary":"Create a post","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/content/posts/{id}":{"get":{"responses":{"200":{"description":"Post found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a post by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Post updated","content":{"application/json":{"schema":{}}}},"400":{"description":"Content validation failed","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a post","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Post deleted","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a post","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/v1/content/posts/slug/{slug}":{"get":{"responses":{"200":{"description":"Post found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a post by slug","tags":["content"],"parameters":[{"name":"slug","in":"path","schema":{},"required":true,"example":"my-post"}]}},"/api/v1/content/media":{"post":{"responses":{"201":{"description":"Media uploaded","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid file","content":{"application/json":{"schema":{}}}},"413":{"description":"File too large","content":{"application/json":{"schema":{}}}}},"summary":"Upload a media file","tags":["content"],"requestBody":{"content":{"multipart/form-data":{"schema":{}}}}},"get":{"responses":{"200":{"description":"Media list","content":{"application/json":{"schema":{}}}}},"summary":"List media","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"mimeType","in":"query","schema":{},"example":"image"}]}},"/api/v1/content/media/{id}":{"get":{"responses":{"200":{"description":"Media found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a media item by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Media updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update media metadata","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Media deleted","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a media item","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/v1/content/sites":{"get":{"responses":{"200":{"description":"Site list","content":{"application/json":{"schema":{}}}}},"summary":"List sites","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"status","in":"query","schema":{},"example":"published"}]},"post":{"responses":{"201":{"description":"Site created","content":{"application/json":{"schema":{}}}}},"summary":"Create a site","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/content/sites/{id}":{"get":{"responses":{"200":{"description":"Site found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a site by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Site updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a site","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Site deleted","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a site","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/v1/content/sites/{siteId}/pages":{"get":{"responses":{"200":{"description":"Page list","content":{"application/json":{"schema":{}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{}}}}},"summary":"List pages for a site","tags":["content"],"parameters":[{"name":"siteId","in":"path","schema":{},"required":true,"example":"site-abc"},{"name":"status","in":"query","schema":{},"example":"published"}]},"post":{"responses":{"201":{"description":"Page created","content":{"application/json":{"schema":{}}}},"400":{"description":"Content validation failed","content":{"application/json":{"schema":{}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{}}}}},"summary":"Create a page","tags":["content"],"parameters":[{"name":"siteId","in":"path","schema":{},"required":true,"example":"site-abc"}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/content/pages/{id}":{"get":{"responses":{"200":{"description":"Page found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a page by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Page updated","content":{"application/json":{"schema":{}}}},"400":{"description":"Content validation failed","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a page","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Page deleted","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a page","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/v1/content/search":{"get":{"responses":{"200":{"description":"Search results sorted by relevance","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{}}}}},"summary":"Full-text search across published content","description":"Uses PostgreSQL full-text search with plainto_tsquery. Searches published posts and/or pages.","tags":["content"],"parameters":[{"name":"q","in":"query","schema":{},"required":true},{"name":"type","in":"query","schema":{}},{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}}]}},"/api/v1/content/users":{"get":{"responses":{"200":{"description":"Paginated user list","content":{"application/json":{"schema":{}}}}},"summary":"List users (admin-only)","tags":["content"],"parameters":[{"name":"page","in":"query","schema":{}},{"name":"limit","in":"query","schema":{}},{"name":"status","in":"query","schema":{}},{"name":"role","in":"query","schema":{}},{"name":"search","in":"query","schema":{}}]}},"/api/v1/content/users/{id}":{"get":{"responses":{"200":{"description":"User found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a user by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"User updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a user","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"User deleted","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a user (soft-delete)","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/v1/content/products":{"get":{"responses":{"200":{"description":"Product list","content":{"application/json":{"schema":{}}}}},"summary":"List products","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"status","in":"query","schema":{},"example":"published"}]},"post":{"responses":{"201":{"description":"Product created","content":{"application/json":{"schema":{}}}}},"summary":"Create a product","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/content/products/{id}":{"get":{"responses":{"200":{"description":"Product found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get a product by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Product updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update a product","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Product deleted","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Delete a product","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]}},"/api/v1/content/orders":{"get":{"responses":{"200":{"description":"Order list","content":{"application/json":{"schema":{}}}}},"summary":"List orders","tags":["content"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"status","in":"query","schema":{}}]},"post":{"responses":{"201":{"description":"Order created","content":{"application/json":{"schema":{}}}}},"summary":"Create an order","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/content/orders/{id}":{"get":{"responses":{"200":{"description":"Order found","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Get an order by ID","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}]},"patch":{"responses":{"200":{"description":"Order updated","content":{"application/json":{"schema":{}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{}}}}},"summary":"Update order status","tags":["content"],"parameters":[{"name":"id","in":"path","schema":{},"required":true,"example":"abc123"}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/content/batch/create":{"post":{"responses":{"200":{"description":"Batch create results","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{}}}}},"summary":"Batch create items in a collection","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/content/batch/update":{"post":{"responses":{"200":{"description":"Batch update results","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{}}}}},"summary":"Batch update items in a collection","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/content/batch/delete":{"post":{"responses":{"200":{"description":"Batch delete results","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{}}}}},"summary":"Batch delete items in a collection","tags":["content"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/content/export/{collection}":{"get":{"responses":{"200":{"description":"Export data","content":{"application/json":{"schema":{}},"text/csv":{"schema":{}}}},"400":{"description":"Invalid collection","content":{"application/json":{"schema":{}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{}}}},"403":{"description":"Admin access required","content":{"application/json":{"schema":{}}}}},"summary":"Export collection data as JSON or CSV","description":"Admin-only bulk export endpoint. Supported collections: posts, pages, users, sites, media. Limited to 10,000 rows per request.","tags":["content"],"parameters":[{"name":"collection","in":"path","schema":{},"required":true,"example":"posts"},{"name":"format","in":"query","schema":{}},{"name":"status","in":"query","schema":{}}]}},"/api/v1/rag/workspaces/{workspaceId}/index/{collection}":{"post":{"responses":{"200":{"description":"Indexing completed","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid collection name","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}},"502":{"description":"Admin fetch error","content":{"application/json":{"schema":{}}}}},"summary":"Trigger RAG indexing for an admin collection","tags":["rag"],"parameters":[{"name":"workspaceId","in":"path","schema":{},"required":true,"description":"Workspace ID"},{"name":"collection","in":"path","schema":{},"required":true,"description":"Admin collection name"}]}},"/api/v1/rag/workspaces/{workspaceId}/documents":{"get":{"responses":{"200":{"description":"Document list","content":{"application/json":{"schema":{}}}}},"summary":"List documents in a workspace","tags":["rag"],"parameters":[{"name":"workspaceId","in":"path","schema":{},"required":true,"description":"Workspace ID"}]}},"/api/v1/rag/workspaces/{workspaceId}/documents/{documentId}":{"delete":{"responses":{"200":{"description":"Document deleted","content":{"application/json":{"schema":{}}}},"403":{"description":"AI feature requires Pro or Enterprise license","content":{"application/json":{"schema":{}}}}},"summary":"Delete a RAG document","tags":["rag"],"parameters":[{"name":"workspaceId","in":"path","schema":{},"required":true,"description":"Workspace ID"},{"name":"documentId","in":"path","schema":{},"required":true,"description":"Document ID"}]}},"/api/v1/rag/workspaces/{workspaceId}/status":{"get":{"responses":{"200":{"description":"Workspace RAG status","content":{"application/json":{"schema":{}}}}},"summary":"Get workspace RAG indexing status","tags":["rag"],"parameters":[{"name":"workspaceId","in":"path","schema":{},"required":true,"description":"Workspace ID"}]}},"/api/v1/admin/logs":{"get":{"responses":{"200":{"description":"Paginated app logs","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List application logs (admin-only)","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"app","in":"query","schema":{}},{"name":"level","in":"query","schema":{}}]}},"/api/v1/admin/errors":{"get":{"responses":{"200":{"description":"Paginated error events","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List error events (admin-only)","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}}]}},"/api/v1/admin/audit":{"get":{"responses":{"200":{"description":"Paginated audit log entries","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List audit log entries (admin-only)","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"severity","in":"query","schema":{}},{"name":"agentId","in":"query","schema":{}},{"name":"eventType","in":"query","schema":{}},{"name":"dateFrom","in":"query","schema":{},"description":"ISO 8601 lower bound (inclusive) on `timestamp`."},{"name":"dateTo","in":"query","schema":{},"description":"ISO 8601 upper bound (inclusive) on `timestamp`."},{"name":"policyViolationId","in":"query","schema":{},"description":"Match entries whose `policy_violations` JSONB array contains this string. Useful for scoping to a single rule's violations."}]}},"/api/v1/admin/webhooks":{"get":{"responses":{"200":{"description":"Paginated webhook events","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List processed webhook events (admin-only)","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"eventType","in":"query","schema":{}}]}},"/api/v1/admin/jobs":{"get":{"responses":{"200":{"description":"Paginated jobs","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List durable-queue jobs (admin-only)","description":"Paginated view of the `jobs` table. Filterable by state (created/active/completed/failed/retry) and by handler name. Ordered newest-created first.","tags":["admin","observability"],"parameters":[{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}},{"name":"state","in":"query","schema":{}},{"name":"name","in":"query","schema":{}}]}},"/api/v1/admin/jobs/summary":{"get":{"responses":{"200":{"description":"Queue summary","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"Durable-queue aggregate stats (admin-only)","description":"Returns: current depth by state, per-handler counts over the last 24 hours (completed / failed / running), and the 10 most-recent failures. Intended for the admin jobs dashboard header.","tags":["admin","observability"]}},"/api/v1/admin/inference/config":{"get":{"responses":{"200":{"description":"Config (per-site) or system default","content":{"application/json":{"schema":{}}}}},"summary":"Read per-site inference config (Max tier)","tags":["admin","inference"],"parameters":[{"name":"workspaceId","in":"query","schema":{},"required":true}]},"put":{"responses":{"200":{"description":"Config saved","content":{"application/json":{"schema":{}}}}},"summary":"Upsert per-site inference config (Max tier)","tags":["admin","inference"],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Config deleted; default returned","content":{"application/json":{"schema":{}}}}},"summary":"Revert site to system default inference (Max tier)","tags":["admin","inference"],"parameters":[{"name":"workspaceId","in":"query","schema":{},"required":true}]}},"/api/v1/admin/coordination/sessions":{"get":{"responses":{"200":{"description":"Paginated coordination sessions","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"List coordination sessions across the agent fleet (admin-only)","description":"Returns sessions from the Neon coordination_sessions table joined with agent info. Default scope is \"active\" (sessions with ended_at IS NULL). Empty result when no daemon writes have landed yet — the surface is intentionally tolerant of the no-data case so admins can deploy this before any daemon is configured.","tags":["admin","coordination"],"parameters":[{"name":"scope","in":"query","schema":{}},{"name":"agentId","in":"query","schema":{}},{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}}]}},"/api/v1/analytics/summary":{"get":{"responses":{"200":{"description":"Aggregated metrics for the period","content":{"application/json":{"schema":{}}}}},"summary":"Period totals for the authenticated user account","tags":["Analytics"],"parameters":[{"name":"days","in":"query","schema":{}}]}},"/api/v1/analytics/by-meter":{"get":{"responses":{"200":{"description":"Breakdown by meter name, sorted by count desc","content":{"application/json":{"schema":{}}}}},"summary":"Per-meter breakdown for the authenticated user account","tags":["Analytics"],"parameters":[{"name":"days","in":"query","schema":{}}]}},"/api/v1/analytics/by-source":{"get":{"responses":{"200":{"description":"Breakdown by source (system|user|agent|api), sorted by count desc","content":{"application/json":{"schema":{}}}}},"summary":"Per-source breakdown for the authenticated user account","tags":["Analytics"],"parameters":[{"name":"days","in":"query","schema":{}}]}},"/api/v1/devkit/profiles":{"get":{"responses":{"200":{"description":"Profile metadata for all five available profiles","content":{"application/json":{"schema":{}}}}},"summary":"List available DevKit profiles","tags":["DevKit"]}},"/api/v1/devkit/profile/active":{"get":{"responses":{"200":{"description":"User selection (or null if unset)","content":{"application/json":{"schema":{}}}}},"summary":"Read the user's active DevKit profile","tags":["DevKit"]},"put":{"responses":{"200":{"description":"Profile selection saved","content":{"application/json":{"schema":{}}}}},"summary":"Set the user's active DevKit profile (Max tier)","tags":["DevKit"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/rotation/history":{"get":{"responses":{"200":{"description":"Credential events for the authenticated user, newest first","content":{"application/json":{"schema":{}}}}},"summary":"Read the user's credential lifecycle history","tags":["Rotation"],"parameters":[{"name":"days","in":"query","schema":{}},{"name":"kind","in":"query","schema":{}}]}},"/api/v1/api-keys":{"post":{"responses":{"201":{"description":"Key stored successfully","content":{"application/json":{"schema":{}}}}},"summary":"Store an encrypted API key","tags":["API Keys"],"requestBody":{"content":{"application/json":{"schema":{}}}}},"get":{"responses":{"200":{"description":"List of key summaries","content":{"application/json":{"schema":{}}}}},"summary":"List stored API keys (hints only, never plaintext)","tags":["API Keys"]}},"/api/v1/api-keys/:id":{"delete":{"responses":{"200":{"description":"Key deleted","content":{"application/json":{"schema":{}}}},"404":{"description":"Key not found"}},"summary":"Delete a stored API key","tags":["API Keys"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}]}},"/api/v1/api-keys/:id/rotate":{"post":{"responses":{"200":{"description":"Key rotated","content":{"application/json":{"schema":{}}}},"404":{"description":"Key not found"}},"summary":"Replace the plaintext for an existing API key slot","tags":["API Keys"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/ghcr/verify":{"post":{"responses":{"200":{"description":"Pull allowed","content":{"application/json":{"schema":{}}}},"401":{"description":"Missing or invalid webhook secret","content":{"application/json":{"schema":{}}}},"403":{"description":"Pull denied  -  no valid entitlement","content":{"application/json":{"schema":{}}}}},"summary":"Verify license for GHCR image pull","description":"Called by GitHub Packages webhook on Docker image pull. Validates the license key against account entitlements.","tags":["ghcr"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/ghcr/status":{"get":{"responses":{"200":{"description":"Access status","content":{"application/json":{"schema":{}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{}}}}},"summary":"Check GHCR access status for authenticated user","description":"Returns whether the authenticated user has GHCR pull access.","tags":["ghcr"]}},"/api/v1/maintenance/cleanup-orphans":{"post":{"responses":{"200":{"description":"Cleanup completed successfully","content":{"application/json":{"schema":{}}}},"403":{"description":"Invalid cron secret","content":{"application/json":{"schema":{}}}},"500":{"description":"Cleanup failed","content":{"application/json":{"schema":{}}}}},"summary":"Clean up orphaned vector data (internal cron)","description":"Removes orphaned Supabase vector data (agent memories, RAG documents, RAG chunks) for sites that have been soft-deleted in NeonDB. Protected by X-Cron-Secret.","tags":["maintenance"]}},"/api/v1/marketplace/servers":{"get":{"responses":{"200":{"description":"List of active servers","content":{"application/json":{"schema":{}}}}},"summary":"List active marketplace servers","tags":["marketplace"],"parameters":[{"name":"category","in":"query","schema":{}},{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}}]},"post":{"responses":{"201":{"description":"Server published","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"422":{"description":"Invalid URL","content":{"application/json":{"schema":{}}}}},"summary":"Publish a new MCP server","tags":["marketplace"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/marketplace/servers/{id}":{"get":{"responses":{"200":{"description":"Server detail","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid server ID","content":{"application/json":{"schema":{}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{}}}}},"summary":"Get single server detail","tags":["marketplace"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}]},"delete":{"responses":{"200":{"description":"Server unpublished","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid server ID","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{}}}}},"summary":"Unpublish own server","tags":["marketplace"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}]}},"/api/v1/marketplace/servers/{id}/invoke":{"post":{"responses":{"200":{"description":"Proxied response from MCP server","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{}}}},"402":{"description":"Payment required","content":{"application/json":{"schema":{}}}},"404":{"description":"Server not found","content":{"application/json":{"schema":{}}}},"502":{"description":"Upstream server unavailable","content":{"application/json":{"schema":{}}}}},"summary":"Invoke an MCP server via marketplace proxy (x402 payment)","tags":["marketplace"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/marketplace/connect/onboard":{"post":{"responses":{"200":{"description":"Onboarding link created","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}}},"summary":"Start Stripe Connect onboarding for developer","tags":["marketplace"]}},"/api/v1/marketplace/connect/return":{"get":{"responses":{"200":{"description":"Onboarding flow completed","content":{"application/json":{"schema":{}}}}},"summary":"Stripe Connect onboarding return callback","tags":["marketplace"]}},"/api/v1/pricing":{"get":{"responses":{"200":{"description":"Pricing data","content":{"application/json":{"schema":{}}}}},"summary":"Get pricing data","description":"Returns subscription tiers, credit bundles, and perpetual license pricing. Prices sourced from Stripe when configured, otherwise server-side defaults.","tags":["pricing"]}},"/api/v1/revmarket/agents":{"get":{"responses":{"200":{"description":"List of published agents","content":{"application/json":{"schema":{}}}}},"summary":"Browse published marketplace agents","tags":["revmarket"],"parameters":[{"name":"category","in":"query","schema":{}},{"name":"search","in":"query","schema":{}},{"name":"sortBy","in":"query","schema":{}},{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}}]},"post":{"responses":{"201":{"description":"Agent published","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}}},"summary":"Publish a new marketplace agent","tags":["revmarket"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/revmarket/agents/{id}":{"get":{"responses":{"200":{"description":"Agent detail","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Get agent detail with skills","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}]},"patch":{"responses":{"200":{"description":"Agent updated","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Update own marketplace agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"delete":{"responses":{"200":{"description":"Agent unpublished","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Unpublish own marketplace agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}]}},"/api/v1/revmarket/agents/{id}/skills":{"post":{"responses":{"201":{"description":"Skill added","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Add a skill to a marketplace agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/revmarket/tasks":{"post":{"responses":{"201":{"description":"Task submitted","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"402":{"description":"Payment required (x402)","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Submit a task to the agent marketplace","tags":["revmarket"],"requestBody":{"content":{"application/json":{"schema":{}}}}}},"/api/v1/revmarket/tasks/{id}":{"get":{"responses":{"200":{"description":"Task detail","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}},"404":{"description":"Task not found","content":{"application/json":{"schema":{}}}}},"summary":"Get task status and result","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}]}},"/api/v1/revmarket/tasks/{id}/cancel":{"post":{"responses":{"200":{"description":"Task cancelled","content":{"application/json":{"schema":{}}}},"400":{"description":"Task cannot be cancelled","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}},"404":{"description":"Task not found","content":{"application/json":{"schema":{}}}}},"summary":"Cancel a pending or queued task","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}]}},"/api/v1/revmarket/agents/{id}/reviews":{"post":{"responses":{"201":{"description":"Review submitted","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"404":{"description":"Agent not found","content":{"application/json":{"schema":{}}}}},"summary":"Leave a review for an agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}],"requestBody":{"content":{"application/json":{"schema":{}}}}},"get":{"responses":{"200":{"description":"Reviews list","content":{"application/json":{"schema":{}}}}},"summary":"List reviews for an agent","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{},"required":true},{"name":"limit","in":"query","schema":{}},{"name":"offset","in":"query","schema":{}}]}},"/api/v1/revmarket/tasks/{id}/progress":{"get":{"responses":{"200":{"description":"Task progress","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"404":{"description":"Task not found","content":{"application/json":{"schema":{}}}}},"summary":"Get task execution progress","tags":["revmarket"],"parameters":[{"name":"id","in":"path","schema":{},"required":true}]}},"/api/v1/revmarket/executor/status":{"get":{"responses":{"200":{"description":"Executor status","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{}}}}},"summary":"Get executor status (admin)","tags":["revmarket"]}}},"components":{"schemas":{"CodeProvenance":{"type":"object","properties":{"id":{"type":"string"},"schemaVersion":{"type":"string"},"filePath":{"type":"string"},"functionName":{"type":"string","nullable":true},"lineStart":{"type":"number","nullable":true},"lineEnd":{"type":"number","nullable":true},"authorType":{"type":"string"},"aiModel":{"type":"string","nullable":true},"aiSessionId":{"type":"string","nullable":true},"gitCommitHash":{"type":"string","nullable":true},"gitAuthor":{"type":"string","nullable":true},"confidence":{"type":"number"},"reviewStatus":{"type":"string"},"reviewedBy":{"type":"string","nullable":true},"reviewedAt":{"type":"string","nullable":true,"format":"date-time"},"linesOfCode":{"type":"number"},"metadata":{"nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","schemaVersion","filePath","functionName","lineStart","lineEnd","authorType","aiModel","aiSessionId","gitCommitHash","gitAuthor","confidence","reviewStatus","reviewedBy","reviewedAt","linesOfCode","metadata","createdAt","updatedAt"]},"CodeReview":{"type":"object","properties":{"id":{"type":"string"},"provenanceId":{"type":"string"},"reviewerId":{"type":"string","nullable":true},"reviewType":{"type":"string"},"status":{"type":"string"},"comment":{"type":"string","nullable":true},"metadata":{"nullable":true},"createdAt":{"type":"string","format":"date-time"}},"required":["id","provenanceId","reviewerId","reviewType","status","comment","metadata","createdAt"]},"Board":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string","nullable":true},"ownerId":{"type":"string","nullable":true},"tenantId":{"type":"string","nullable":true},"isDefault":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","slug","description","ownerId","tenantId","isDefault","createdAt","updatedAt"]},"BoardColumn":{"type":"object","properties":{"id":{"type":"string"},"boardId":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"position":{"type":"number"},"wipLimit":{"type":"number","nullable":true},"color":{"type":"string","nullable":true},"isDefault":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","boardId","name","slug","position","wipLimit","color","isDefault","createdAt","updatedAt"]},"Ticket":{"type":"object","properties":{"id":{"type":"string"},"boardId":{"type":"string"},"columnId":{"type":"string","nullable":true},"parentTicketId":{"type":"string","nullable":true},"ticketNumber":{"type":"number"},"title":{"type":"string"},"description":{"nullable":true},"status":{"type":"string","enum":["open","in_progress","in_review","done","closed"]},"priority":{"type":"string","enum":["urgent","high","medium","low"]},"type":{"type":"string","enum":["task","bug","feature","improvement","epic"]},"assigneeId":{"type":"string","nullable":true},"reporterId":{"type":"string","nullable":true},"dueDate":{"type":"string","nullable":true,"format":"date-time"},"estimatedEffort":{"type":"number","nullable":true},"sortOrder":{"type":"number"},"commentCount":{"type":"number"},"attachments":{"nullable":true},"metadata":{"nullable":true},"closedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","boardId","columnId","parentTicketId","ticketNumber","title","description","status","priority","type","assigneeId","reporterId","dueDate","estimatedEffort","sortOrder","commentCount","attachments","metadata","closedAt","createdAt","updatedAt"]},"TicketComment":{"type":"object","properties":{"id":{"type":"string"},"ticketId":{"type":"string"},"authorId":{"type":"string","nullable":true},"body":{"nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","ticketId","authorId","body","createdAt","updatedAt"]},"TicketLabel":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"color":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"tenantId":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","slug","color","description","tenantId","createdAt","updatedAt"]},"Post":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"slug":{"type":"string"},"excerpt":{"type":"string","nullable":true},"content":{"nullable":true},"featuredImageId":{"type":"string","nullable":true},"authorId":{"type":"string","nullable":true},"status":{"type":"string","enum":["draft","published","archived"]},"published":{"type":"boolean","nullable":true},"meta":{"nullable":true},"categories":{"nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","title","slug","excerpt","content","featuredImageId","authorId","status","published","meta","categories","createdAt","updatedAt","publishedAt"]},"Media":{"type":"object","properties":{"id":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"filesize":{"type":"number","nullable":true},"url":{"type":"string"},"alt":{"type":"string","nullable":true},"width":{"type":"number","nullable":true},"height":{"type":"number","nullable":true},"focalPoint":{"nullable":true},"sizes":{"nullable":true},"uploadedBy":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","filename","mimeType","filesize","url","alt","width","height","focalPoint","sizes","uploadedBy","createdAt","updatedAt"]},"Site":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string","nullable":true},"ownerId":{"type":"string"},"status":{"type":"string","enum":["draft","published","archived","maintenance"]},"theme":{"nullable":true},"settings":{"nullable":true},"pageCount":{"type":"number","nullable":true},"favicon":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","name","slug","description","ownerId","status","theme","settings","pageCount","favicon","createdAt","updatedAt","publishedAt"]},"Page":{"type":"object","properties":{"id":{"type":"string"},"siteId":{"type":"string"},"parentId":{"type":"string","nullable":true},"templateId":{"type":"string","nullable":true},"title":{"type":"string"},"slug":{"type":"string"},"path":{"type":"string"},"status":{"type":"string","enum":["draft","published","scheduled","archived"]},"blocks":{"nullable":true},"seo":{"nullable":true},"blockCount":{"type":"number","nullable":true},"wordCount":{"type":"number","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","siteId","parentId","templateId","title","slug","path","status","blocks","seo","blockCount","wordCount","createdAt","updatedAt","publishedAt"]},"User":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","nullable":true},"avatarUrl":{"type":"string","nullable":true},"type":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"},"emailVerified":{"type":"boolean"},"mfaEnabled":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"lastActiveAt":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","name","email","avatarUrl","type","role","status","emailVerified","mfaEnabled","createdAt","updatedAt","lastActiveAt"]},"Product":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string","nullable":true},"priceInCents":{"type":"number","nullable":true},"currency":{"type":"string"},"stripeProductId":{"type":"string","nullable":true},"stripePriceId":{"type":"string","nullable":true},"active":{"type":"boolean"},"status":{"type":"string","enum":["draft","published","archived"]},"images":{"nullable":true},"metadata":{"nullable":true},"ownerId":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"deletedAt":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","title","slug","description","priceInCents","currency","stripeProductId","stripePriceId","active","status","images","metadata","ownerId","createdAt","updatedAt","deletedAt"]},"Order":{"type":"object","properties":{"id":{"type":"string"},"customerId":{"type":"string"},"status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled","refunded"]},"totalInCents":{"type":"number"},"currency":{"type":"string"},"stripePaymentIntentId":{"type":"string","nullable":true},"stripeCheckoutSessionId":{"type":"string","nullable":true},"items":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"title":{"type":"string"},"quantity":{"type":"integer","exclusiveMinimum":0},"priceInCents":{"type":"integer","minimum":0}},"required":["productId","title","quantity","priceInCents"]}},"shippingAddress":{"nullable":true},"metadata":{"nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","customerId","status","totalInCents","currency","stripePaymentIntentId","stripeCheckoutSessionId","items","shippingAddress","metadata","createdAt","updatedAt"]},"CollabUpdateResponse":{"type":"object","properties":{"success":{"type":"boolean","const":true}},"required":["success"]},"CollabUpdateRequest":{"type":"object","properties":{"documentId":{"type":"string","minLength":1},"update":{"type":"string","minLength":1,"description":"Base64-encoded Yjs binary update"}},"required":["documentId","update"]},"CollabSnapshotResponse":{"type":"object","properties":{"success":{"type":"boolean","const":true},"documentId":{"type":"string"},"state":{"type":"string","description":"Base64-encoded Yjs document state"}},"required":["success","documentId","state"]},"AgentConnectResponse":{"type":"object","properties":{"success":{"type":"boolean","const":true},"wsUrl":{"type":"string","description":"WebSocket URL for real-time collaboration"},"documentId":{"type":"string"},"identity":{"type":"object","properties":{"type":{"type":"string","const":"agent"},"name":{"type":"string"},"model":{"type":"string"},"color":{"type":"string"}},"required":["type","name","model","color"]}},"required":["success","wsUrl","documentId","identity"]},"AgentConnectRequest":{"type":"object","properties":{"documentId":{"type":"string","minLength":1},"agentName":{"type":"string","minLength":1,"maxLength":100},"agentModel":{"type":"string","minLength":1,"maxLength":100},"color":{"type":"string"}},"required":["documentId","agentName","agentModel"]},"AgentEditResponse":{"type":"object","properties":{"success":{"type":"boolean","const":true},"documentId":{"type":"string"},"textLength":{"type":"number"}},"required":["success","documentId","textLength"]},"AgentEditRequest":{"type":"object","properties":{"documentId":{"type":"string","minLength":1},"edit":{"type":"object","properties":{"type":{"type":"string","enum":["insert","delete","replace-all"]},"textName":{"type":"string"},"index":{"type":"integer","minimum":0},"content":{"type":"string"},"length":{"type":"integer","exclusiveMinimum":0}},"required":["type"]}},"required":["documentId","edit"]},"AgentSnapshotResponse":{"type":"object","properties":{"success":{"type":"boolean","const":true},"documentId":{"type":"string"},"content":{"type":"string"},"textLength":{"type":"number"},"connectedClients":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"string"},"agentModel":{"type":"string"}},"required":["type","id","name","color"]}}},"required":["success","documentId","content","textLength","connectedClients"]}}}}