---
title: "API Endpoints - Documentation"
description: "Complete public API reference: queries, dashboards, workflows, connections, webhooks, usage, and keys."
canonical: "https://www.aifordatabase.com/docs/endpoints/"
---

# API Endpoints

advanced 8 min read

## API Endpoints

Reference for the AI for Database API. All paths are relative to `https://app.aifordatabase.com/api/v1`.

For exact request/response schemas, use the live [OpenAPI spec](https://app.aifordatabase.com/api/v1/openapi.json) or the [interactive reference](https://app.aifordatabase.com/api/v1/docs). The spec is maintained alongside the route handlers and is the contract for public v1 integrations.

### Connections

| Method | Path | Description |
| --- | --- | --- |
| GET / POST | `/connections` | List / create connections (create is admin-only) |
| GET / PATCH / DELETE | `/connections/:id` | Read / update / remove a connection |
| POST | `/connections/:id/test` | Test connectivity |
| GET / POST | `/connections/:id/schema` | Read cached schema / introspect now |
| POST | `/connections/:id/query` | Run SQL directly against the connection |
| GET / POST | `/connections/:id/annotations` | List / add schema annotations |
| POST | `/connections/:id/annotations/auto` | AI-generate annotations |

**Create a connection** — `type` must be one of `POSTGRES`, `MYSQL`, `MARIADB`, `MSSQL`, `MONGODB`, `SQLITE`:

```json
{
  "name": "Production DB",
  "type": "POSTGRES",
  "host": "db.example.com",
  "port": 5432,
  "database": "production",
  "username": "aifordb_reader",
  "password": "your-db-password",
  "sslEnabled": true
}
```

The password is write-only — it is never returned by any endpoint. (`encryptedPassword` and `ssl` are accepted as aliases for `password` / `sslEnabled`.)

**Setup flow:** creating a connection stores it; then call `POST /connections/:id/test`. On its first success, the test also introspects your tables and generates the AI schema overview automatically — create → test is the complete setup. Use `POST /connections/:id/schema` to re-introspect after your schema changes.

Failed tests return a structured `diagnosis` in the error details — what stage failed (DNS, connect, TLS, auth, schema read), whose fault it is, and concrete fix steps with your actual host/database/username filled in.

**Connection health:** connections are tested automatically in the background. If a connection fails 3 checks in a row, it's deactivated and the reason is saved — check `lastError` and `lastErrorDiagnosis` on `GET /connections/:id` any time to see why, without having to re-run a test yourself. Subscribe a webhook to `connection.health.degraded` to be notified the moment it happens instead of finding out from a failed query.

### Chat & Conversations

| Method | Path | Description |
| --- | --- | --- |
| POST | `/chat` | Send a natural-language message, get AI-generated SQL and results |
| GET / POST | `/conversations` | List / create conversations |
| GET / PATCH / DELETE | `/conversations/:id` | Manage a conversation |
| GET | `/conversations/:id/messages` | Message history |

### Query Approval

| Method | Path | Description |
| --- | --- | --- |
| POST | `/queries/submit` | Submit a query for approval |
| GET | `/queries/pending` | List queries awaiting approval |
| GET | `/queries/:id/status` | Check approval status |
| POST | `/queries/:id/approve` / `/queries/:id/reject` | Approve or reject |
| GET / POST | `/approval-rules` | List / create auto-approval rules |

### Saved Queries & Metrics

| Method | Path | Description |
| --- | --- | --- |
| GET / POST | `/saved-queries` | List / create saved queries |
| GET / PATCH / DELETE | `/saved-queries/:id` | Manage a saved query |
| POST | `/saved-queries/:id/run` | Execute (with parameters) |
| GET / POST | `/metrics` | List / define metrics |
| GET | `/metrics/:id/value` | Evaluate a metric now |

### Dashboards

| Method | Path | Description |
| --- | --- | --- |
| GET / POST | `/dashboards` | List / create dashboards |
| GET / PATCH / DELETE | `/dashboards/:id` | Manage a dashboard |
| GET / POST | `/dashboards/:id/widgets` | List / add widgets |
| PATCH / DELETE | `/dashboards/:id/widgets/:widgetId` | Update / remove a widget |
| GET | `/dashboards/:id/widgets/:widgetId/data` | Widget's current data |

### Workflows

| Method | Path | Description |
| --- | --- | --- |
| GET / POST | `/workflows` | List workflows / create an inactive draft |
| GET / PATCH / DELETE | `/workflows/:id` | Read, edit, publish/unpublish, or delete |
| POST | `/workflows/:id/preview` | Run only draft queries and return raw rows; never deliver or persist a workflow run |
| POST | `/workflows/:id/run` | Run the current draft, including actions |
| POST | `/workflows/:id/actions/:order/test` | Send one explicitly confirmed action test |
| GET | `/workflows/:id/runs` | Paginated run history |
| GET / POST | `/workflow-credentials` | List metadata / create an encrypted credential |
| GET / PATCH / DELETE | `/workflow-credentials/:id` | Read metadata, rotate the secret, or safely delete |

Workflow creation never schedules an incomplete draft. `PATCH /workflows/:id` can replace the draft's query steps and actions; include the current `draftRevision` as `expectedDraftRevision` so concurrent edits cannot be overwritten. Set `isActive: true` to validate and publish an immutable production version; set it to `false` to stop future scheduled runs. Manual runs use the current draft and have real external side effects.

Webhook action authentication is referenced by an encrypted, exact-host-bound `credentialId`. Create one through `POST /workflow-credentials` using the dedicated `workflow_credentials` scope and an admin-owned API key; the response contains metadata but never the secret. Inline authentication secrets are rejected. Preview the draft first to inspect raw eligible rows without delivery. Then call the action-test endpoint with `{"confirmDelivery":true}`; it sends a real request and returns the run with sanitized HTTP attempts. Run history includes the same attempt status, status code, retry timing, and bounded credential-redacted response data.

By default, every HTTP 2xx response is successful. Set `successStatusCodes` on a webhook action when the destination distinguishes full and partial acceptance. For example, Brevo's batch Events API uses `[202]`: HTTP 207 then becomes a visible failed delivery with the bounded response body instead of a false success.

### Webhooks, Usage & Keys

| Method | Path | Description |
| --- | --- | --- |
| GET / POST | `/webhooks` | List / create signed event webhook endpoints |
| GET / PATCH / DELETE | `/webhooks/:id` | Manage a signed event webhook |
| GET | `/webhooks/:id/deliveries` | Delivery log |
| POST | `/webhooks/:id/test` | Send a test event |
| GET | `/usage` | Usage records |
| GET | `/usage/budget` | Persistent balance in USD cents (fractional cents supported); no expiry or quota periods |
| GET / POST | `/keys` | List / create API keys |
| DELETE | `/keys/:id` | Revoke a key |

Event webhook destinations must use public HTTPS on port 443. Private/reserved networks and unsafe redirects are blocked. Deliveries are HMAC-signed and non-2xx responses are failures; retryable responses are retried.

### Error Codes

| Code | HTTP Status | Description |
| --- | --- | --- |
| `UNAUTHORIZED` | 401 | Missing, invalid, or expired API key |
| `FORBIDDEN` | 403 | Key lacks the required scope, or admin role required |
| `NOT_FOUND` | 404 | Resource does not exist (or belongs to another org) |
| `BAD_REQUEST` | 400 | Malformed JSON body |
| `VALIDATION_ERROR` | 400 | Missing or invalid request fields |
| `PRECONDITION_REQUIRED` | 428 | Draft update omitted `expectedDraftRevision` |
| `CONFIRMATION_REQUIRED` | 428 | Live action test omitted explicit confirmation |
| `ACTION_TEST_FAILED` | 422 | Controlled action delivery ran but failed |
| `PREVIEW_FAILED` | 422 | Workflow queries could not be previewed because a source is unavailable |
| `CONNECTION_FAILED` | 422 | Database connection test failed |
| `INTROSPECTION_FAILED` | 422 | Schema introspection failed |
| `RATE_LIMITED` | 429 | Too many requests |
| `INTERNAL_ERROR` | 500 | Unexpected server error |

Source: https://www.aifordatabase.com/docs/endpoints/
