Overview
This page explains the model behind the API so the request sequence in Getting Started makes sense.
Why Queries Are Asynchronous
Analytics queries run against a columnar data lake, not a transactional database. A query over months of access history can take seconds or minutes depending on how much data it scans — far longer than an HTTP request should stay open.
So the API splits the work into two calls. The first hands your SQL to the query engine and returns immediately with an identifier. The second reports on that identifier, and once the query has finished, gives you somewhere to fetch the results.
sequenceDiagram
participant C as Your client
participant B as Britive API
participant Q as Query engine
participant S as Result storage
C->>B: POST /api/bizintel/analytics/query<br/>{"sql": "SELECT ..."}
B->>Q: Start query execution
B-->>C: 202 {"query_execution_id": "abc-123"}
loop until finished
C->>B: GET /api/bizintel/analytics/query/abc-123
B->>Q: Check execution status
B-->>C: 200 {"status": "RUNNING"}
end
C->>B: GET /api/bizintel/analytics/query/abc-123
B->>Q: Check execution status
B->>S: Sign a time-limited result URL
B-->>C: 200 {"status": "SUCCEEDED", "download_url": "...", "expires_in": 300}
C->>S: GET download_url
S-->>C: results.csv
The Three Stages
Submit
POST your SQL. The API validates that the statement is a single read-only SELECT,
starts the query, and returns 202 Accepted with a query_execution_id. A 202
means the query started — not that it will succeed. A query can still fail later on
a bad column name or a type error.
Poll
GET the status using that id. While the query runs you get {"status": "RUNNING"}
(or "QUEUED"). Poll every 10 seconds — a tighter loop adds load without returning
results any sooner.
Download
Once the status is SUCCEEDED, the response includes a download_url pointing at
the result CSV and an expires_in in seconds. Fetch the URL to get your rows.
Result URLs Are Short-Lived
The download_url is a signed, time-limited link — by default it works for 300
seconds (5 minutes). The expires_in value is the URL’s real remaining lifetime,
not an optimistic upper bound, so you can rely on it for retry logic.
If a URL lapses before you fetch it, poll the same query_execution_id again. The
query does not re-run; you get a freshly signed URL for the same stored results.
The download URL carries its own authorization. Fetch it without an
Authorization header — adding one causes the storage layer to reject the request.
When to Use Britive Analytics Instead
This API returns query data. It has no way to list databases, tables, or columns —
SHOW, DESCRIBE, and EXPLAIN all return 400.
Use Britive Analytics in the console to explore the schema, find the tables you need, and iterate on a query interactively. Once the query is right, move it into your script and use this API to run it on a schedule.
Next Steps
- Getting Started — run your first query end to end.
- API Reference — every field, status code, and SQL rule.