Query Endpoints
The query endpoints allow you to execute semantic queries against your Olytix Core project.
POST /api/v1/query
Execute a semantic query.
Request
curl -X POST http://localhost:8000/api/v1/query \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": ["orders.total_revenue", "orders.count"],
"dimensions": ["orders.region", "orders.order_date.month"],
"filters": [
{
"dimension": "orders.order_date.year",
"operator": "equals",
"value": 2024
},
{
"dimension": "orders.status",
"operator": "notEquals",
"value": "cancelled"
}
],
"order_by": [
{"field": "orders.total_revenue", "direction": "desc"}
],
"limit": 100,
"offset": 0
}'
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
metrics | string[] | Yes | List of metrics to query |
dimensions | string[] | No | Dimensions to group by |
filters | Filter[] | No | Filters to apply |
order_by | OrderBy[] | No | Sort order |
limit | number | No | Max rows (default: 1000) |
offset | number | No | Pagination offset |
time_range | TimeRange | No | Time range filter |
Filter Object
| Field | Type | Description |
|---|---|---|
dimension | string | Dimension to filter |
operator | string | Filter operator |
value | any | Filter value |
Filter Operators
| Operator | Description | Example Value |
|---|---|---|
equals | Exact match | "completed" |
notEquals | Not equal | "cancelled" |
contains | String contains | "ship" |
startsWith | Starts with | "US-" |
endsWith | Ends with | "-2024" |
gt | Greater than | 100 |
gte | Greater than or equal | 100 |
lt | Less than | 1000 |
lte | Less than or equal | 1000 |
between | Range (inclusive) | [10, 100] |
inList | In array | ["A", "B", "C"] |
notInList | Not in array | ["X", "Y"] |
set | Is not null | (no value) |
notSet | Is null | (no value) |
Response
{
"data": [
{
"orders.region": "NORTH",
"orders.order_date.month": "2024-01",
"orders.total_revenue": 125000.00,
"orders.count": 1523
},
{
"orders.region": "NORTH",
"orders.order_date.month": "2024-02",
"orders.total_revenue": 142000.00,
"orders.count": 1687
}
],
"query": {
"sql": "SELECT region, DATE_TRUNC('month', order_date), SUM(amount), COUNT(*) FROM ...",
"duration_ms": 45
},
"meta": {
"total_rows": 48,
"returned_rows": 48,
"cached": false,
"cache_key": "abc123"
}
}
POST /api/v1/query/sql
Get the generated SQL without executing.
Request
curl -X POST http://localhost:8000/api/v1/query/sql \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": ["orders.total_revenue"],
"dimensions": ["orders.region"]
}'
Response
{
"sql": "SELECT\n UPPER(region) AS \"orders.region\",\n SUM(total_amount) AS \"orders.total_revenue\"\nFROM fct_orders\nGROUP BY UPPER(region)"
}
POST /api/v1/query/async
Start an asynchronous query for large datasets.
Request
curl -X POST http://localhost:8000/api/v1/query/async \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": ["orders.total_revenue"],
"dimensions": ["orders.customer_id"],
"limit": 1000000
}'
Response
{
"job_id": "job_abc123",
"status": "pending",
"created_at": "2024-01-20T10:30:00Z",
"poll_url": "/api/v1/query/async/job_abc123"
}
GET /api/v1/query/async/{job_id}
Check async query status.
Response (In Progress)
{
"job_id": "job_abc123",
"status": "running",
"progress": 45,
"started_at": "2024-01-20T10:30:01Z"
}
Response (Complete)
{
"job_id": "job_abc123",
"status": "complete",
"completed_at": "2024-01-20T10:30:45Z",
"result_url": "/api/v1/query/async/job_abc123/result",
"row_count": 500000
}
GET /api/v1/query/async/{job_id}/result
Get async query results.
Response
{
"data": [...],
"meta": {
"total_rows": 500000
}
}
Error Responses
400 Bad Request
{
"error": {
"code": "INVALID_QUERY",
"message": "Metric 'invalid_metric' not found",
"details": {
"available_metrics": ["orders.total_revenue", "orders.count"]
}
}
}
408 Request Timeout
{
"error": {
"code": "QUERY_TIMEOUT",
"message": "Query exceeded 30 second timeout",
"suggestion": "Use async query endpoint for large datasets"
}
}