{"openapi":"3.1.0","info":{"title":"AI for Database API","version":"1.0.0","description":"API for AI agents to interact with databases through natural language, dashboards, workflows, and more."},"servers":[{"url":"https://app.aifordatabase.com/api/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Connections","description":"Manage database connections, schemas, annotations, and execute SQL queries"},{"name":"Chat","description":"Send natural-language messages and receive AI-generated SQL and insights"},{"name":"Conversations","description":"Manage chat conversation history"},{"name":"Dashboards","description":"Create and manage dashboards and their widgets"},{"name":"Workflows","description":"Build and run scheduled or manual multi-step workflows"},{"name":"Workflow Credentials","description":"Manage encrypted, destination-bound credentials for workflow actions"},{"name":"Webhooks","description":"Manage webhook endpoints, deliveries, and test events"},{"name":"Metrics","description":"Define and evaluate metric formulas against connections"},{"name":"Saved Queries","description":"Store, parameterize, and execute reusable SQL queries"},{"name":"Query Approval","description":"Submit queries for human approval before execution"},{"name":"Usage","description":"View usage records and budget information"},{"name":"Keys","description":"Manage platform API keys"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"Platform API key starting with afd_"}},"schemas":{"ApiMeta":{"type":"object","properties":{"requestId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["requestId","timestamp"]},"Pagination":{"type":"object","properties":{"total":{"type":"integer"},"page":{"type":"integer"},"pageSize":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["total","page","pageSize","totalPages"]},"ApiError":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"]},"SuccessEnvelope":{"type":"object","properties":{"data":{},"error":{"type":"null"},"meta":{"$ref":"#/components/schemas/ApiMeta"}},"required":["data","error","meta"]},"ErrorEnvelope":{"type":"object","properties":{"data":{"type":"null"},"error":{"$ref":"#/components/schemas/ApiError"},"meta":{"$ref":"#/components/schemas/ApiMeta"}},"required":["data","error","meta"]},"DeletedResponse":{"type":"object","properties":{"deleted":{"type":"boolean","example":true}}},"Connection":{"type":"object","description":"Sanitized connection metadata. Passwords, encrypted credentials, and platform secrets are never returned.","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["POSTGRES","MYSQL","MARIADB","MSSQL","MONGODB","SQLITE"]},"host":{"type":"string"},"port":{"type":"integer","nullable":true},"database":{"type":"string"},"username":{"type":"string"},"sslEnabled":{"type":"boolean"},"isActive":{"type":"boolean","description":"False after 3 consecutive failed health checks (see lastError for why) or a failed manual test."},"lastTestedAt":{"type":"string","format":"date-time","nullable":true},"lastError":{"type":"string","nullable":true,"description":"Message from the most recent failed test/introspect/health-check. Null when the last attempt succeeded."},"lastErrorDiagnosis":{"$ref":"#/components/schemas/Diagnosis","description":"Structured diagnosis for lastError — check this instead of re-running a test to see why a connection is unhealthy."},"schemaUpdatedAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"ConnectionCreate":{"type":"object","required":["name","type"],"properties":{"name":{"type":"string"},"type":{"type":"string","enum":["POSTGRES","MYSQL","MARIADB","MSSQL","MONGODB","SQLITE"]},"host":{"type":"string"},"port":{"type":"integer"},"database":{"type":"string"},"username":{"type":"string"},"password":{"type":"string","description":"Database password (write-only, never returned). `encryptedPassword` is accepted as an alias."},"encryptedPassword":{"type":"string","description":"Alias of `password`."},"sslEnabled":{"type":"boolean","default":false,"description":"`ssl` is accepted as an alias."}}},"ConnectionUpdate":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["POSTGRES","MYSQL","MARIADB","MSSQL","MONGODB","SQLITE"]},"host":{"type":"string"},"port":{"type":"integer"},"database":{"type":"string"},"username":{"type":"string"},"password":{"type":"string","description":"Database password (write-only, never returned). `encryptedPassword` is accepted as an alias."},"encryptedPassword":{"type":"string","description":"Alias of `password`."},"sslEnabled":{"type":"boolean","description":"`ssl` is accepted as an alias."},"isActive":{"type":"boolean"}}},"TestResult":{"type":"object","properties":{"success":{"type":"boolean"},"latency":{"type":"number"},"message":{"type":"string"},"schemaIntrospected":{"type":"boolean","description":"True when this test also introspected and cached the schema (first successful test on a connection with no schema)."},"tableCount":{"type":"integer","description":"Number of tables found, when schemaIntrospected is true."},"schemaError":{"type":"string","description":"Present when the connection test succeeded but the automatic schema introspection failed."}}},"Diagnosis":{"type":"object","description":"Structured failure diagnosis included in CONNECTION_FAILED / INTROSPECTION_FAILED error details.","properties":{"stage":{"type":"string","description":"Where it failed: RESOLVE, CONNECT, TLS, AUTH, READ_SCHEMA, ..."},"fault":{"type":"string","description":"Whose problem it is: user, server, third-party, us"},"title":{"type":"string"},"explanation":{"type":"string"},"fixSteps":{"type":"array","items":{"type":"string"}},"retryable":{"type":"boolean"}}},"SchemaResult":{"type":"object","properties":{"schema":{"type":"object","description":"Introspected database schema with tables, columns, and types"},"schemaSummary":{"type":"string","nullable":true},"schemaUpdatedAt":{"type":"string","format":"date-time"}}},"QueryRequest":{"type":"object","required":["sql"],"properties":{"sql":{"type":"string","description":"SQL query to execute"}}},"QueryResult":{"type":"object","description":"Raw database result returned directly to the authenticated caller.","properties":{"columns":{"type":"array","items":{"type":"string"}},"rows":{"type":"array","items":{"type":"object"}},"rowCount":{"type":"integer"},"executionTime":{"type":"number","description":"Execution time in milliseconds"}}},"Annotation":{"type":"object","properties":{"id":{"type":"string"},"connectionId":{"type":"string"},"tableName":{"type":"string"},"columnName":{"type":"string","nullable":true},"annotation":{"type":"string"},"dataType":{"type":"string","nullable":true},"examples":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"AnnotationCreate":{"type":"object","required":["tableName","annotation"],"properties":{"tableName":{"type":"string"},"columnName":{"type":"string","nullable":true},"annotation":{"type":"string"},"dataType":{"type":"string"},"examples":{"type":"string"}}},"AnnotationUpdate":{"type":"object","properties":{"annotation":{"type":"string"},"dataType":{"type":"string","nullable":true},"examples":{"type":"string","nullable":true}}},"AutoAnnotationRequest":{"type":"object","properties":{"tables":{"type":"array","items":{"type":"string"},"description":"Specific table names to annotate. Omit to annotate all tables."}}},"AutoAnnotationResult":{"type":"object","properties":{"message":{"type":"string"},"connectionId":{"type":"string"},"tables":{"type":"array","items":{"type":"string"}},"tableCount":{"type":"integer"}}},"ChatRequest":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"Natural-language question or instruction"},"connectionId":{"type":"string","description":"Database connection to use for SQL execution"},"conversationId":{"type":"string","description":"Continue an existing conversation"},"stream":{"type":"boolean","default":false,"description":"Set true for Server-Sent Events streaming"}}},"ChatResponse":{"type":"object","properties":{"messageId":{"type":"string"},"conversationId":{"type":"string"},"content":{"type":"string","description":"AI-generated natural language response"},"sqlQuery":{"type":"string","nullable":true},"intent":{"type":"string","nullable":true},"queryResult":{"$ref":"#/components/schemas/QueryResult"},"steps":{"type":"array","items":{"type":"object","properties":{"action":{"type":"string"},"detail":{"type":"string"},"sql":{"type":"string","nullable":true},"queryResult":{"type":"object","nullable":true,"properties":{"columns":{"type":"array","items":{"type":"string"}},"rowCount":{"type":"integer"},"executionTime":{"type":"number"}}},"queryError":{"type":"string","nullable":true}}}},"usage":{"type":"object","properties":{"model":{"type":"string"},"promptTokens":{"type":"integer"},"completionTokens":{"type":"integer"}}}}},"Conversation":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"userId":{"type":"string"},"connectionId":{"type":"string","nullable":true},"title":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ConversationCreate":{"type":"object","properties":{"title":{"type":"string"},"connectionId":{"type":"string"}}},"ConversationUpdate":{"type":"object","required":["title"],"properties":{"title":{"type":"string"}}},"Message":{"type":"object","properties":{"id":{"type":"string"},"conversationId":{"type":"string"},"role":{"type":"string","enum":["USER","ASSISTANT"]},"content":{"type":"string"},"sqlQuery":{"type":"string","nullable":true},"resultSummary":{"type":"string","nullable":true},"promptTokens":{"type":"integer","nullable":true},"completionTokens":{"type":"integer","nullable":true},"model":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"Dashboard":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"isPublic":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"widgets":{"type":"array","items":{"$ref":"#/components/schemas/Widget"}}}},"DashboardCreate":{"type":"object","required":["title"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"isPublic":{"type":"boolean","default":false}}},"DashboardUpdate":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"isPublic":{"type":"boolean"}}},"Widget":{"type":"object","properties":{"id":{"type":"string"},"dashboardId":{"type":"string"},"connectionId":{"type":"string","nullable":true},"type":{"type":"string"},"title":{"type":"string"},"query":{"type":"string"},"config":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"position":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WidgetCreate":{"type":"object","required":["type","title"],"properties":{"type":{"type":"string"},"title":{"type":"string"},"query":{"type":"string"},"connectionId":{"type":"string"},"config":{"type":"string"},"width":{"type":"integer","default":6},"height":{"type":"integer","default":4},"position":{"type":"integer","default":0}}},"WidgetUpdate":{"type":"object","properties":{"title":{"type":"string"},"query":{"type":"string"},"config":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"position":{"type":"integer"}}},"ScheduleConfig":{"oneOf":[{"type":"object","title":"Every N minutes","required":["preset","minutes"],"properties":{"preset":{"type":"string","const":"EVERY_N_MINUTES"},"minutes":{"type":"integer","minimum":5,"maximum":43200}}},{"type":"object","title":"Hourly","required":["preset"],"properties":{"preset":{"type":"string","const":"HOURLY"}}},{"type":"object","title":"Daily","required":["preset","hour"],"properties":{"preset":{"type":"string","const":"DAILY"},"hour":{"type":"integer","minimum":0,"maximum":23},"minute":{"type":"integer","minimum":0,"maximum":59,"default":0}}},{"type":"object","title":"Weekly","required":["preset","dayOfWeek","hour"],"properties":{"preset":{"type":"string","const":"WEEKLY"},"dayOfWeek":{"type":"integer","minimum":0,"maximum":6},"hour":{"type":"integer","minimum":0,"maximum":23},"minute":{"type":"integer","minimum":0,"maximum":59,"default":0}}}],"discriminator":{"propertyName":"preset"}},"Workflow":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"connectionId":{"type":"string","nullable":true},"projectId":{"type":"string","nullable":true},"triggerType":{"type":"string","enum":["MANUAL","SCHEDULE"]},"triggerConfig":{"type":"string","description":"JSON configuration for schedule triggers"},"isActive":{"type":"boolean"},"draftRevision":{"type":"integer","description":"Monotonic revision of the editable draft"},"publishedVersion":{"type":"integer","nullable":true,"description":"Immutable version used by scheduled production runs"},"publishedDraftRevision":{"type":"integer","nullable":true},"publishedAt":{"type":"string","format":"date-time","nullable":true},"hasUnpublishedChanges":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowStep"}},"actions":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowAction"}}}},"WorkflowCreate":{"type":"object","required":["name","triggerType","steps"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"connectionId":{"type":"string"},"projectId":{"type":"string"},"triggerType":{"type":"string","enum":["MANUAL","SCHEDULE"]},"triggerConfig":{"oneOf":[{"$ref":"#/components/schemas/ScheduleConfig"},{"type":"string","description":"JSON-encoded schedule configuration"}]},"steps":{"type":"array","minItems":1,"maxItems":5,"items":{"type":"object","required":["query"],"properties":{"name":{"type":"string"},"query":{"type":"string"},"stopIfEmpty":{"type":"boolean","default":false},"order":{"type":"integer"},"connectionId":{"type":"string","format":"uuid","nullable":true}}}},"actions":{"type":"array","items":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["EMAIL","WEBHOOK"]},"config":{"oneOf":[{"$ref":"#/components/schemas/WebhookActionConfig"},{"type":"string","description":"JSON-encoded action configuration"}]},"order":{"type":"integer"}}}}}},"WorkflowUpdate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"connectionId":{"type":"string","nullable":true},"projectId":{"type":"string","nullable":true},"triggerType":{"type":"string","enum":["MANUAL","SCHEDULE"]},"triggerConfig":{"oneOf":[{"$ref":"#/components/schemas/ScheduleConfig"},{"type":"string","description":"JSON-encoded schedule configuration"}]},"steps":{"type":"array","minItems":1,"maxItems":5,"description":"Complete replacement for the draft query steps.","items":{"$ref":"#/components/schemas/WorkflowStepInput"}},"actions":{"type":"array","maxItems":10,"description":"Complete replacement for the draft delivery actions.","items":{"$ref":"#/components/schemas/WorkflowActionInput"}},"expectedDraftRevision":{"type":"integer","minimum":1,"description":"Required whenever a draft field, step, or action changes. Read the current draftRevision first; a stale revision returns HTTP 409."},"acknowledgedWarnings":{"type":"array","items":{"type":"string"},"description":"Exact warning strings returned by a prior publish attempt. Resubmit them to explicitly confirm publishing."},"isActive":{"type":"boolean"}}},"WebhookActionConfig":{"type":"object","required":["version","url","method","bodyMode"],"properties":{"version":{"type":"integer","const":2},"url":{"type":"string","format":"uri","description":"Public HTTPS destination on port 443. Private and reserved networks are rejected."},"method":{"type":"string","enum":["GET","POST","PUT","PATCH","DELETE"]},"credentialId":{"type":"string","format":"uuid","nullable":true,"description":"Encrypted, destination-bound workflow credential. Secret headers cannot be supplied inline."},"headers":{"type":"array","maxItems":20,"items":{"type":"object","required":["name","value"],"properties":{"name":{"type":"string"},"value":{"type":"string"}}}},"bodyMode":{"type":"string","enum":["NONE","JSON","RAW","FORM_URLENCODED"]},"bodyTemplate":{"type":"string","description":"Supports workflow/query variables such as {{query_1.row_count}} and {{query_1.rows}}. A bare rows placeholder preserves the native JSON array. Wrap it when the destination expects an object, for example Brevo POST /events/batch expects {\"events\":{{query_1.rows}}}."},"contentType":{"type":"string"},"timeoutMs":{"type":"integer","minimum":1000,"maximum":30000,"default":10000},"retry":{"type":"object","properties":{"maxAttempts":{"type":"integer","minimum":1,"maximum":5,"default":3},"baseDelayMs":{"type":"integer","minimum":100,"maximum":30000,"default":500}}},"successStatusCodes":{"type":"array","minItems":1,"maxItems":20,"uniqueItems":true,"description":"Optional exact HTTP statuses considered successful. When omitted, every 2xx status succeeds. For Brevo POST /events/batch use [202], so a partial 207 response is recorded as a failure.","items":{"type":"integer","minimum":100,"maximum":599}},"critical":{"type":"boolean","default":true}}},"WorkflowStep":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"query":{"type":"string"},"stopIfEmpty":{"type":"boolean"},"order":{"type":"integer"},"connectionId":{"type":"string","format":"uuid","nullable":true}}},"WorkflowStepInput":{"type":"object","required":["query"],"properties":{"name":{"type":"string"},"query":{"type":"string"},"stopIfEmpty":{"type":"boolean","default":false},"order":{"type":"integer","minimum":0},"connectionId":{"type":"string","format":"uuid","nullable":true}}},"WorkflowAction":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"config":{"type":"string","description":"Sanitized JSON. Encrypted credential values and legacy inline secrets are never returned."},"order":{"type":"integer"}}},"WorkflowActionInput":{"type":"object","required":["type","config"],"properties":{"type":{"type":"string","enum":["EMAIL","WEBHOOK"]},"config":{"oneOf":[{"$ref":"#/components/schemas/WebhookActionConfig"},{"type":"object","description":"Email action configuration"},{"type":"string","description":"JSON-encoded action configuration"}]},"order":{"type":"integer","minimum":0}}},"WorkflowRun":{"type":"object","properties":{"id":{"type":"string"},"workflowId":{"type":"string"},"trigger":{"type":"string","enum":["MANUAL","SCHEDULE","ACTION_TEST"]},"status":{"type":"string","enum":["PENDING","RUNNING","SUCCESS","PARTIAL_SUCCESS","CONDITION_NOT_MET","FAILED","TIMED_OUT"]},"definitionVersion":{"type":"integer","nullable":true},"scheduledFor":{"type":"string","format":"date-time","nullable":true},"stepResults":{"type":"string","nullable":true,"description":"JSON-encoded query results."},"actionResults":{"type":"string","nullable":true,"description":"JSON-encoded delivery results."},"durationMs":{"type":"integer","nullable":true},"error":{"type":"string","nullable":true},"startedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time","nullable":true},"actionAttempts":{"type":"array","description":"Sanitized outbound delivery attempts. Secret headers and request bodies are never persisted.","items":{"$ref":"#/components/schemas/WorkflowActionAttempt"}}}},"WorkflowPreviewStep":{"type":"object","properties":{"stepId":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["SUCCESS","FAILED"]},"rowCount":{"type":"integer"},"columns":{"type":"array","items":{"type":"string"}},"rows":{"type":"array","maxItems":100,"description":"Raw preview rows. At most 100 rows are returned per step.","items":{"type":"object"}},"executionTimeMs":{"type":"integer"},"conditionMet":{"type":"boolean"},"error":{"type":"string"}}},"WorkflowPreview":{"type":"object","description":"Point-in-time execution of the current draft's query steps. No delivery actions run, no WorkflowRun is created, and these preview rows are not persisted.","properties":{"workflowId":{"type":"string"},"draftRevision":{"type":"integer","nullable":true},"status":{"type":"string","enum":["READY","CONDITION_NOT_MET","FAILED"]},"wouldRunActions":{"type":"boolean"},"actionsConfigured":{"type":"integer"},"rowsLimitedTo":{"type":"integer","const":100},"steps":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowPreviewStep"}}}},"WorkflowActionAttempt":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"runId":{"type":"string","format":"uuid"},"actionId":{"type":"string","format":"uuid","nullable":true},"actionOrder":{"type":"integer"},"attempt":{"type":"integer"},"status":{"type":"string","enum":["RUNNING","SUCCESS","FAILED"]},"method":{"type":"string"},"url":{"type":"string","description":"Sanitized URL without query string or fragment."},"requestBodyBytes":{"type":"integer"},"statusCode":{"type":"integer","nullable":true},"durationMs":{"type":"integer","nullable":true},"responseHeaders":{"type":"string","nullable":true,"description":"Bounded allowlisted response headers as JSON."},"responseBody":{"type":"string","nullable":true,"description":"Bounded, credential-redacted response body."},"error":{"type":"string","nullable":true},"startedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time","nullable":true}}},"WorkflowCredential":{"type":"object","description":"Credential metadata only. Stored secret configuration is never returned.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"kind":{"type":"string","enum":["API_KEY_HEADER","BEARER","BASIC","CUSTOM_HEADERS"]},"allowedHosts":{"type":"array","items":{"type":"string"}},"hasSecret":{"type":"boolean","const":true},"lastTestedAt":{"type":"string","format":"date-time","nullable":true},"lastTestStatus":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WorkflowCredentialConfig":{"oneOf":[{"type":"object","title":"API key header","required":["headerName","value"],"properties":{"headerName":{"type":"string"},"value":{"type":"string","writeOnly":true}}},{"type":"object","title":"Bearer token","required":["token"],"properties":{"token":{"type":"string","writeOnly":true}}},{"type":"object","title":"Basic authentication","required":["username","password"],"properties":{"username":{"type":"string","writeOnly":true},"password":{"type":"string","writeOnly":true}}},{"type":"object","title":"Custom headers","required":["headers"],"properties":{"headers":{"type":"array","minItems":1,"maxItems":20,"writeOnly":true,"items":{"type":"object","required":["name","value"],"properties":{"name":{"type":"string"},"value":{"type":"string"}}}}}}]},"WorkflowCredentialCreate":{"type":"object","required":["name","kind","allowedHosts","config"],"properties":{"name":{"type":"string","maxLength":120},"kind":{"type":"string","enum":["API_KEY_HEADER","BEARER","BASIC","CUSTOM_HEADERS"]},"allowedHosts":{"type":"array","minItems":1,"maxItems":20,"description":"Exact destination hostnames without scheme, port, or path.","items":{"type":"string"}},"config":{"$ref":"#/components/schemas/WorkflowCredentialConfig","writeOnly":true}}},"WorkflowCredentialRotate":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/WorkflowCredentialConfig","writeOnly":true}}},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"url":{"type":"string","format":"uri"},"secret":{"type":"string","description":"Full secret shown only on creation; masked on subsequent reads"},"events":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WebhookEndpointCreate":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"},"description":"Event types to subscribe to, or ['*'] for all"},"isActive":{"type":"boolean","default":true}}},"WebhookEndpointUpdate":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"}}},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"endpointId":{"type":"string"},"event":{"type":"string"},"payload":{"type":"string"},"statusCode":{"type":"integer","nullable":true},"attempts":{"type":"integer"},"deliveredAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"WebhookTestResult":{"type":"object","properties":{"delivery":{"$ref":"#/components/schemas/WebhookDelivery"},"success":{"type":"boolean"},"error":{"type":"string","nullable":true}}},"MetricDefinition":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"formula":{"type":"string","description":"SQL query whose first column of first row yields the metric value"},"connectionId":{"type":"string","nullable":true},"unit":{"type":"string","nullable":true},"dimensions":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"MetricCreate":{"type":"object","required":["name","formula"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"formula":{"type":"string"},"connectionId":{"type":"string"},"unit":{"type":"string"},"dimensions":{"type":"string"}}},"MetricUpdate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"formula":{"type":"string"},"connectionId":{"type":"string"},"unit":{"type":"string"},"dimensions":{"type":"string"}}},"MetricValue":{"type":"object","properties":{"value":{"description":"The computed metric value"},"unit":{"type":"string","nullable":true},"asOf":{"type":"string","format":"date-time"},"executionTime":{"type":"number"}}},"SavedQuery":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"connectionId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"query":{"type":"string"},"parameters":{"type":"string","description":"JSON array of parameter definitions"},"tags":{"type":"string","nullable":true},"isPublic":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"SavedQueryCreate":{"type":"object","required":["name","query","connectionId"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"connectionId":{"type":"string"},"query":{"type":"string"},"parameters":{"type":"string","description":"JSON array of { name, type, required }"},"tags":{"type":"string"},"isPublic":{"type":"boolean","default":true}}},"SavedQueryUpdate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"connectionId":{"type":"string"},"query":{"type":"string"},"parameters":{"type":"string"},"tags":{"type":"string"},"isPublic":{"type":"boolean"}}},"SavedQueryRunRequest":{"type":"object","properties":{"params":{"type":"object","additionalProperties":true,"description":"Key-value pairs for query placeholders"}}},"ApprovalRule":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"connectionId":{"type":"string","nullable":true},"scope":{"type":"string"},"approvers":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ApprovalRuleCreate":{"type":"object","required":["approvers"],"properties":{"connectionId":{"type":"string"},"scope":{"type":"string","default":"all"},"approvers":{"type":"array","items":{"type":"string"},"description":"User IDs of authorized approvers"}}},"ApprovalRuleUpdate":{"type":"object","properties":{"connectionId":{"type":"string","nullable":true},"scope":{"type":"string"},"approvers":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"}}},"QuerySubmitRequest":{"type":"object","required":["connectionId","query"],"properties":{"connectionId":{"type":"string"},"query":{"type":"string"},"context":{"type":"string","description":"Optional description of why this query needs to run"}}},"PendingQuery":{"type":"object","properties":{"id":{"type":"string"},"connectionId":{"type":"string"},"connectionName":{"type":"string","nullable":true},"connectionType":{"type":"string","nullable":true},"apiKeyId":{"type":"string","nullable":true},"query":{"type":"string"},"context":{"type":"string","nullable":true},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED","EXPIRED"]},"reviewNote":{"type":"string","nullable":true},"result":{"nullable":true,"description":"Query result (only present after approval)"},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}},"ApproveRejectRequest":{"type":"object","properties":{"note":{"type":"string","description":"Optional reviewer note"}}},"ApprovalResult":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["APPROVED","REJECTED"]},"reviewedBy":{"type":"string"},"reviewNote":{"type":"string","nullable":true},"result":{"$ref":"#/components/schemas/QueryResult"}}},"UsageRecord":{"type":"object","properties":{"id":{"type":"string"},"orgId":{"type":"string"},"userId":{"type":"string"},"model":{"type":"string"},"promptTokens":{"type":"integer"},"completionTokens":{"type":"integer"},"costCents":{"type":"number"},"feature":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"Budget":{"type":"object","properties":{"included":{"type":"integer","description":"Included budget in cents"},"topUp":{"type":"integer","description":"Top-up budget in cents"},"used":{"type":"integer","description":"Used budget in cents"},"remaining":{"type":"integer","description":"Remaining budget in cents"},"periodStart":{"type":"string","format":"date-time","nullable":true},"periodEnd":{"type":"string","format":"date-time","nullable":true}}},"ApiKey":{"type":"object","properties":{"id":{"type":"string"},"keyPrefix":{"type":"string"},"name":{"type":"string"},"scopes":{"type":"string"},"lastUsedAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time","nullable":true}}},"ApiKeyCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"},"default":["*"],"description":"Permission scopes — use '*' for all"},"expiresAt":{"type":"string","format":"date-time"}}},"ApiKeyCreated":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"keyPrefix":{"type":"string"},"scopes":{"type":"string"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"},"key":{"type":"string","description":"Full API key — only returned at creation time"}}}},"parameters":{"PageParam":{"name":"page","in":"query","schema":{"type":"integer","default":1},"description":"Page number (1-based)"},"PageSizeParam":{"name":"pageSize","in":"query","schema":{"type":"integer","default":20,"maximum":100},"description":"Items per page (max 100)"},"IdParam":{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Resource ID"}},"responses":{"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"BadRequest":{"description":"Validation error or bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Forbidden":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"paths":{"/connections":{"get":{"tags":["Connections"],"summary":"List connections","operationId":"listConnections","description":"Returns paginated list of database connections. Admins see all org connections; regular users see only assigned connections.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated list of connections","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Connection"}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Connections"],"summary":"Create connection","operationId":"createConnection","description":"Create a new database connection. Admin only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionCreate"}}}},"responses":{"201":{"description":"Connection created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Connection"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/connections/{id}":{"get":{"tags":["Connections"],"summary":"Get connection","operationId":"getConnection","description":"Get a single database connection by ID.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Connection details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Connection"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Connections"],"summary":"Update connection","operationId":"updateConnection","description":"Update a database connection. Admin only.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionUpdate"}}}},"responses":{"200":{"description":"Connection updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Connection"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Connections"],"summary":"Delete connection","operationId":"deleteConnection","description":"Delete a database connection. Admin only.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Connection deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/connections/{id}/test":{"post":{"tags":["Connections"],"summary":"Test connection","operationId":"testConnection","description":"Test connectivity to the database and report latency. On the first successful test of a connection with no cached schema, this also introspects and caches the schema + AI overview, so create → test is the complete setup flow. Failures include a structured `diagnosis` (see Diagnosis schema) in error details.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TestResult"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Connection test failed (error.details.diagnosis explains the failure and fix steps)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/connections/{id}/schema":{"get":{"tags":["Connections"],"summary":"Get schema","operationId":"getConnectionSchema","description":"Return the cached introspected database schema.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Schema data","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SchemaResult"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Connections"],"summary":"Introspect schema","operationId":"introspectConnectionSchema","description":"Re-introspect the database schema from the live connection and cache the result.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Freshly introspected schema","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SchemaResult"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Introspection failed (error.details.diagnosis explains the failure and fix steps)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/connections/{id}/query":{"post":{"tags":["Connections"],"summary":"Execute SQL","operationId":"executeQuery","description":"Execute a raw SQL query against the connection and return results.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryRequest"}}}},"responses":{"200":{"description":"Query result","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/QueryResult"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Query execution failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/connections/{id}/annotations":{"get":{"tags":["Connections"],"summary":"List annotations","operationId":"listAnnotations","description":"List schema annotations for a connection, optionally filtered by table.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"},{"name":"table","in":"query","schema":{"type":"string"},"description":"Filter by table name"}],"responses":{"200":{"description":"Paginated list of annotations","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Annotation"}}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Connections"],"summary":"Create or upsert annotation","operationId":"createAnnotation","description":"Create a new schema annotation or update an existing one (upserts on tableName + columnName).","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnotationCreate"}}}},"responses":{"201":{"description":"Annotation created or upserted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Annotation"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/connections/{id}/annotations/{annotationId}":{"get":{"tags":["Connections"],"summary":"Get annotation","operationId":"getAnnotation","description":"Get a single schema annotation by ID.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"name":"annotationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Annotation details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Annotation"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Connections"],"summary":"Update annotation","operationId":"updateAnnotation","description":"Update an existing schema annotation.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"name":"annotationId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnotationUpdate"}}}},"responses":{"200":{"description":"Annotation updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Annotation"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Connections"],"summary":"Delete annotation","operationId":"deleteAnnotation","description":"Delete a schema annotation.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"name":"annotationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Annotation deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/connections/{id}/annotations/auto":{"post":{"tags":["Connections"],"summary":"Auto-generate annotations","operationId":"autoGenerateAnnotations","description":"Use AI to automatically generate schema annotations for all or specified tables. Requires a prior schema introspection.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoAnnotationRequest"}}}},"responses":{"202":{"description":"Auto-annotation queued","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AutoAnnotationResult"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"},"412":{"description":"Schema not yet introspected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/chat":{"post":{"tags":["Chat"],"summary":"Send message","operationId":"sendChatMessage","description":"Send a natural-language message. Returns AI response with optional SQL generation and execution. Set `stream: true` for Server-Sent Events streaming.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"200":{"description":"Chat response (sync mode)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ChatResponse"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"402":{"description":"Credits exhausted or upgrade required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"200 (stream)":{"description":"Server-Sent Events stream (when stream=true). Each event is a JSON object with `type` field."}}}},"/conversations":{"get":{"tags":["Conversations"],"summary":"List conversations","operationId":"listConversations","description":"List chat conversations for the organization, optionally filtered by connectionId.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"},{"name":"connectionId","in":"query","schema":{"type":"string"},"description":"Filter by connection"}],"responses":{"200":{"description":"Paginated list of conversations","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Conversation"}}}}]}}}}}},"post":{"tags":["Conversations"],"summary":"Create conversation","operationId":"createConversation","description":"Create a new empty conversation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationCreate"}}}},"responses":{"201":{"description":"Conversation created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Conversation"}}}]}}}}}}},"/conversations/{id}":{"get":{"tags":["Conversations"],"summary":"Get conversation","operationId":"getConversation","description":"Get a conversation with all its messages.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Conversation with messages","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Conversation"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Conversations"],"summary":"Update conversation","operationId":"updateConversation","description":"Update the conversation title.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationUpdate"}}}},"responses":{"200":{"description":"Conversation updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Conversation"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Conversations"],"summary":"Delete conversation","operationId":"deleteConversation","description":"Delete a conversation and all its messages.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Conversation deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/conversations/{id}/messages":{"get":{"tags":["Conversations"],"summary":"Get messages","operationId":"listConversationMessages","description":"List messages in a conversation, ordered chronologically.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated messages","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Message"}}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/dashboards":{"get":{"tags":["Dashboards"],"summary":"List dashboards","operationId":"listDashboards","description":"List all dashboards for the organization.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated dashboards","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Dashboard"}}}}]}}}}}},"post":{"tags":["Dashboards"],"summary":"Create dashboard","operationId":"createDashboard","description":"Create a new dashboard.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardCreate"}}}},"responses":{"201":{"description":"Dashboard created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Dashboard"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/dashboards/{id}":{"get":{"tags":["Dashboards"],"summary":"Get dashboard","operationId":"getDashboard","description":"Get a dashboard with all its widgets.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Dashboard with widgets","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Dashboard"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Dashboards"],"summary":"Update dashboard","operationId":"updateDashboard","description":"Update dashboard properties.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardUpdate"}}}},"responses":{"200":{"description":"Dashboard updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Dashboard"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Dashboards"],"summary":"Delete dashboard","operationId":"deleteDashboard","description":"Delete a dashboard and all its widgets.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Dashboard deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/dashboards/{id}/widgets":{"get":{"tags":["Dashboards"],"summary":"List widgets","operationId":"listWidgets","description":"List all widgets for a dashboard, ordered by position.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"List of widgets","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Widget"}}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Dashboards"],"summary":"Create widget","operationId":"createWidget","description":"Add a new widget to a dashboard.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetCreate"}}}},"responses":{"201":{"description":"Widget created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Widget"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/dashboards/{id}/widgets/{widgetId}":{"patch":{"tags":["Dashboards"],"summary":"Update widget","operationId":"updateWidget","description":"Update widget properties.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"name":"widgetId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetUpdate"}}}},"responses":{"200":{"description":"Widget updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Widget"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Dashboards"],"summary":"Delete widget","operationId":"deleteWidget","description":"Remove a widget from a dashboard.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"name":"widgetId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Widget deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/dashboards/{id}/widgets/{widgetId}/data":{"get":{"tags":["Dashboards"],"summary":"Get widget data","operationId":"getWidgetData","description":"Execute the widget's SQL query against its connection and return the result set.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"name":"widgetId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Query result for the widget","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/QueryResult"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/workflows":{"get":{"tags":["Workflows"],"summary":"List workflows","operationId":"listWorkflows","description":"List all workflows for the organization.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated workflows","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Workflow"}}}}]}}}}}},"post":{"tags":["Workflows"],"summary":"Create workflow","operationId":"createWorkflow","description":"Create an inactive workflow draft with query steps and optional email or webhook actions. Scheduled execution begins only after publishing by setting isActive to true.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowCreate"}}}},"responses":{"201":{"description":"Workflow created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Workflow"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/workflows/{id}":{"get":{"tags":["Workflows"],"summary":"Get workflow","operationId":"getWorkflow","description":"Get a workflow with its steps and actions.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Workflow details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Workflow"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Workflows"],"summary":"Update workflow","operationId":"updateWorkflow","description":"Replace any draft fields, query steps, or delivery actions. Include expectedDraftRevision whenever the draft changes. Set isActive to true to validate and atomically publish an immutable production version, or false to stop scheduled runs.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowUpdate"}}}},"responses":{"200":{"description":"Workflow updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Workflow"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Draft revision conflict"},"428":{"description":"expectedDraftRevision is required for draft changes"}}},"delete":{"tags":["Workflows"],"summary":"Delete workflow","operationId":"deleteWorkflow","description":"Delete a workflow and its steps, actions, and run history.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Workflow deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/workflows/{id}/run":{"post":{"tags":["Workflows"],"summary":"Trigger workflow","operationId":"triggerWorkflow","description":"Run the current draft immediately, including its configured delivery actions. This has real external side effects.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"201":{"description":"Workflow run completed","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkflowRun"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/workflows/{id}/preview":{"post":{"tags":["Workflows"],"summary":"Preview workflow queries","operationId":"previewWorkflow","description":"Execute only the current draft's query steps and return raw rows, condition state, and whether actions would run. This never executes delivery actions, never creates a WorkflowRun, and does not persist the returned preview rows.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Query-only workflow preview","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkflowPreview"}}}]}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The preview could not be started because no active source connection is available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/workflows/{id}/actions/{order}/test":{"post":{"tags":["Workflows"],"summary":"Test one workflow action","operationId":"testWorkflowAction","description":"Execute one action from the current draft and return its sanitized delivery attempts. This sends a real external request and requires explicit confirmation.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"name":"order","in":"path","required":true,"schema":{"type":"integer","minimum":0}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["confirmDelivery"],"properties":{"confirmDelivery":{"type":"boolean","const":true}}}}}},"responses":{"200":{"description":"Action test succeeded","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkflowRun"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The action test ran but delivery failed; error.details.run contains the run and attempts"},"428":{"description":"confirmDelivery must be true"}}}},"/workflows/{id}/runs":{"get":{"tags":["Workflows"],"summary":"Get run history","operationId":"listWorkflowRuns","description":"List execution history for a workflow, including sanitized per-attempt delivery status, HTTP status codes, retry details, and bounded responses.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated workflow runs","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowRun"}}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/workflow-credentials":{"get":{"tags":["Workflow Credentials"],"summary":"List workflow credentials","operationId":"listWorkflowCredentials","description":"List metadata for encrypted workflow credentials. Requires the workflow_credentials scope and an organization admin role. Secret configuration is never returned.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated credential metadata","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowCredential"}}}}]}}}},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Workflow Credentials"],"summary":"Create workflow credential","operationId":"createWorkflowCredential","description":"Encrypt a credential and bind it to exact outbound destination hostnames. Requires the workflow_credentials scope and an organization admin role. The secret is write-only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowCredentialCreate"}}}},"responses":{"201":{"description":"Credential metadata","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkflowCredential"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"Credential name already exists"}}}},"/workflow-credentials/{id}":{"get":{"tags":["Workflow Credentials"],"summary":"Get workflow credential metadata","operationId":"getWorkflowCredential","description":"Get non-secret credential metadata. Requires the workflow_credentials scope and an organization admin role.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Credential metadata","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkflowCredential"}}}]}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Workflow Credentials"],"summary":"Rotate workflow credential secret","operationId":"rotateWorkflowCredential","description":"Replace only the encrypted secret configuration while preserving its kind and allowed hosts. Requires the workflow_credentials scope and an organization admin role.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowCredentialRotate"}}}},"responses":{"200":{"description":"Updated credential metadata","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WorkflowCredential"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Workflow Credentials"],"summary":"Delete workflow credential","operationId":"deleteWorkflowCredential","description":"Delete a credential only when no workflow draft or active published version references it. Requires the workflow_credentials scope and an organization admin role.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Credential deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Credential is still referenced by a workflow"}}}},"/webhooks":{"get":{"tags":["Webhooks"],"summary":"List endpoints","operationId":"listWebhookEndpoints","description":"List all webhook endpoints for the organization.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated webhook endpoints","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}]}}}}}},"post":{"tags":["Webhooks"],"summary":"Create endpoint","operationId":"createWebhookEndpoint","description":"Create a new webhook endpoint. The signing secret is returned only in the creation response.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"}}}},"responses":{"201":{"description":"Webhook endpoint created (includes full secret)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/webhooks/{id}":{"get":{"tags":["Webhooks"],"summary":"Get endpoint","operationId":"getWebhookEndpoint","description":"Get a webhook endpoint by ID. The secret is masked.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Webhook endpoint (secret masked)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Webhooks"],"summary":"Update endpoint","operationId":"updateWebhookEndpoint","description":"Update webhook endpoint URL, events, or active status.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointUpdate"}}}},"responses":{"200":{"description":"Webhook endpoint updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Webhooks"],"summary":"Delete endpoint","operationId":"deleteWebhookEndpoint","description":"Delete a webhook endpoint and all its delivery history.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Webhook endpoint deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/webhooks/{id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"Get deliveries","operationId":"listWebhookDeliveries","description":"List delivery attempts for a webhook endpoint.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated deliveries","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"summary":"Send test event","operationId":"testWebhookEndpoint","description":"Send a test webhook event to the endpoint and return the delivery result.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Test delivery result","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookTestResult"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/metrics":{"get":{"tags":["Metrics"],"summary":"List metrics","operationId":"listMetrics","description":"List metric definitions for the organization, optionally filtered by connectionId.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"},{"name":"connectionId","in":"query","schema":{"type":"string"},"description":"Filter by connection"}],"responses":{"200":{"description":"Paginated metrics","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MetricDefinition"}}}}]}}}}}},"post":{"tags":["Metrics"],"summary":"Create metric","operationId":"createMetric","description":"Create a new metric definition with an SQL formula.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricCreate"}}}},"responses":{"201":{"description":"Metric created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MetricDefinition"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"description":"A metric with this name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/metrics/{id}":{"get":{"tags":["Metrics"],"summary":"Get metric","operationId":"getMetric","description":"Get a single metric definition by ID.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Metric details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MetricDefinition"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Metrics"],"summary":"Update metric","operationId":"updateMetric","description":"Update metric definition properties.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricUpdate"}}}},"responses":{"200":{"description":"Metric updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MetricDefinition"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Duplicate metric name","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"tags":["Metrics"],"summary":"Delete metric","operationId":"deleteMetric","description":"Delete a metric definition.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Metric deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/metrics/{id}/value":{"get":{"tags":["Metrics"],"summary":"Get metric value","operationId":"getMetricValue","description":"Execute the metric formula and return the current computed value.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"name":"connectionId","in":"query","schema":{"type":"string"},"description":"Override the metric's default connection"}],"responses":{"200":{"description":"Metric value","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MetricValue"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Formula execution failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/saved-queries":{"get":{"tags":["Saved Queries"],"summary":"List saved queries","operationId":"listSavedQueries","description":"List saved queries, optionally filtered by connectionId or tags.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"},{"name":"connectionId","in":"query","schema":{"type":"string"},"description":"Filter by connection"},{"name":"tags","in":"query","schema":{"type":"string"},"description":"Filter by tag substring"}],"responses":{"200":{"description":"Paginated saved queries","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SavedQuery"}}}}]}}}}}},"post":{"tags":["Saved Queries"],"summary":"Create saved query","operationId":"createSavedQuery","description":"Create a new reusable saved query with optional parameterized placeholders.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedQueryCreate"}}}},"responses":{"201":{"description":"Saved query created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SavedQuery"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"description":"Duplicate name","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/saved-queries/{id}":{"get":{"tags":["Saved Queries"],"summary":"Get saved query","operationId":"getSavedQuery","description":"Get a single saved query by ID.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Saved query details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SavedQuery"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Saved Queries"],"summary":"Update saved query","operationId":"updateSavedQuery","description":"Update saved query properties.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedQueryUpdate"}}}},"responses":{"200":{"description":"Saved query updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SavedQuery"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Duplicate name","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"tags":["Saved Queries"],"summary":"Delete saved query","operationId":"deleteSavedQuery","description":"Delete a saved query.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Saved query deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/saved-queries/{id}/run":{"post":{"tags":["Saved Queries"],"summary":"Execute saved query","operationId":"executeSavedQuery","description":"Execute a saved query with optional parameter substitution. Parameters replace {{paramName}} placeholders in the query.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedQueryRunRequest"}}}},"responses":{"200":{"description":"Query execution result","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/QueryResult"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Query execution failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/approval-rules":{"get":{"tags":["Query Approval"],"summary":"List rules","operationId":"listApprovalRules","description":"List query approval rules for the organization. Admin only.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated approval rules","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApprovalRule"}}}}]}}}},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Query Approval"],"summary":"Create rule","operationId":"createApprovalRule","description":"Create a new query approval rule. Admin only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRuleCreate"}}}},"responses":{"201":{"description":"Approval rule created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApprovalRule"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/approval-rules/{id}":{"get":{"tags":["Query Approval"],"summary":"Get rule","operationId":"getApprovalRule","description":"Get a single approval rule by ID. Admin only.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Approval rule details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApprovalRule"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Query Approval"],"summary":"Update rule","operationId":"updateApprovalRule","description":"Update an approval rule. Admin only.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRuleUpdate"}}}},"responses":{"200":{"description":"Approval rule updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApprovalRule"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Query Approval"],"summary":"Delete rule","operationId":"deleteApprovalRule","description":"Delete an approval rule. Admin only.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Approval rule deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResponse"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/queries/submit":{"post":{"tags":["Query Approval"],"summary":"Submit query for approval","operationId":"submitQueryForApproval","description":"Submit a SQL query for human approval before execution. Returns a pending query ID for status polling.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuerySubmitRequest"}}}},"responses":{"202":{"description":"Query submitted for approval","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","properties":{"pendingQueryId":{"type":"string"},"status":{"type":"string","enum":["PENDING"]},"expiresAt":{"type":"string","format":"date-time"}}}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/queries/{id}/status":{"get":{"tags":["Query Approval"],"summary":"Get query status","operationId":"getQueryApprovalStatus","description":"Get the current status of a pending query. Automatically marks expired queries.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Pending query status","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PendingQuery"}}}]}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/queries/pending":{"get":{"tags":["Query Approval"],"summary":"List pending queries","operationId":"listPendingQueries","description":"List all queries awaiting approval. Admin only.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated pending queries","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PendingQuery"}}}}]}}}},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/queries/{id}/approve":{"post":{"tags":["Query Approval"],"summary":"Approve query","operationId":"approveQuery","description":"Approve a pending query and execute it. The query result is returned in the response. Only authorized approvers can approve.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveRejectRequest"}}}},"responses":{"200":{"description":"Query approved and executed","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApprovalResult"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"Query execution failed after approval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/queries/{id}/reject":{"post":{"tags":["Query Approval"],"summary":"Reject query","operationId":"rejectQuery","description":"Reject a pending query with an optional note.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveRejectRequest"}}}},"responses":{"200":{"description":"Query rejected","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["REJECTED"]},"reviewedBy":{"type":"string"},"reviewNote":{"type":"string","nullable":true}}}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/usage":{"get":{"tags":["Usage"],"summary":"Usage records","operationId":"listUsageRecords","description":"List AI usage records for the organization.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/PageSizeParam"}],"responses":{"200":{"description":"Paginated usage records","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageRecord"}}}}]}}}}}}},"/usage/budget":{"get":{"tags":["Usage"],"summary":"Budget info","operationId":"getUsageBudget","description":"Get the current billing period budget including included credits, top-ups, usage, and remaining balance.","responses":{"200":{"description":"Budget summary","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Budget"}}}]}}}}}}},"/keys":{"get":{"tags":["Keys"],"summary":"List API keys","operationId":"listApiKeys","description":"List all active (non-revoked) API keys for the organization. Admin only.","responses":{"200":{"description":"List of API keys","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}}]}}}},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Keys"],"summary":"Create API key","operationId":"createApiKey","description":"Create a new platform API key. The full key is returned only once in the response. Admin only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreate"}}}},"responses":{"201":{"description":"API key created (includes full key)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApiKeyCreated"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/keys/{id}":{"delete":{"tags":["Keys"],"summary":"Revoke API key","operationId":"revokeApiKey","description":"Revoke an API key. The key will no longer be usable for authentication. Admin only.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"API key revoked","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","properties":{"revoked":{"type":"boolean","example":true}}}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}