Core CRUD
Basic query creation, retrieval, update, and deletion operations.
GET /api/queries
Search and filter queries with pagination and aggregations.
Authentication: Required
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | - | Full-text search query (searches slug, name, description) |
datasource | string | - | Filter by datasource ID |
sort | string | name | Sort field (prefix with - for descending) |
limit | integer | 30 | Results per page |
start | integer | 0 | Pagination offset |
Response:
The response is a paginated HAL collection. Query items are returned under _embedded["inf:query"], each with an embedded datasource.
{
"_links": {
"self": { "href": "/api/queries{?sort,limit,start,q,embedded,expand,dataUpdatedAt}", "templated": true },
"next": { "href": "/api/queries?start=30&limit=30" }
},
"_embedded": {
"inf:query": [
{
"_links": {
"self": { "href": "/api/queries/550e8400-..." },
"inf:run": { "href": "/api/queries/analytics:sales-query/_run" },
"inf:execute": { "href": "/api/queries/analytics:sales-query/_execute" },
"inf:draft": { "href": "/api/queries/analytics:sales-query/draft" }
},
"_embedded": {
"inf:datasource": {
"_links": { "self": { "href": "/api/datasources/a1b2c3d4-..." } },
"id": "a1b2c3d4-...",
"name": "Production MySQL",
"type": "mysql",
"embedded": false
}
},
"id": "550e8400-...",
"slug": "sales-query",
"name": "Sales Analysis Query",
"description": "Quarterly sales data with regional breakdowns",
"language": "sql",
"ownerId": "analytics",
"datasourceId": "a1b2c3d4-...",
"shared": true,
"embedded": false,
"source": "dataset",
"sourceId": { "datasetId": "sales-2024" },
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-02-08T14:30:00.000Z",
"defnUpdatedAt": "2024-02-08T14:30:00.000Z"
}
]
},
"start": 0,
"count": 1,
"total": 42,
"aggs": {
"datasource": [
{ "id": "a1b2c3d4-...", "label": "Production MySQL", "value": 28 },
{ "id": "e5f6a7b8-...", "label": "Analytics DB", "value": 14 }
],
"total": 42
},
"permissions": {
"create": true
}
}
Each embedded query includes an _embedded["inf:datasource"] with the query's datasource details. The aggs.datasource array provides counts by datasource for building filter UIs.
Use the datasource parameter to filter queries by datasource before applying full-text search for better performance.
GET /api/queries-list
Get a complete list of readable queries with full details (no pagination).
Authentication: Required
Response:
Returns an array of all queries the user can read, including tag information, owner details, and datasource metadata. This endpoint is optimized for building query selectors and dropdowns.
[
{
"id": "550e8400-...",
"naturalId": "analytics:sales-query",
"name": "Sales Analysis Query",
"description": "Quarterly sales data",
"source": "dataset",
"sourceId": { "datasetId": "sales-2024" },
"datasourceType": "mysql",
"datasourceName": "Production MySQL",
"ownerId": "analytics",
"ownerName": "Analytics Team",
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-02-08T14:30:00.000Z",
"tags": ["tag-uuid-1", "tag-uuid-2"],
"sharing": [
{ "principalId": "marketing", "accessLevel": 2 }
],
"permissions": {
"write": true,
"edit": true,
"delete": true,
"run": true,
"copy": true,
"share": true,
"rename": true,
"assign-tags": true,
"change-owner": true
}
}
]
GET /api/queries/{id}
Get a single query by ID or natural ID.
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query ID (UUID) or natural ID (ownerId:slug) |
Response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"naturalId": "team:analytics:sales-query",
"slug": "sales-query",
"name": "Sales Analysis Query",
"description": "Quarterly sales data with regional breakdowns",
"language": "sql",
"datasourceId": "mysql-prod",
"payload": {
"sql": "SELECT * FROM sales WHERE date >= :startDate",
"fields": [
{ "id": "date", "name": "Sale Date", "type": "date" },
{ "id": "amount", "name": "Amount", "type": "number" }
]
},
"inputs": {
"startDate": {
"type": "date",
"label": "Start Date",
"default": "2024-01-01"
}
},
"flow": [],
"fields": {
"date": { "format": "MM/DD/YYYY" },
"amount": { "format": "$0,0.00" }
},
"settings": {
"timeout": 60000
},
"limit": -1,
"embedded": false,
"shared": true,
"ownerId": "team:analytics",
"folderId": null,
"tags": ["tag-uuid-1", "tag-uuid-2"],
"createdAt": "2024-01-15T10:00:00.000Z",
"updatedAt": "2024-02-08T14:30:00.000Z",
"defnUpdatedAt": "2024-02-08T14:30:00.000Z",
"permissions": {
"write": true,
"edit": true,
"delete": true,
"run": true,
"copy": true,
"share": true,
"rename": true,
"assign-tags": true,
"change-owner": true
},
"_links": {
"self": { "href": "/api/queries/550e8400-..." },
"edit": { "href": "/api/queries/550e8400-..." },
"inf:run": { "href": "/api/queries/analytics:sales-query/_run" },
"inf:benchmark": { "href": "/api/queries/analytics:sales-query/_benchmark" },
"inf:execute": { "href": "/api/queries/analytics:sales-query/_execute" },
"inf:draft": { "href": "/api/queries/analytics:sales-query/draft" },
"inf:dataset": { "href": "/api/queries/analytics:sales-query/dataset" },
"inf:comments": { "href": "./comments" },
"inf:query-shares": { "href": "./shares" },
"inf:query-tags": { "href": "./tags" },
"inf:favorite": { "href": "./favorite" },
"inf:owner": { "href": "./owner" },
"inf:user-settings": { "href": "/api/queries/analytics:sales-query/settings" },
"inf:input-templates": { "href": "/api/queries/analytics:sales-query/input-templates" },
"inf:export-bundle": { "href": "./_export" }
},
"_embedded": {
"inf:datasource": {
"_links": { "self": { "href": "/api/datasources/a1b2c3d4-..." } },
"id": "a1b2c3d4-...",
"name": "Production MySQL",
"type": "mysql",
"embedded": false
},
"inf:query-language": {
"id": "sql",
"name": "SQL",
"type": "sql",
"editable": true
}
}
}
Queries can be referenced by UUID or by natural ID in the format ownerId:slug (e.g., team:analytics:sales-query).
POST /api/queries
Create a new query.
Authentication: Required
Permission: queries:create
Request Body:
{
"name": "Customer Revenue Query",
"description": "Monthly customer revenue aggregations",
"language": "sql",
"datasourceId": "mysql-prod",
"payload": {
"sql": "SELECT customer_id, SUM(revenue) FROM orders GROUP BY customer_id"
},
"inputs": {},
"flow": [],
"settings": {},
"fields": {}
}
Validation:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Query display name |
description | string | No | Query description |
language | string | Yes | Query language (e.g., sql, i5-ql) |
datasourceId | string | Yes | Datasource UUID |
payload | object | No | Language-specific query definition |
inputs | object | No | Input parameter definitions |
flow | array | No | Transformation steps (default: []) |
settings | object | No | Query settings |
fields | object | No | Field metadata and formatting |
Response:
Returns the created query with a 201 Created status and Location header pointing to the new query.
PUT /api/queries/{id}
Update an existing query.
Authentication: Required
Permission: query:write
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query ID (UUID) or natural ID |
Request Body:
{
"name": "Updated Query Name",
"description": "Updated description",
"datasourceId": "postgres-analytics",
"payload": {
"sql": "SELECT * FROM updated_table"
},
"inputs": {
"filter": { "type": "string", "label": "Filter" }
},
"flow": [],
"settings": { "timeout": 120000 },
"fields": {},
"shared": true,
"folderId": "folder-uuid",
"limit": 1000
}
Validation:
All fields are optional. Only provided fields will be updated.
| Field | Type | Description |
|---|---|---|
name | string | Query display name |
description | string | Query description (can be empty string) |
language | string | Query language |
datasourceId | string | Datasource UUID |
payload | object | Language-specific query definition |
inputs | object | Input parameters (can be null) |
flow | array | Transformation steps |
settings | object | Query settings |
fields | object | Field metadata (can be null) |
shared | boolean | Whether query is shared |
folderId | string | Folder ID (can be null) |
limit | integer | Row limit |
Response:
Returns the updated query with 200 OK status.
Query payloads are limited by tenant configuration (default: 10MB). Large queries may be rejected.
PATCH /api/queries/{id}
Partially update a query using JSON Patch operations.
Authentication: Required
Permission: query:write
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query ID (UUID) or natural ID |
Request Body:
[
{ "op": "replace", "path": "/name", "value": "New Query Name" },
{ "op": "add", "path": "/settings/timeout", "value": 90000 },
{ "op": "remove", "path": "/folderId" }
]
Supported Operations:
add- Add or update a propertyreplace- Replace a property valueremove- Remove a property (converted to setnull)
Response:
Returns the updated query with 200 OK status.
DELETE /api/queries/{id}
Delete a query.
Authentication: Required
Permission: query:write
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query ID (UUID) or natural ID |
Response:
Returns 204 No Content on success.
Deleting a query will also delete:
- Associated drafts
- Query shares
- Comments
- Tag associations
- Embedded datasets (if embedded query)
GET /api/queries/{id}/permissions
Get the effective permissions for a query.
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query ID (UUID) or natural ID |
Response:
{
"write": true,
"edit": true,
"delete": true,
"run": true,
"copy": true,
"share": true,
"rename": true,
"assign-tags": true,
"change-owner": true
}
Permission Breakdown:
| Permission | Description |
|---|---|
write | Can modify query definition, settings, fields |
run | Can execute query to generate datasets |
copy | Can create copies of the query |
edit | Can edit the query (usually delegates to write) |
delete | Can delete the query (usually delegates to write) |
rename | Can rename the query |
share | Can manage query shares and access control |
assign-tags | Can add/remove tags |
change-owner | Can transfer ownership |
Permissions are evaluated based on team roles for team-owned queries or ownership for user-owned queries. Embedded queries require Data Wizard role, while ad-hoc queries require Designer role for write access.