Computed Tables API
Programmatic access to Computed Tables uses the generic Container endpoints on the Qualytics REST API. The requests below cover creation, update, deletion, validation, and history. Requests share the same base URL and Bearer token authentication as the rest of the platform API.
- Base URL. Your deployment's platform host (for example,
https://<your-tenant>.qualytics.io/api). - Auth. Bearer token in the
Authorizationheader. See Access Tokens to create one.
Complete API Reference
The endpoints below are illustrative. For the full request and response schemas, live examples, and every field that each endpoint accepts, see the interactive API reference at demo.qualytics.io/api/docs.
Permissions
- Create, edit, delete: requires the Editor team permission on the parent datastore, or the Author team permission when the user is the current owner (for Edit and Delete) or will be its owner (for Create, when
owner_idis omitted or set to the caller's own user id). - View, list, history: requires the Reporter team permission or above.
- Validate: requires the Editor team permission on the datastore, or Author when the caller will be the owner of the Computed Table.
- Reassign owner: requires the Editor team permission.
Payload Shape
The Computed Table is a specialization of the generic Container payload. Common fields:
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
container_type |
string | Yes | - | Discriminator identifying the container as a Computed Table. Set to the literal "computed_table". |
datastore_id |
integer | Yes (Create) | - | The JDBC source datastore the Computed Table lives in. Set at creation; cannot be changed on Update. |
name |
string | Yes | - | Max 255 characters. Spaces are replaced with underscores. Must be unique inside the datastore. |
query |
string | Yes | - | The SQL body. Must be valid in the parent datastore's dialect and reference only base containers (physical tables and views) inside the same datastore. |
description |
string | No | null |
Max 255 characters. |
owner_id |
integer | No | Caller's user id | Reassignment (on Update) requires the Editor team permission. |
additional_metadata |
object | No | null |
Freeform key-value pairs. |
force_drop_fields |
boolean | No (Update) | false |
Set to true to save an update whose new query drops fields with attached quality checks or anomalies. |
incremental_field_name |
string | No (Update) | null |
Enables incremental profiling on the specified field. |
incremental_identifier_type |
enum | No (Update) | null |
One of "last-modified" or "batch-value". Used with incremental_field_name. |
Create
Endpoint: POST /containers
Permission: Editor team permission on the datastore, or Author creating a Computed Table they will own.
Create with curl
curl -X POST "https://<your-tenant>.qualytics.io/api/containers" \
-H "Authorization: Bearer $QUALYTICS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"container_type": "computed_table",
"datastore_id": 12,
"name": "customer_order_statistics",
"query": "SELECT o.customer_id, COUNT(*) AS order_count, SUM(o.total) AS total_amount FROM public.orders o WHERE o.status = '\''placed'\'' GROUP BY o.customer_id",
"description": "Order counts and totals per customer for placed orders.",
"owner_id": 42
}'
Returns the created Container object with its assigned id. Qualytics runs a basic profile that samples up to 1000 records per partition immediately after save.
Update
Endpoint: PUT /containers/{id}
Permission: Editor team permission on the datastore, or Author owner of the Computed Table.
Update with curl
curl -X PUT "https://<your-tenant>.qualytics.io/api/containers/34" \
-H "Authorization: Bearer $QUALYTICS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"container_type": "computed_table",
"name": "customer_order_statistics",
"query": "SELECT o.customer_id, COUNT(*) AS order_count, SUM(o.total) AS total_amount FROM public.orders o WHERE o.status = '\''placed'\'' AND o.year = 2026 GROUP BY o.customer_id",
"description": "Order counts and totals per customer for placed orders in the current year.",
"owner_id": 42
}'
The datastore_id cannot be changed. Changing owner_id (reassigning ownership) requires the Editor team permission; Authors can edit Computed Tables they own but cannot reassign them.
If the new query drops a field that has attached quality checks or anomalies, the update returns 409 Conflict with a dropped_fields payload. Add force_drop_fields: true to the body to save anyway; the affected fields are marked as missing while their checks and anomalies are preserved.
Editing the query causes Qualytics to re-profile the Computed Table immediately after save: a synchronous slim profile refreshes field statistics right away, and a full asynchronous profile follows.
Delete
Endpoint: DELETE /containers/{id}
Permission: Editor team permission on the datastore, or Author owner of the Computed Table.
Delete with curl
Returns 204 No Content on success. The container, its quality checks, anomalies, profile history, and scan history are removed. The delete is blocked with 409 Conflict when quality checks in other containers reference this Computed Table (for example, an existsIn or dataDiff check pointing at it); delete or repoint those checks first.
Validate a Query Before Save
Endpoint: POST /containers/validate
Permission: Editor team permission on the datastore, or Author when the caller will be the owner of the Computed Table (Hybrid Gate). Validate uses the same permission check as Create in the controlplane.
Validates the SQL without persisting anything. The request body carries the same payload you would send to Create or Update, wrapped in a container object:
Validate with curl
curl -X POST "https://<your-tenant>.qualytics.io/api/containers/validate" \
-H "Authorization: Bearer $QUALYTICS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"container": {
"container_type": "computed_table",
"datastore_id": 12,
"name": "customer_order_statistics",
"query": "SELECT o.customer_id, COUNT(*) AS order_count FROM public.orders o GROUP BY o.customer_id"
}
}'
Returns 204 No Content on success. On failure, the response body carries a detail field with the underlying error message from the warehouse.
History
Endpoint: GET /containers/{id}/history
Permission: Reporter team permission on the datastore or above.
Returns the version history for the container, including the query text and metadata as they were at each revision. Use this to review previous versions of the SQL or attribute changes to specific users.
Read
Endpoint: GET /containers/{id} for a single container, GET /containers?container_type=computed_table&datastore={id} to list Computed Tables inside a datastore.
Permission: Reporter team permission on the datastore or above.
Error Responses
| Status | Meaning |
|---|---|
400 Bad Request |
Payload validation failed: missing required field or query syntactically invalid. |
403 Forbidden |
Caller lacks the required team permission for the operation. |
404 Not Found |
Datastore or container does not exist, or is not visible to the caller. |
409 Conflict |
The requested change is blocked by the current state, most often: a Computed Table with the same name already exists in the datastore, the update would drop fields that have attached quality checks or anomalies (use force_drop_fields: true to confirm), or the delete is blocked by dependents. The response body carries a detail describing the blocker and any dropped_fields or dependent IDs. |
422 Unprocessable Entity |
Payload does not match the schema: unknown container type, wrong field types, or a required top-level field is missing. |
408 Request Timeout |
The warehouse did not respond within the validation window. Retry after simplifying the query or verifying the connection. |