# Computed Fields API

Source: https://userguide.qualytics.io/fields/computed-fields/api/

Programmatic access to Computed Fields uses the **Field** endpoints on the Qualytics REST API. The requests below cover creation, update, deletion, and read. 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](https://userguide.qualytics.io/settings/access-tokens/getting-started/) to create one.

> **Tip: 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](https://demo.qualytics.io/api/docs).

> **Note: Permissions**
>
> - **Create, edit, delete**: the **Editor** team permission on the parent datastore, or the **Author** team permission when the caller is (or will be) the owner of the Computed Field (Hybrid Gate).
> - **Reassign ownership** (setting `owner_id` to a different user on Update): always requires the **Editor** team permission.
> - **View, list**: the **Reporter** team permission or above.

## Payload Shape

A Computed Field is a specialization of the generic Field payload. Common fields:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `container_id` | integer | Yes (Create) | - | The container the Computed Field belongs to. Set at creation; cannot be changed on Update. |
| `name` | string | Yes | - | Max 255 characters. Must be unique inside the container. |
| `transformation` | enum | Yes | - | One of `cast`, `cleanedEntityName`, `convertFormattedNumeric`, `customExpression`. |
| `source_fields` | array of strings | Conditional | `null` | The source field names read by the transformation. Required for **Cast**, **Cleaned Entity Name**, and **Convert Formatted Numeric**. **Custom Expression** derives its inputs from the SQL text, so `source_fields` can be omitted. |
| `properties` | object | Conditional | `null` | Type-specific configuration. Shape depends on `transformation`: `target_type` and optional `format` for Cast; `drop_from_prefix`/`drop_from_suffix`/`drop_from_interior` booleans plus `terms_to_drop` and `terms_to_ignore` for Cleaned Entity Name; `column_expression` for Custom Expression; empty for Convert Formatted Numeric. See the interactive reference for the full schema per type. |
| `description` | string | No | `null` | Max 8000 characters. |
| `additional_metadata` | object | No | `null` | Freeform key-value pairs. |
| `owner_id` | integer | No | caller's user id | The Qualytics user who owns the field. Reassignment (on Update) requires the **Editor** team permission. |

## Create

**Endpoint:** `POST /computed-fields`

**Permission:** **Editor** team permission on the parent datastore, or **Author** when `owner_id` is omitted or set to the caller's own user id.

> **Example: Create a Cast field**
>
> ```bash
> curl -X POST "https://<your-tenant>.qualytics.io/api/computed-fields" \
>   -H "Authorization: Bearer $QUALYTICS_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "container_id": 34,
>     "name": "order_total_numeric",
>     "transformation": "cast",
>     "source_fields": ["order_total"],
>     "properties": {
>       "target_type": "decimal(10,2)"
>     },
>     "description": "Numeric version of order_total for aggregation checks."
>   }'
> ```

> **Example: Create a Custom Expression field**
>
> ```bash
> curl -X POST "https://<your-tenant>.qualytics.io/api/computed-fields" \
>   -H "Authorization: Bearer $QUALYTICS_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "container_id": 34,
>     "name": "full_name",
>     "transformation": "customExpression",
>     "properties": {
>       "column_expression": "concat_ws('\'' '\'', first_name, last_name)"
>     },
>     "description": "First and last name concatenated with a space."
>   }'
> ```

Returns the created Field object with its assigned `id`. The request runs a quick profile of the container before it returns, so the Computed Field already has its first values.

## Update

**Endpoint:** `PUT /computed-fields/{id}`

**Permission:** **Editor** team permission on the parent datastore, or **Author** when the caller is the current owner. Reassigning ownership always requires **Editor**.

> **Example: Update a Custom Expression**
>
> ```bash
> curl -X PUT "https://<your-tenant>.qualytics.io/api/computed-fields/128" \
>   -H "Authorization: Bearer $QUALYTICS_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "name": "full_name",
>     "transformation": "customExpression",
>     "properties": {
>       "column_expression": "concat_ws('\'' '\'', first_name, middle_name, last_name)"
>     },
>     "description": "First, middle, and last name concatenated with a space."
>   }'
> ```

The `container_id` cannot be changed. Saving an edit re-registers the transformation on the container and runs a quick profile of the container, which computes values against the new definition.

## Delete

**Endpoint:** `DELETE /computed-fields/{id}`

**Permission:** **Editor** team permission on the parent datastore, or **Author** when the caller is the current owner.

> **Example: Delete a Computed Field**
>
> ```bash
> curl -X DELETE "https://<your-tenant>.qualytics.io/api/computed-fields/128" \
>   -H "Authorization: Bearer $QUALYTICS_TOKEN"
> ```

Returns `204 No Content` on success. The Computed Field definition, the derived output, and any quality checks that target it are removed. Expected Schema checks are kept and drop the field from their list. Source fields are not affected.

## Read

**Endpoint:** `GET /fields/{id}` returns any field on the platform (regular or computed), and the response includes a `computed_field` object when the field is derived. To list every field on a container, use `GET /containers/{id}/fields`, or fetch the container itself with `GET /containers/{id}`, whose response includes a `computed_fields` array of the derived fields.

**Permission:** **Reporter** team permission on the parent datastore or above.

## Error Responses

| Status | Meaning |
| --- | --- |
| `403 Forbidden` | Caller lacks the required team permission for the operation. |
| `404 Not Found` | Container, Computed Field, or one of the `source_fields` does not exist. |
| `406 Not Acceptable` | The name is already used by another field on the container, or `source_fields` is missing for a transformation that requires it. |
| `408 Request Timeout` | The quick profile that validates the definition did not finish in time. Retry the request. |
| `409 Conflict` | A Computed Field with the same name already exists in the container. |
| `422 Unprocessable Entity` | The payload or `properties` are invalid for the selected transformation (wrong types, unknown `transformation`, missing required option, unsupported Cast `target_type`), or the quick profile rejected the definition, for example a Custom Expression that does not compile. |

*Last updated: October 20, 2026.*
