Skip to content

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 Authorization header. 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_id is 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
curl -X DELETE "https://<your-tenant>.qualytics.io/api/containers/34" \
  -H "Authorization: Bearer $QUALYTICS_TOKEN"

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.