Reten Docs

Audiences

Build user/commerce segments with a query-builder, without writing SQL, and generate, validate and preview the resulting query.

Overview

An Audience Criteria is a segment of users or commerces defined with a query-builder —table → columns → filters → joins → aggregations → combination of blocks and audiences— without writing SQL by hand.

The definition is assembled by composing:

PieceWhat it provides
Query blocksOne or more blocks; each block starts from a catalog table and defines on it columns, filters, time, joins and aggregations.
FiltersPer-column conditions with a comparison operator (EQUALS, IN, BETWEEN, …).
Record filtersConditions over the elements of a RECORD REPEATED column (attributes): at least one element satisfies the sub-filter.
Time windowNarrows the block to a time period (IN_THE_LAST 30 DAYS, SINCE, …).
JoinsJoins the block with other catalog tables (INNER, LEFT, …).
AggregationsSummarizes block columns into a metric (COUNT, SUM, AVG, …).
CompositionsCombines multiple blocks and other audiences with set operators (UNION_DISTINCT, …).

Identity column

Every audience criteria is a segment with its own identity: at least one of its query blocks must project the base table's identity column (for example user_id). That rule is unconditional — a definition that does not expose it is rejected with 400.

Endpoints

Base URL and environments

All routes hang off the global prefix /api under the /audience-criterias resource (for example POST /api/audience-criterias).

Reten Environments

EnvironmentAdmin PanelAPI Base URL
Developmentapp-development.reten.aihttps://api-development.reten.ai
Stagingapp-staging.reten.aihttps://api-staging.reten.ai
Productionapp.reten.aihttps://api.reten.ai

Use the admin panel URL to manage API keys and dispatch configurations. Replace BASE_URL in code examples with the API base URL for your environment.

Authentication

All endpoints require a JWT Bearer token, the x-tenant-id header that identifies the tenant on whose schema the request operates, and the x-project-id header that identifies the project the request works in (see Authentication → Project Context).

HeaderRequiredValue
AuthorizationYesBearer <access_token>
x-tenant-idYesTenant UUID
x-project-idYesProject UUID
-H "Authorization: Bearer <access_token>"
-H "x-tenant-id: <tenant-id>"
-H "x-project-id: <project-id>"

Permissions

Each route requires a specific permission:

PermissionEndpoints
audience-criteria:viewGET /audience-criterias, GET /audience-criterias/:id, GET /tables, GET /tables/:tableName/columns
audience-criteria:createPOST /audience-criterias
audience-criteria:updatePATCH /audience-criterias/:id
audience-criteria:deleteDELETE /audience-criterias/:id
audience-criteria:view-sqlPOST /generate-sql, GET /:id/sql, POST /validate-from-body, POST /:id/validate, POST /preview-from-body, POST /:id/preview

Status codes

The read-only POST endpoints (generate-sql, validate-*, preview-*) respond 201 Created —not 200—, even though they don't create any resource.

Method + routeCodeResponse body
POST /audience-criterias (create)201The created criterion
GET /audience-criterias200Paginated list
GET /audience-criterias/:id200The criterion
GET /tables200Catalog tables
GET /tables/:tableName/columns200Catalog columns
PATCH /audience-criterias/:id200The updated criterion
DELETE /audience-criterias/:id204(no body)
POST /generate-sql201Generated SQL
GET /:id/sql200Generated SQL
POST /validate-from-body201Validation result
POST /:id/validate201Validation result
POST /preview-from-body201Sample result
POST /:id/preview201Sample result

Error format

Errors follow the API's standard format:

{
  "statusCode": 400,
  "message": ["name should not be empty"],
  "error": "Bad Request"
}

On DTO validation errors, message is an array of strings (one entry per broken rule). Validation is strict: undeclared properties are rejected, so sending an unknown field produces a 400.

Common errors in this API:

  • 400 Bad Request — invalid definition or DTO (missing field, wrong type, enum out of range, unknown property).
  • 401 Unauthorized — the Authorization: Bearer is missing or invalid.
  • 403 Forbidden — the user lacks the required permission, or the x-tenant-id is not authorized.
  • 404 Not Found — the requested id does not exist in the active project.

Pagination

The list wraps results in PaginatedResponseDto<T>:

{
  "data": [],
  "pagination": {
    "page": 1,
    "per_page": 25,
    "total": 0,
    "total_pages": 0,
    "has_next": false,
    "has_previous": false
  }
}

The fields inside pagination use snake_case (per_page, total_pages, has_next, has_previous), unlike the rest of the resource which uses camelCase.

The detail of the pagination parameters (page, per_page, filters) is documented in List.

Enum glossary

Quick reference catalog. Each endpoint page re-lists the valid values next to the field where they appear.

SetOperatorEnum

Combination of blocks/audiences in composedWith.

  • UNION_DISTINCT · UNION_ALL · INTERSECT_DISTINCT

LogicalOperatorEnum

Chaining of predicates within a group.

  • AND · OR

ComparisonOperatorEnum

Operator of a predicate over a column.

  • EQUALS · NOT_EQUALS · GREATER_THAN · LESS_THAN · GREATER_THAN_OR_EQUAL · LESS_THAN_OR_EQUAL · CONTAINS · NOT_CONTAINS · STARTS_WITH · ENDS_WITH · IS_NULL · IS_NOT_NULL · IN · NOT_IN · BETWEEN

AggregationOperatorEnum

Aggregation function over an operand (a column, * or an arithmetic expression).

  • COUNT · SUM · AVG · MIN · MAX

ArithmeticOperatorEnum

Operator of an arithmetic expression inside an aggregate's operand. SAFE_DIVIDE yields NULL when the denominator is zero.

  • ADD · SUBTRACT · MULTIPLY · SAFE_DIVIDE

TimeOperatorEnum

Operator of the time window (timeWindow).

  • ALL_TIME · IN_THE_LAST · IN_THE_FIRST · SINCE · BETWEEN

TimeUnitEnum

Unit of the time window.

  • DAYS · WEEKS · MONTHS · YEARS

JoinTypeEnum

Type of join between catalog tables.

  • INNER · LEFT · RIGHT · FULL

CatalogFieldTypeEnum

Data type of an audiences catalog field.

  • STRING · TIMESTAMP · BOOLEAN · FLOAT64 · INT64 · NUMERIC · BIGNUMERIC

Value shape by comparison operator

The shape that value takes depends on the predicate's comparisonOperator:

OperatorsShape of valueExample
IS_NULL, IS_NOT_NULLNo value (NONE)(omitted)
IN, NOT_INNon-empty list (LIST)["a", "b", "c"]
BETWEENOrdered pair (RANGE)[10, 20]
The rest (EQUALS, GREATER_THAN, CONTAINS, …)Single scalar (SINGLE)"active" · 42