Computed Attributes API
Computed attributes are reusable computed properties attached to a parent entity model. They let you define aggregations, occurrences, lists, formulas, and custom SQL calculations that enrich your customer profiles and power audience segmentation. The API path remains traits for backwards compatibility.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v1/workspaces/{id}/traits | List all computed attributes |
POST | /api/v1/workspaces/{id}/traits | Create a computed attribute |
GET | /api/v1/workspaces/{id}/traits/{traitId} | Get a computed attribute |
PUT | /api/v1/workspaces/{id}/traits/{traitId} | Update a computed attribute |
DELETE | /api/v1/workspaces/{id}/traits/{traitId} | Delete a computed attribute |
GET | /api/v1/workspaces/{id}/models/{modelId}/traits | List computed attributes by model |
POST | /api/v1/workspaces/{id}/models/{modelId}/trait-evaluation/trigger | Optional manual refresh of all attributes on a model |
POST | /api/v1/workspaces/{id}/models/{modelId}/traits/{traitId}/evaluate | Optional manual refresh of a single computed attribute |
List Computed Attributes
GET /api/v1/workspaces/{id}/traits
Returns all computed attributes in the workspace.
Response
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"workspace_id": "660e8400-e29b-41d4-a716-446655440000",
"parent_model_id": "770e8400-e29b-41d4-a716-446655440000",
"name": "Total Purchases",
"slug": "total_purchases",
"description": "Total number of purchases per customer",
"trait_type": "aggregation",
"config": {
"source_model_id": "880e8400-e29b-41d4-a716-446655440000",
"relationship_id": "990e8400-e29b-41d4-a716-446655440000",
"aggregation": "count",
"column": "order_id"
},
"result_type": "number",
"status": "active",
"status_error": "",
"created_by": "aae8400-e29b-41d4-a716-446655440000",
"created_at": "2024-01-15T09:30:00Z",
"updated_at": "2024-01-15T09:30:00Z",
"last_computed_at": "2024-01-15T15:00:00Z"
}
]Example
curl -X GET https://composable.zeotap.com/api/v1/workspaces/{id}/traits \
-H "Authorization: Bearer <token>" \
-H "X-Workspace-ID: <workspace-id>"Create Computed Attribute
POST /api/v1/workspaces/{id}/traits
Creates a new computed attribute definition.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name |
description | string | No | Description |
parent_model_id | string (UUID) | Yes | Parent entity model this computed attribute attaches to |
trait_type | string | Yes | aggregation, occurrence, list, sql, or formula |
config | object | Yes | Type-specific configuration (varies by type) |
result_type | string | Yes | text, number, boolean, timestamp, or array |
Computed Attribute Types
Aggregation
Computes an aggregate value (count, sum, avg, min, max) across a related model.
{
"name": "Total Revenue",
"parent_model_id": "770e8400-e29b-41d4-a716-446655440000",
"trait_type": "aggregation",
"config": {
"source_model_id": "880e8400-e29b-41d4-a716-446655440000",
"relationship_id": "990e8400-e29b-41d4-a716-446655440000",
"aggregation": "sum",
"column": "order_total"
},
"result_type": "number"
}Occurrence
Detects whether or when an event occurred (first, last, exists).
{
"name": "Last Purchase Date",
"parent_model_id": "770e8400-e29b-41d4-a716-446655440000",
"trait_type": "occurrence",
"config": {
"source_model_id": "880e8400-e29b-41d4-a716-446655440000",
"relationship_id": "990e8400-e29b-41d4-a716-446655440000",
"occurrence": "last",
"column": "order_date"
},
"result_type": "timestamp"
}List
Collects distinct values into an array.
{
"name": "Product Categories",
"parent_model_id": "770e8400-e29b-41d4-a716-446655440000",
"trait_type": "list",
"config": {
"source_model_id": "880e8400-e29b-41d4-a716-446655440000",
"relationship_id": "990e8400-e29b-41d4-a716-446655440000",
"column": "category"
},
"result_type": "array"
}SQL
Custom SQL expression evaluated per entity.
{
"name": "Customer Tier",
"parent_model_id": "770e8400-e29b-41d4-a716-446655440000",
"trait_type": "sql",
"config": {
"sql_expression": "CASE WHEN lifetime_value > 10000 THEN 'platinum' WHEN lifetime_value > 1000 THEN 'gold' ELSE 'standard' END"
},
"result_type": "text"
}Formula
Combines other computed attributes using arithmetic or logic.
{
"name": "Average Order Value",
"parent_model_id": "770e8400-e29b-41d4-a716-446655440000",
"trait_type": "formula",
"config": {
"expression": "{total_revenue} / NULLIF({total_purchases}, 0)"
},
"result_type": "number"
}Example
curl -X POST https://composable.zeotap.com/api/v1/workspaces/{id}/traits \
-H "Authorization: Bearer <token>" \
-H "X-Workspace-ID: <workspace-id>" \
-H "Content-Type: application/json" \
-d '{
"name": "Total Purchases",
"parent_model_id": "770e8400-e29b-41d4-a716-446655440000",
"trait_type": "aggregation",
"config": {
"source_model_id": "880e8400-e29b-41d4-a716-446655440000",
"relationship_id": "990e8400-e29b-41d4-a716-446655440000",
"aggregation": "count",
"column": "order_id"
},
"result_type": "number"
}'Get Computed Attribute
GET /api/v1/workspaces/{id}/traits/{traitId}
Returns a single computed attribute by ID.
Example
curl -X GET https://composable.zeotap.com/api/v1/workspaces/{id}/traits/{traitId} \
-H "Authorization: Bearer <token>" \
-H "X-Workspace-ID: <workspace-id>"Update Computed Attribute
PUT /api/v1/workspaces/{id}/traits/{traitId}
Updates an existing computed attribute definition.
Request Body
Same fields as create. Only include fields you want to change.
Example
curl -X PUT https://composable.zeotap.com/api/v1/workspaces/{id}/traits/{traitId} \
-H "Authorization: Bearer <token>" \
-H "X-Workspace-ID: <workspace-id>" \
-H "Content-Type: application/json" \
-d '{
"name": "Total Purchases (All Time)",
"description": "Count of all orders per customer"
}'Delete Computed Attribute
DELETE /api/v1/workspaces/{id}/traits/{traitId}
Deletes a computed attribute. Cannot be deleted if audiences reference it in their filter trees.
Response
{
"status": "deleted"
}List Computed Attributes by Model
GET /api/v1/workspaces/{id}/models/{modelId}/traits
Returns all computed attributes attached to a specific parent model.
Example
curl -X GET https://composable.zeotap.com/api/v1/workspaces/{id}/models/{modelId}/traits \
-H "Authorization: Bearer <token>" \
-H "X-Workspace-ID: <workspace-id>"Manually Refresh a Single Computed Attribute
POST /api/v1/workspaces/{id}/models/{modelId}/traits/{traitId}/evaluate
Triggers an optional manual refresh of a single computed attribute against the latest source data. This is not required — computed attributes are always computed on read wherever they are referenced (audiences, estimates, syncs, journeys), so a manual refresh is purely a convenience.
Response
Returns the created refresh run object with status 201 Created.
Manually Refresh All Computed Attributes on a Model
POST /api/v1/workspaces/{id}/models/{modelId}/trait-evaluation/trigger
Triggers an optional manual refresh of every computed attribute attached to the given parent model. As with the single-attribute endpoint, this is not required for the attributes to be usable — they are computed on read whenever referenced.
Response
Returns the created refresh run object with status 201 Created.
Computed Attribute Object
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique identifier |
workspace_id | string (UUID) | Owning workspace |
parent_model_id | string (UUID) | Parent entity model |
name | string | Display name |
slug | string | URL-safe identifier |
description | string | Description |
trait_type | string | aggregation, occurrence, list, sql, or formula |
config | object | Type-specific configuration |
result_type | string | text, number, boolean, timestamp, or array |
status | string | draft, active, or error |
status_error | string | Error message when status is error |
created_by | string (UUID) | Account that created the computed attribute |
created_at | string (ISO 8601) | Creation timestamp |
updated_at | string (ISO 8601) | Last update timestamp |
last_computed_at | string (ISO 8601) or null | Time of the last manual refresh, if any (computed attributes are otherwise computed on read) |