Datasets & Jobs
Endpoints that connect a Query to the Datasets and Jobs built on top of it: the per-user embedded Dataset a Query produces, the standalone Dataset action, the Jobs that reference the Query, and the Job templates registered for Query-backed Jobs.
These routes require a normal authenticated user. Read access is enforced by the
read_access model scope rather than a permission, so lookups return only the
Query (and its related Datasets and Jobs) the caller may see.
GET /api/queries/{id}/dataset
Get the current user's embedded Dataset for a Query: the embedded Dataset that
is not attached to a Job (resolved by the query.dataset server method).
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query id (UUID) or natural id |
Response:
Responds 200 with the full Dataset as a HAL resource. The handler also sets a
Location header pointing at the Dataset, and the response HAL-embeds the
Dataset's inf:field and inf:filter collections. There is no params-only or
trimmed projection here; this is the same Dataset shape the Datasets API
returns, including its many _links (inf:run, inf:refresh, inf:data,
inf:query, and so on).
When the current user has no unattached embedded Dataset for this Query, the
route answers 404.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002"
},
"inf:draft": {
"href": "https://informer.example.com/api/datasets/admin%3Asales-analysis-query-results/draft"
},
"inf:run": {
"href": "https://informer.example.com/api/datasets/admin%3Asales-analysis-query-results/_run"
},
"inf:benchmark": {
"href": "https://informer.example.com/api/datasets/admin%3Asales-analysis-query-results/_benchmark"
},
"inf:refresh": {
"href": "https://informer.example.com/api/datasets/admin%3Asales-analysis-query-results/_refresh"
},
"inf:data": {
"href": "https://informer.example.com/api/datasets/admin%3Asales-analysis-query-results/data{?start,limit,q,sort,show,report}",
"templated": true
},
"inf:user-settings": {
"href": "https://informer.example.com/api/datasets/admin%3Asales-analysis-query-results/settings"
},
"inf:query": {
"href": "https://informer.example.com/api/queries/00000000-0000-4000-8000-000000000001"
},
"inf:owner": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/owner"
},
"inf:search": {
"href": "https://informer.example.com/api/datasets/admin%3Asales-analysis-query-results/_search{?query,_source,sort,from,size,searchType,aggs,report,aggregations,alias,snapshots}",
"templated": true
},
"inf:mapping": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/mapping"
},
"inf:job-templates": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/job-templates"
},
"inf:fields": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/fields"
},
"inf:count": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/count"
},
"inf:comments": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/comments"
},
"inf:visuals": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/visuals"
},
"inf:visual-templates": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/visual-templates"
},
"inf:dataset-tags": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/tags"
},
"inf:dataset-tag": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/tags/{tagId}",
"templated": true
},
"inf:discover": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/discover"
},
"inf:filters": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/filters"
},
"inf:dataset-shares": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/shares"
},
"inf:flow": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/flow"
},
"inf:group": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/group"
},
"inf:group-rows": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/group-rows"
},
"inf:dataset-share": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/shares/{principalId}",
"templated": true
},
"inf:import": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/_import"
},
"inf:exceptions": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/_exceptions"
},
"inf:search-aggregates": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/_search-aggregates"
},
"inf:exporters": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/exporters"
},
"inf:favorite": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/favorite"
},
"inf:export-bundle": {
"href": "https://informer.example.com/api/datasets/00000000-0000-4000-8000-000000000002/_export"
},
"edit": {
"href": "https://informer.example.com/api/reports/admin%3Asales-analysis-query-results/_edit"
}
},
"naturalId": "admin:sales-analysis-query-results",
"permissions": {
"edit": true,
"share": true,
"delete": true,
"write": true,
"addVisual": true,
"deleteVisual": true,
"changeOwner": true,
"copy": true,
"rename": true,
"refresh": true,
"modifyFlows": true,
"replaceFile": true,
"modifySettings": true,
"createDataView": true,
"assignTags": true,
"createFilter": true,
"scriptFields": true,
"setIndex": false
},
"id": "00000000-0000-4000-8000-000000000002",
"tenant": "acme",
"ownerId": "admin",
"slug": "sales-analysis-query-results",
"name": "Sales Analysis Query Results",
"description": null,
"embedded": true,
"esIndex": null,
"esIndexName": "sales-analysis-query-results",
"esType": "data",
"records": null,
"size": null,
"source": null,
"sourceId": null,
"params": {},
"dataUpdatedAt": null,
"dataExpiresAt": null,
"ttl": null,
"append": false,
"shared": false,
"timestampField": null,
"lastDurationMillis": "1500",
"windowSize": 500,
"settings": {},
"flow": [],
"esId": null,
"lastQueriedAt": null,
"esWorkers": 1,
"datasetFieldReportAccess": false,
"parentId": null,
"templateProcessorId": null,
"deleteDate": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"datasourceId": null,
"reportId": null,
"queryId": "00000000-0000-4000-8000-000000000001",
"editingId": null,
"folderId": null,
"query": {
"naturalId": "admin:sales-analysis-query",
"fields": "(omitted)",
"permissions": {
"assignTags": true,
"changeOwner": true,
"copy": true,
"delete": true,
"edit": true,
"rename": true,
"run": true,
"share": true,
"write": true
},
"id": "00000000-0000-4000-8000-000000000001",
"tenant": "acme",
"ownerId": "admin",
"slug": "sales-analysis-query",
"name": "Sales Analysis Query",
"description": null,
"shared": false,
"embedded": false,
"source": null,
"sourceId": null,
"settings": {},
"inputs": null,
"language": "sql",
"flow": [],
"payload": {
"sql": "select * from orders"
},
"defnUpdatedAt": null,
"limit": -1,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"datasourceId": "00000000-0000-4000-8000-000000000003",
"editingId": null,
"folderId": null,
"datasource": {
"defaultLinkType": "sql",
"aiSystemMessage": "This is a PostgresSQL database. Identifiers are case-sensitive by default. \n Always surround all column names, table names, and schema names in double-quotes (\"). \n For example:\n SELECT \"OrderID\", \"ShipCountry\" FROM \"public\".\"orders\" WHERE \"ShipCity\" = 'Raleigh';\n ---",
"family": "sql",
"languages": [
"informer",
"sql",
"distinctValue",
"… 2 more items (5 total) — omitted from docs"
],
"naturalId": "admin:northwind",
"image": "/opt/informer/packages/informer-server/modules/sql/images/postgres.svg",
"compatibility": [],
"permissions": {
"assignTags": true,
"edit": true,
"delete": true,
"share": true,
"write": true,
"changeOwner": true,
"ping": true,
"scan": true,
"downloadSchema": true,
"importData": true,
"importSchema": true,
"rename": true,
"editConnection": true,
"createLink": true,
"setWrite": true,
"createSuite": true,
"createFieldExpression": true,
"createMapping": false,
"bundle": true,
"query": true
},
"id": "00000000-0000-4000-8000-000000000003",
"tenant": "acme",
"ownerId": "admin",
"slug": "northwind",
"name": "Northwind",
"description": null,
"embedded": false,
"type": "postgres",
"connection": {
"host": "localhost",
"pool": {
"max": 5,
"min": 0,
"idle": 10000,
"acquire": 10000
},
"port": 5432,
"user": "northwinduser",
"database": "northwind",
"password": "encrypted:iv:0000000000000000",
"idleTimeoutMillis": 7
},
"scannedAt": "2026-01-15T16:20:00.000Z",
"schemaUpdatedAt": "2026-01-15T16:20:00.000Z",
"rescanRequired": false,
"shared": false,
"schemas": [
"public"
],
"source": null,
"sourceId": null,
"settings": {
"multiSchema": false,
"useFakeData": false,
"remoteQueryBatchSize": {
"multiKey": 500,
"singleKey": 500
},
"usePreparedStatements": false
},
"data": null,
"appId": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"folderId": null,
"fileId": null,
"shares": []
}
},
"_embedded": {
"inf:field": "(omitted)",
"inf:filter": "(omitted)"
}
}
Embedded Datasets are created per user when a Query runs. Each user gets their own embedded Dataset for the Query, and this route resolves the caller's own.
POST /api/queries/{id}/_create-dataset
Create a standalone Dataset from a Query, seeding its saved Filters and user settings from an existing Dataset.
Authentication: Required
This action creates the Dataset through an internal sub-inject to
dataset.create, so it inherits the datasets:create permission. There is no
separate query:run pre-block on the route.
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query id (UUID) or natural id |
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
dataset | string | Yes (in practice) | Id of an existing Dataset whose saved Filters and user settings are copied onto the new Dataset |
name | string | No | Name for the new Dataset |
description | string | No | Description for the new Dataset |
params | object | No | Parameter values for the new Dataset |
progress | string | No | Progress identifier for tracking the create |
There is no shared or folderId field. The dataset source is required in
practice: without it, the Dataset lookup that copies Filters and settings
answers 404.
Example Request:
{
"name": "Sales Analysis Dataset",
"description": "Standalone dataset for sales analysis",
"dataset": "00000000-0000-4000-8000-000000000002",
"params": {
"region": "West"
}
}
Response:
Responds 200 with the new Dataset's natural id as a bare JSON string (for
example "admin:sales-analysis-dataset"). It does not return a Dataset object,
and it does not use 201.
{
"name": "Sales Analysis Dataset",
"description": "Standalone dataset for sales analysis",
"dataset": "00000000-0000-4000-8000-000000000002",
"params": {
"region": "West"
}
}
"admin:sales-analysis-dataset"
Use the returned natural id to fetch the new Dataset from the Datasets API, then attach it to a Job for scheduled execution or build Reports on top of it.
GET /api/queries/{id}/jobs
List the Jobs whose queryId is this Query.
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query id (UUID) or natural id |
Response:
Responds 200 with a JSON array of Jobs (Job.findAll scoped to this Query),
not a start/count/total envelope. Each Job carries its full column set
(type, enabled, ownerId, queryId, scheduling fields such as startOn
and nextRunAt, and an actions array) plus a permissions object. The array
is empty when the Query has no Jobs.
[
{
"naturalId": "admin:daily-sales-report",
"permissions": {
"assignTags": false,
"write": false,
"edit": false,
"run": false,
"delete": false,
"changeOwner": false,
"rename": false
},
"id": "00000000-0000-4000-8000-000000000002",
"type": "smart-job",
"tenant": "acme",
"slug": "daily-sales-report",
"name": "Daily Sales Report",
"description": null,
"nextRunAt": null,
"lockedAt": null,
"enabled": false,
"data": {},
"interval": null,
"startOn": "2026-01-15T16:20:00.000Z",
"intervalType": null,
"endOn": null,
"notes": null,
"source": null,
"sourceId": null,
"timezone": null,
"heartbeat": null,
"chatId": null,
"createdAt": "2026-01-15T16:20:00.000Z",
"updatedAt": "2026-01-15T16:20:00.000Z",
"ownerId": "admin",
"folderId": null,
"datasetId": null,
"reportId": null,
"queryId": "00000000-0000-4000-8000-000000000001",
"datasourceId": null,
"editingId": null,
"actions": []
}
]
This route returns the Jobs that reference the Query directly through their
queryId.
GET /api/queries/{id}/job-templates
List the Job templates registered for Query-backed Jobs.
Authentication: Required
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Query id (UUID) or natural id |
Response:
Responds 200 with a HAL collection ({ _links, items, start, count, total })
discovered from the job-builder:query driver manager. Each item describes a
template (value.name, value.description, value.materialIcon) and the
skeleton Job it produces under value.job, prefilled with the Query's id. These
are the templates the UI offers when creating a Job from a Query, not a fixed
list of email/export presets.
{
"_links": {
"self": {
"href": "https://informer.example.com/api/queries/00000000-0000-4000-8000-000000000001/job-templates"
}
},
"items": [
{
"detective": "00000000-0000-4000-8000-000000000002",
"id": "00000000-0000-4000-8000-000000000002:0",
"value": {
"group": "__top",
"name": "New Job",
"description": "Run the Query with Filters and input parameters filled out, then perform various actions.",
"materialIcon": "lightbulb_outline",
"queryId": "00000000-0000-4000-8000-000000000001",
"job": {
"name": "Run Sales Analysis Query",
"type": "smart-job",
"datasets": {
"salesAnalysisQuery": {
"queryId": "00000000-0000-4000-8000-000000000001",
"refresh": true
}
},
"data": {
"actions": []
}
}
}
}
],
"start": 0,
"count": 1,
"total": 1
}
Use a template's value.job skeleton as the starting payload when creating a
Job, then fill in the schedule, parameter values, and actions before posting it.