Skip to content
ABRQ DATADocs Abrq DIP · latest
Product page Request a trial
On this page

API

Conventions#

Every application endpoint lives under /api/v1. Requests and responses are JSON unless stated otherwise. The self-hosted OpenAPI document is served by the instance itself — see Discovery — and is the exact route list for your version. This page documents the shapes and rules that hold across all of them.

Authentication#

Three credential types reach the API.

Access tokens#

A bearer JWT with a 15-minute lifetime:

curl -H "Authorization: Bearer <ACCESS_TOKEN>" \
  https://<ABRQ_HOST>/api/v1/data-connectors

Refresh tokens#

The refresh token is never returned in a response body. It is set as an httpOnly, SameSite=strict cookie named abrq_refresh, scoped to the path /api/v1/auth, so it is only ever sent to the auth endpoints.

Refresh is rotating with reuse detection: each refresh invalidates the token it consumed. Presenting an already-consumed refresh token is treated as theft and revokes the whole session — every token in that chain stops working and the user must sign in again.

Personal access tokens#

Long-lived tokens for scripts and integrations. They are prefixed abrq_ and are shown once, at creation.

  • Scope is read or write, enforced centrally rather than per route. A read token receives 403 on any unsafe method (POST, PUT, PATCH, DELETE), whatever the endpoint.
  • A token may optionally be scoped to a project, in which case it cannot see or touch anything outside it.
curl -H "Authorization: Bearer abrq_<TOKEN>" \
  https://<ABRQ_HOST>/api/v1/executions

Server-sent events#

EventSource cannot set request headers, so SSE endpoints authenticate with a query parameter instead:

GET /api/v1/cdc-tables/<CDC_TABLE_ID>/logs/stream?token=<ACCESS_TOKEN>

Warning. A token in a query string is visible to proxies and access logs. Use a short-lived access token for SSE, never a personal access token.

Error envelope#

Every error response uses the same envelope:

{
  "detail": "Data connector not found",
  "request_id": "5e1c0f6a-2b41-4f8f-9f2a-7d0b1c3e4a55"
}

detail is a human-readable message; request_id correlates the response with the structured log line for that request — quote it in any support conversation. Some errors add extra top-level keys, described below.

Status mapping#

Status Meaning
400 Malformed request the schema could not even parse
401 Authentication problem — missing, expired, invalid or revoked token
403 Permission denied, insufficient token scope, or a licensing refusal
404 The addressed resource does not exist, or is outside your project scope
409 Conflict with existing state — a duplicate name, or a resource already bound
422 Request parsed, but a field failed validation
429 Rate limit exceeded
500 Unhandled server error; the request_id is the way to find it in the logs

Structured 403 codes#

Two of the 403 cases carry machine-readable structure beyond detail.

RBAC refusalpermission_denied:

{
  "detail": "permission_denied",
  "reason": "not_a_member",
  "required_capability": "connector:write",
  "project_id": "3f0b0d4c-8f1e-4a0e-9d1b-1c2f3a4b5c6d",
  "environment_id": null,
  "request_id": "0c9f2b1a-77d3-4a41-9d2e-6b0a5c8e1f30"
}

License refusallicense_expired:

{
  "detail": "license_expired",
  "request_id": "b2d4f6a8-1c3e-4f50-8a9b-0d1e2f3a4b5c"
}

A license_expired response means the instance has dropped into read-only mode: reads continue to work, writes are refused platform-wide.

Rate limits#

Scope Limit
All endpoints 100 requests / minute
Login 10 requests / minute

Two headers accompany rate-limited routes:

Header Meaning
X-RateLimit-Remaining Requests left in the current window
X-RateLimit-Reset When the current window resets

Health, metrics and discovery#

GET /health#

{
  "status": "ok",
  "version": "1.4.1",
  "commit": "cdcbcc8",
  "deps": {
    "framework_db": "ok",
    "redis": "ok"
  }
}

Returns 200 when both dependencies report ok, and 503 otherwise. Both the framework database and Redis must be healthy for the instance to be considered up.

Note. GET /health is the only health endpoint. There is no /ready, no /readyz, and no /healthz. Point every liveness and readiness probe at /health and treat the same endpoint as both.

GET /metrics#

Prometheus text exposition of every metric the backend exposes. See Metrics.

OpenAPI#

A self-hosted instance serves its own interactive API documentation at /docs and the raw schema at /openapi.json. Those are the authoritative route list for the version you are running.

Route-prefix inventory#

The API is organised into the prefixes below. These are prefixes, not callable paths — read /openapi.json on your instance for the concrete routes and their parameters.

Area Prefixes under /api/v1
Identity and access auth, users, me, api-tokens, sso, ldap
Audit audit-log, audit-forwarder-settings
Connectivity data-connectors
Ingestion cdc-tables, streams, inboxes, email-feeds, file-ingestions
Delivery exports
Alerting notification-configs, notification-settings, alert-rules
Platform license, admin
Metadata and governance lineage, catalog, masking-policies, retention-policies
Operations overview, executions, schedules/dashboard
Modelling and AI dw-models, ai-providers
ETL the etl/* family

Streaming endpoints#

Two endpoints stream server-sent events rather than returning a body:

Stream Purpose
CDC log tail Live run-log lines for one CDC table
Stream runs Live run status for one stream

Both authenticate with ?token= as described above.