Skip to content

REST API Reference

Every action in the Datarelix UI is a REST endpoint, and the same endpoints are available programmatically. Base URL: https://app.datarelix.ai. Most routes live under /api/v1; sign-in routes are at the root (/auth/...). An interactive reference (Swagger / ReDoc) and the OpenAPI schema are served by the app itself.

Authentication

Two credentials are accepted, and either one is enough:

  • A browser session cookie — set when you sign in. This is what the app itself uses; no key involved.
  • An X-API-Key header — for server-to-server calls.
Terminal window
curl -H "X-API-Key: $DATARELIX_API_KEY" \
https://app.datarelix.ai/api/v1/connections

API keys are issued on request, not self-serve — there is no key-generation screen in the app. Contact us if you need one. Full details, including what happens when both credentials are present, are in Authentication.

Execution

POST /api/v1/run # run a question, returns the finished RunResult
POST /api/v1/run/stream # same, as an SSE stream of progress + artifacts
GET /api/v1/runs # ?connection_id= &status= &limit= (max 100) &offset=
GET /api/v1/runs/{run_id}

Note the path is run (singular) for execution and runs (plural) for history. There is no endpoint to cancel a run — a run is cancelled by closing the SSE stream. (The one cancel endpoint in the API belongs to background schema-discovery jobs, below.)

Request body for both execution routes:

FieldTypeNotes
questionstringRequired, 1–2000 characters.
connection_idstringRequired.
conversation_idstringOptional — continues an existing conversation instead of starting one.
chart_requestedbooleanOptional, default false. Set when the user asked for a chart.
selected_tables_overridestring[]Optional — restrict this run’s table scope.
selected_columns_overrideobjectOptional — table name → column names, for this run only.

Artifacts

GET /api/v1/artifacts/{artifact_id}
GET /api/v1/artifacts/{artifact_id}/download
GET /api/v1/artifacts/{artifact_id}/render # ?format=png|svg — server-side chart render
GET /api/v1/runs/{run_id}/artifacts/{artifact_id}/csv # ?rerun=true to bypass the cache
POST /api/v1/runs/{run_id}/artifacts/{artifact_id}/refresh

CSV export and refresh are addressed through their run — the run id is part of the path, and it’s what ownership is checked against.

Connections

GET /api/v1/connections # ?tag=
POST /api/v1/connections
GET /api/v1/connections/{id}
PATCH /api/v1/connections/{id}
DELETE /api/v1/connections/{id}
POST /api/v1/connections/{id}/test
POST /api/v1/connections/{id}/duplicate
POST /api/v1/connections/{id}/paused # body: { "paused": true | false }
PUT /api/v1/connections/{id}/tags
GET /api/v1/connections/dialects # supported engines + auth modes + availability
GET /api/v1/connections/auth-modes # ?dialect=postgres (required)

GET /api/v1/connections/dialects is the authoritative list of engines and the auth modes each one supports — read it rather than hard-coding a list.

POST /api/v1/connections/{id}/paused is how you free a connection slot without deleting anything; see Billing & plans.

Schema

GET /api/v1/connections/{id}/schemas # schemas / datasets / databases in scope
GET /api/v1/schema/{connection_id}/tables
GET /api/v1/schema/{connection_id}/tables/{table_name}
GET /api/v1/connections/{id}/metadata/status # is the analyzed metadata stale?
PUT /api/v1/connections/{id}/metadata # curated table/column descriptions, keys
PUT /api/v1/connections/{id}/schema-overrides # key/relationship overrides used when planning
PUT /api/v1/connections/{id}/schema-selection # persisted table + column selection
PUT /api/v1/connections/{id}/selected-tables

Table listing lives under /api/v1/schema/{connection_id}/..., not under the connection. There is no /connections/{id}/schema endpoint.

Schema discovery

POST /api/v1/connections/{id}/introspect # structure only, no AI
POST /api/v1/connections/{id}/discover # AI schema analysis, blocking
POST /api/v1/connections/{id}/discover/stream # AI schema analysis, SSE
POST /api/v1/connections/{id}/discover/cross-schema # relationships only, reuses metadata
POST /api/v1/connections/{id}/discover/jobs # start (or re-attach to) a background job
GET /api/v1/connections/{id}/discover/jobs/active
GET /api/v1/connections/{id}/discover/jobs/{job_id}
GET /api/v1/connections/{id}/discover/jobs/{job_id}/stream
POST /api/v1/connections/{id}/discover/jobs/{job_id}/cancel # 202, best-effort

Background jobs are the path the app uses: a job survives navigating away, and the stream can be re-attached. Starting a fresh AI schema analysis consumes one from your monthly allowance; resuming or retrying a job that reuses existing discovery does not.

Conversations

GET /api/v1/conversations # ?connection_id= &limit= (max 100) &offset=
GET /api/v1/conversations/{id}
GET /api/v1/conversations/{id}/runs
DELETE /api/v1/conversations/{id}
DELETE /api/v1/conversations/{id}/runs/from/{from_turn_index}

The last one is the truncate operation — it’s a DELETE addressed at a turn index, and it removes that turn and everything after it. This is what “edit an earlier message and re-ask” does under the covers.

Query templates

GET /api/v1/connections/{id}/templates
POST /api/v1/connections/{id}/templates
PUT /api/v1/templates/{template_id}
DELETE /api/v1/templates/{template_id}

Dashboards

GET /api/v1/dashboards
POST /api/v1/dashboards
GET /api/v1/dashboards/{id}
PUT /api/v1/dashboards/{id}
DELETE /api/v1/dashboards/{id}
POST /api/v1/dashboards/{id}/refresh
POST /api/v1/dashboards/{id}/items
PUT /api/v1/dashboards/{id}/items/reorder
PUT /api/v1/dashboards/{id}/items/{item_id}
DELETE /api/v1/dashboards/{id}/items/{item_id}
POST /api/v1/dashboards/{id}/items/{item_id}/refresh

Updating a dashboard is PUT, not PATCH. Reordering is PUT .../items/reorder — a nested route under items, not a top-level reorder.

Chart styling

GET /api/v1/conversations/{id}/style
POST /api/v1/conversations/{id}/style # apply a style patch directly, no AI
GET /api/v1/conversations/{id}/charts/restyle # ?run_id= &artifact_id=
GET /api/v1/style/presets

Billing and workspace

GET /api/v1/billing/summary # plan, status, usage this month, seats
POST /api/v1/billing/checkout # returns a Stripe Checkout URL
POST /api/v1/billing/portal # returns a Stripe customer portal URL
GET /api/v1/workspace # your workspace: roster for owners, summary for members
POST /api/v1/workspace/invites
DELETE /api/v1/workspace/invites/{invite_id}
POST /api/v1/workspace/invites/accept
DELETE /api/v1/workspace/members/{member_user_id}

Workspace routes only do anything on a Team plan. Plan behaviour is described in Billing & plans; the error codes these return are in Error codes.

POST /api/v1/billing/webhook also exists — it is Stripe’s callback, authenticated by signature, and is not callable by you.

Account

GET /auth/me
GET /auth/me/onboarding-status
GET /auth/providers # which sign-in methods are enabled
POST /auth/email/register
POST /auth/email/login
POST /auth/email/forgot-password
POST /auth/email/reset-password
POST /auth/email/verify
POST /auth/refresh
POST /auth/logout

These are at the root, not under /api/v1. See Authentication.

Streaming a run

POST /api/v1/run/stream returns server-sent events. Each event has a name and a JSON payload.

Terminal window
curl -N -X POST https://app.datarelix.ai/api/v1/run/stream \
-H "X-API-Key: $DATARELIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "conn_abc",
"question": "Top 10 customers by revenue last quarter",
"chart_requested": true
}'

Events you’ll see:

EventPayload
status{ phase: "building_context" | "planning" | "executing" }
step_start{ index, op, ref }
step_complete{ index, status, elapsed_ms }
error{ type, message, recoverable }
completeThe full run result

The connection is kept alive with periodic heartbeat comments, so don’t treat a quiet stream as a dead one. To continue a conversation, pass conversation_id in the request body.

Failures are described by error codes.

Idempotency

Run creation is not idempotent — each call creates a new run. To replay a question, re-issue the same payload; to replay it in place within a conversation, truncate from the turn index first (DELETE /api/v1/conversations/{id}/runs/from/{from_turn_index}) and then ask again.

Rate limits and quotas

Two different things throttle you, and they return different bodies:

  • Rate limit — a fixed per-minute request limit, currently 20 requests per minute, counted per API key (or per signed-in user when you’re using a session). Exceeding it returns 429 with a plain-string detail and Retry-After, X-RateLimit-Limit, and X-RateLimit-Remaining headers.
  • Plan quotas — monthly questions, monthly AI schema analyses, connection limits. These return a structured body with a code you can branch on. See Error codes.

Branch on the response body’s code, never on the status alone — 429 is shared by the rate limiter and the quota system.