Skip to main content

Audience Query Payload & API Specification

This document defines the formal JSON specification for executable audience definitions evaluated by analytics-query-engine, alongside the complete REST API contract.


1. Executable Audience Query Schema​

All audience evaluation, validation, and preview endpoints accept a root query object with the following structure:

{
"query": {
"entity": "Customer",
"dimensions": ["Customer.country", "Orders.purchaseCount"],
"metrics": ["Customer.count"],
"time": [
{
"member": "metrics.timestamp",
"range": ["2026-07-01", "2026-07-15"]
}
],
"filters": {
"match": "ALL",
"conditions": [
{
"member": "Customer.country",
"operator": "equals",
"values": ["India"]
},
{
"member": "commerceDetails.count",
"operator": "greaterThanOrEqual",
"values": ["1"],
"window": "31d"
},
{
"not": {
"member": "Orders.refundAmount",
"operator": "greaterThan",
"values": ["100"]
}
}
]
}
}
}

Top-Level Query Attributes​

FieldTypeRequiredDescription
entitystringYesPrimary entity evaluated. Must be set to "Customer".
dimensionsstring[]NoSelected returnable attributes for preview rows (e.g., ["Customer.email", "Orders.purchaseCount"]).
metricsstring[]YesAggregation metric evaluated. Must include ["Customer.count"].
timeobject[]YesGlobal evaluation lookback window. Must target "metrics.timestamp". Range can be ISO dates (["2026-01-01", "2026-03-31"]) or relative presets (["last 30 days"]). Maximum span is 365 days.
filtersobjectYesThe root rule group. Note: Must use filters, not where.

2. Filter Group & Condition Syntax​

Root & Nested Groups (match: "ALL" / "ANY")​

Groups contain a match property and a conditions array:

  • AND Logic: Set "match": "ALL" — all enclosed conditions or subgroups must be satisfied.
  • OR Logic: Set "match": "ANY" — at least one condition or subgroup must be satisfied.
{
"match": "ALL",
"conditions": [
{
"member": "Customer.lifecycleStage",
"operator": "equals",
"values": ["lead"]
},
{
"match": "ANY",
"conditions": [
{
"member": "touchpoint.source",
"operator": "equals",
"values": ["Google"],
"window": "30d"
},
{
"member": "touchpoint.source",
"operator": "equals",
"values": ["LinkedIn"],
"window": "30d"
}
]
}
]
}

Exclusion Logic (not)​

To exclude users matching a specific condition or group, wrap the definition in a "not" object:

{
"not": {
"member": "events.eventType",
"operator": "equals",
"values": ["purchase"],
"window": "30d"
}
}

3. Operator Reference Matrix​

The supported operators depend on the catalog field type:

OperatorField TypesValues RequiredDescriptionExample Payload Snippet
equalsstring, number, booleanExactly 1Exact match equality.{"operator": "equals", "values": ["active"]}
notEqualsstring, number, booleanExactly 1Inequality comparison.{"operator": "notEquals", "values": ["churned"]}
instring, number1 or moreValue matches any in the list.{"operator": "in", "values": ["India", "UAE", "UK"]}
notInstring, number1 or moreValue does not match any in list.{"operator": "notIn", "values": ["internal", "test"]}
greaterThannumber, money, timeExactly 1Numeric/time greater than.{"operator": "greaterThan", "values": ["100"]}
greaterThanOrEqualnumber, money, timeExactly 1Numeric/time greater than or equal.{"operator": "greaterThanOrEqual", "values": ["1"]}
lessThannumber, money, timeExactly 1Numeric/time less than.{"operator": "lessThan", "values": ["50"]}
lessThanOrEqualnumber, money, timeExactly 1Numeric/time less than or equal.{"operator": "lessThanOrEqual", "values": ["5"]}
betweennumber, money, timeExactly 2Value lies inclusively within range.{"operator": "between", "values": ["10", "50"]}
isSetAll types0 (empty [])Attribute is not null/empty.{"operator": "isSet", "values": []}
isNotSetAll types0 (empty [])Attribute is null or missing.{"operator": "isNotSet", "values": []}

4. Time Windows & Lookback Intervals​

Any field marked requiresTimeWindow: true in the catalog must specify a window property.

Supported window formats:

  1. Interval Notation: "7d", "14d", "30d", "90d", "180d", "365d".
  2. Relative Semantic Presets:
    • "last 7 days"
    • "last 30 days"
    • "from 7 days ago to now"
    • "from now to 2 weeks from now"

5. Analytics Query Engine REST Endpoints​

All endpoints use base URL http://<analytics-query-engine-host> and share the same response envelope:

{
"code": 200,
"success": true,
"message": "",
"data": [
{
"...": "typed response object"
}
]
}

Endpoints Matrix​

RouteMethodPurposeKey Headers
/api/v2/analytics/audiences/audience-fieldsGETFetch field catalog & operators.Client-ID, Workspace-ID
/api/v2/analytics/audiences/field-valuesPOSTAutocomplete dropdown values for a field.Client-ID, Workspace-ID
/api/v2/analytics/audiences/validatePOSTCheck query syntax and rule validity.Client-ID, Workspace-ID
/api/v2/analytics/audiences/previewPOSTCalculate reach and return sample rows.Client-ID, Workspace-ID, X-Audience-PII-Access (optional)
/api/v2/analytics/audiences/{audienceId}/evaluatePOSTRun live evaluation for a saved audience.Client-ID, Workspace-ID, X-Audience-PII-Access (optional)
/api/v2/analytics/audiences/{audienceId}/insightPOSTCompute statistical overlap & drivers.Client-ID, Workspace-ID

6. Sample Request & Response Payloads​

Validate Audience Query (POST /api/v2/analytics/audiences/validate)​

Request​

curl --location 'http://localhost:8080/api/v2/analytics/audiences/validate' \
--header 'Authorization: Bearer <JWT_TOKEN>' \
--header 'Content-Type: application/json' \
--header 'Client-ID: 34507' \
--header 'Workspace-ID: 34509' \
--data '{
"query": {
"entity": "Customer",
"metrics": ["Customer.count"],
"time": [{"member": "metrics.timestamp", "range": ["last 30 days"]}],
"filters": {
"match": "ALL",
"conditions": [
{
"member": "Customer.country",
"operator": "equals",
"values": ["India"]
}
]
}
}
}'

Valid Response (data[0])​

{
"valid": true,
"warnings": [],
"errors": []
}

Invalid Response (data[0])​

{
"valid": false,
"warnings": [],
"errors": [
{
"code": "missing_filters",
"field": "query.filters",
"message": "Audience requests must include query.filters."
}
]
}

Preview Audience (POST /api/v2/analytics/audiences/preview)​

Request (Include Rows & PII Clearance)​

curl --location 'http://localhost:8080/api/v2/analytics/audiences/preview?limit=10&offset=0&includeRows=true' \
--header 'Authorization: Bearer <JWT_TOKEN>' \
--header 'Content-Type: application/json' \
--header 'Client-ID: 34507' \
--header 'Workspace-ID: 34509' \
--header 'X-Audience-PII-Access: true' \
--data '{
"query": {
"entity": "Customer",
"dimensions": ["Customer.email", "Customer.country", "Orders.purchaseCount"],
"metrics": ["Customer.count"],
"time": [{"member": "metrics.timestamp", "range": ["last 30 days"]}],
"filters": {
"match": "ALL",
"conditions": [
{
"member": "Customer.country",
"operator": "equals",
"values": ["India"]
}
]
}
}
}'

Response (data[0])​

{
"summary": {
"estimatedCount": 1420,
"totalCount": 10500,
"impactSteps": [
{
"step": 1,
"name": "Country equals India",
"count": 1420
}
]
},
"rows": [
{
"Customer.email": "[email protected]",
"Customer.country": "India",
"Orders.purchaseCount": 3
}
],
"pagination": {
"totalRows": 1420,
"limit": 10,
"offset": 0
}
}