Skip to main content

Drafts & Versioning

Create and manage draft copies of queries for safe editing without affecting production queries or cached data.

Draft Workflow

The draft workflow allows users to:

  1. Create a personal draft copy of a query
  2. Make changes to the draft without affecting the original
  3. Commit the draft to update the original query
  4. Discard the draft if changes are unwanted

Each user gets their own draft instance, allowing multiple users to experiment with changes simultaneously.

POST /api/queries/{id}/_edit

Create or retrieve a draft copy of a query for editing.

Authentication: Required Permission: query:write

Path Parameters:

ParameterTypeDescription
idstringQuery ID (UUID) or natural ID of the original query

Response:

If a draft already exists for the current user, it is returned. Otherwise, a new draft is created.

{
"id": "draft-uuid",
"naturalId": "draft-uuid",
"name": "Sales Analysis Query (Draft)",
"description": "Quarterly sales data with regional breakdowns",
"language": "sql",
"datasourceId": "mysql-prod",
"payload": {
"sql": "SELECT * FROM sales WHERE date >= :startDate"
},
"inputs": {
"startDate": {
"type": "date",
"label": "Start Date",
"default": "2024-01-01"
}
},
"flow": [],
"fields": {},
"settings": {},
"limit": -1,
"embedded": false,
"editingId": "550e8400-e29b-41d4-a716-446655440000",
"ownerId": "john.doe",
"createdAt": "2024-02-09T10:00:00Z",
"updatedAt": "2024-02-09T10:00:00Z",
"_links": {
"self": { "href": "/api/queries/draft-uuid" }
}
}

Draft Properties:

PropertyDescription
editingIdID of the original query being edited
ownerIdUser ID of the draft owner (not team)
nameOriginal name with " (Draft)" suffix
Single Draft Per User

Each user can have only one draft per query. Calling this endpoint multiple times returns the same draft instance.


GET /api/queries/{id}/draft

Get the current user's draft for a query.

Authentication: Required

Path Parameters:

ParameterTypeDescription
idstringQuery ID (UUID) or natural ID of the original query

Response:

Returns 404 if no draft exists for the current user. Otherwise returns the draft query.

{
"id": "draft-uuid",
"name": "Sales Analysis Query (Draft)",
"editingId": "550e8400-e29b-41d4-a716-446655440000",
"hasUserSettings": true,
"ownerId": "john.doe",
"_links": {
"self": { "href": "/api/queries/draft-uuid" },
"inf:original": { "href": "/api/queries/550e8400-e29b-41d4-a716-446655440000" },
"inf:commit-draft": { "href": "/api/queries/550e8400-e29b-41d4-a716-446655440000/draft/_commit" }
},
"_embedded": {
"inf:datasource": {
"id": "mysql-prod",
"name": "Production MySQL",
"type": "mysql"
}
}
}

Additional Properties:

PropertyDescription
hasUserSettingsWhether any users have custom settings for this query

PUT /api/queries/{id}/draft

Create or update a draft with specific changes.

Authentication: Required Permission: query:write

Path Parameters:

ParameterTypeDescription
idstringQuery ID (UUID) or natural ID of the original query

Request Body:

{
"language": "sql",
"payload": {
"sql": "SELECT * FROM sales WHERE region = :region AND date >= :startDate"
},
"inputs": {
"region": {
"type": "string",
"label": "Sales Region",
"default": "West"
},
"startDate": {
"type": "date",
"label": "Start Date"
}
},
"flow": [],
"datasourceId": "mysql-prod",
"settings": { "timeout": 90000 },
"fields": {
"region": { "format": "uppercase" }
}
}

Validation:

FieldTypeRequiredDescription
languagestringNoQuery language
payloadobjectNoLanguage-specific query definition
inputsobjectNoInput parameter definitions
flowarrayNoTransformation steps
datasourceIdstringNoDatasource UUID
settingsobjectNoQuery settings
fieldsobjectNoField metadata (default: {})

Response:

Returns the created or updated draft with 200 OK status and Location header.

Testing Changes

After updating a draft, use POST /api/queries/{draftId}/_execute to test the query without committing changes.


DELETE /api/queries/{id}/draft

Discard the current user's draft for a query.

Authentication: Required Permission: query:write

Path Parameters:

ParameterTypeDescription
idstringQuery ID (UUID) or natural ID of the original query

Response:

Returns 204 No Content on success, or 404 if no draft exists.

Automatic Cleanup

Drafts are automatically removed when committed (for ad-hoc queries) or when the draft owner is deleted.


POST /api/queries/{id}/draft/_commit

Commit a draft to update the original query.

Authentication: Required Permission: query:write

Path Parameters:

ParameterTypeDescription
idstringQuery ID (UUID) or natural ID of the original query

Request Body:

{
"clearAllUserSettings": true
}

Validation:

FieldTypeDefaultDescription
clearAllUserSettingsbooleantrueWhether to clear all user settings and cached data when committing

Response:

Returns the updated original query with 200 OK status.

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"naturalId": "team:analytics:sales-query",
"name": "Sales Analysis Query",
"description": "Quarterly sales data with regional breakdowns",
"language": "sql",
"payload": {
"sql": "SELECT * FROM sales WHERE region = :region AND date >= :startDate"
},
"inputs": {
"region": { "type": "string", "label": "Sales Region" },
"startDate": { "type": "date", "label": "Start Date" }
},
"defnUpdatedAt": "2024-02-09T10:15:00Z",
"updatedAt": "2024-02-09T10:15:00Z"
}

Commit Side Effects:

When clearAllUserSettings is true (default):

  1. User Settings Cleared - All users' custom settings for the query are deleted
  2. Dataset Fields Cleared - All embedded dataset fields are reset
  3. Indexed Data Cleared - All cached Elasticsearch data is removed
  4. Dataset Cache Invalidated - dataUpdatedAt is cleared for all embedded datasets
  5. Job Settings Cleared - All job-specific dataset settings are removed

When clearAllUserSettings is false:

  1. Only the query definition is updated
  2. User settings and cached data are preserved
  3. defnUpdatedAt is still updated to track definition changes
Breaking Changes

Committing with clearAllUserSettings: true will force all users to re-run the query and reconfigure their views. Use false for non-breaking changes like description updates.

Embedded Query Drafts

For embedded queries, the draft is NOT deleted after commit - it persists for future edits. For ad-hoc queries, the draft is automatically deleted.


Draft Best Practices

When to Use Drafts

  • Schema Changes - Adding/removing fields or changing data types
  • Performance Tuning - Testing query optimizations
  • Parameter Updates - Adding or modifying input parameters
  • Breaking Changes - Any change that invalidates cached data

When to Skip Drafts

  • Metadata Updates - Name, description, folder changes
  • Non-Breaking Settings - Timeout adjustments, display settings
  • Quick Fixes - Typos or minor corrections

Testing Workflow

# 1. Create a draft
POST /api/queries/my-query/_edit

# 2. Update the draft with changes
PUT /api/queries/my-query/draft
{
"payload": { "sql": "SELECT * FROM new_table" }
}

# 3. Test the draft query
POST /api/queries/{draftId}/_execute
{
"startDate": "2024-01-01"
}

# 4. Commit if tests pass
POST /api/queries/my-query/draft/_commit
{
"clearAllUserSettings": true
}

# Or discard if tests fail
DELETE /api/queries/my-query/draft

Clearing User Settings

ScenarioclearAllUserSettings
Changed field names/typestrue
Added new fieldstrue
Changed datasourcetrue
Performance optimizationtrue (to force re-fetch)
Updated description onlyfalse
Changed timeout settingfalse
Renamed queryfalse