Endpoint how-to
This page takes you from a base URL to a parsed response. Every payload below is synthetic and labelled as sample data — the shared constants they all reuse are documented once in the example gallery.
Base URL
All paths are relative to:
https://engines.api.telmar.com/omg/prd/v1
The following endpoints are available under the Explore API:
| Method | Path | Description |
|---|---|---|
GET | /docs | Returns the OpenAPI specification for this service in JSON format |
POST | /crosstab | Executes a crosstab query against the dataset and returns weighted audience results |
OPTIONS | /crosstab | CORS preflight check for the /crosstab endpoint |
Authenticated requests need a Telmar-Engine-Authorizer API key. See
Authentication if you do not have one yet.
POST /crosstab
Executes a crosstab query against a specified survey dataset. Returns weighted audience counts, unweighted respondent counts, and stability indicators for each requested target code.
| Field | Required | Description |
|---|---|---|
SurveyCode | Yes | Identifies the target survey dataset (e.g. "M20F") |
PopulationBaseCode | Yes | Population base for the query (e.g. "AR18_24") |
TargetCodes | Yes | Target segment codes. Min 1, max 2 |
AuthorizationGroup | No | Authorization group filter. Use "_ALL_" to include all groups |
Understanding target codes
TargetCodes is the single concept worth getting right first:
- 1 target — a single demographic cut against the population base.
- 2 targets — a side-by-side comparison (the shape used in the official sample).
- More than 2 — rejected with
400. Split across multiple calls.
Each entry in TargetCodes produces one object in Results, in the same order.
A first request
Sample data- curl
- Python
- TypeScript
curl -X POST 'https://engines.api.telmar.com/omg/prd/v1/crosstab' \
-H 'Telmar-Engine-Authorizer: SAMPLE.ENGINE.AUTHORIZER' \
-H 'Content-Type: application/json' \
-d '{
"SurveyCode": "M20F",
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": "AR18_24",
"TargetCodes": ["OMEN", "OWOMEN"]
}'
import os
import requests
BASE_URL = "https://engines.api.telmar.com/omg/prd/v1"
def crosstab(survey: str, population_base: str, targets: list[str]) -> dict:
body = {
"SurveyCode": survey,
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": population_base,
"TargetCodes": targets,
}
response = requests.post(
f"{BASE_URL}/crosstab",
json=body,
headers={"Telmar-Engine-Authorizer": os.environ["SAMPLE_ENGINE_AUTHORIZER"]},
timeout=30,
)
if response.status_code != 200:
payload = response.json()
# Prefer the nested error.code when present; otherwise ResultCode.
error = payload.get("error") or {}
code = error.get("code") or payload.get("ResultCode")
message = error.get("message") or payload.get("ResultDescription")
raise RuntimeError(f"{code}: {message}")
return response.json()
result = crosstab("M20F", "AR18_24", ["OMEN", "OWOMEN"])
print(result["Results"])
const BASE_URL = 'https://engines.api.telmar.com/omg/prd/v1';
async function crosstab(
survey: string,
populationBase: string,
targets: string[],
) {
const response = await fetch(`${BASE_URL}/crosstab`, {
method: 'POST',
headers: {
'Telmar-Engine-Authorizer': process.env.SAMPLE_ENGINE_AUTHORIZER!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
SurveyCode: survey,
AuthorizationGroup: '_ALL_',
PopulationBaseCode: populationBase,
TargetCodes: targets,
}),
});
const payload = await response.json();
if (!response.ok) {
const error = payload.error ?? {};
const code = error.code ?? payload.ResultCode;
const message = error.message ?? payload.ResultDescription;
throw new Error(`${code}: ${message}`);
}
return payload;
}
const result = await crosstab('M20F', 'AR18_24', ['OMEN', 'OWOMEN']);
console.log(result.Results);
How to read the response
A successful response is an envelope around a small Results array.
{
"ResultCode": 0,
"ResultDescription": "",
"Results": [
{ "Resps": 1000, "WgtAud": 10000, "Stbl": 0 },
{ "Resps": 123, "WgtAud": 4444, "Stbl": 1 }
],
"AudienceReportUnits": 1000
}
Read it in this order:
ResultCode—0means success. A value greater than0is a partial or conditional result — checkResultDescription.Results— one object perTargetCodesentry, in the same order.Resps— unweighted respondents matching the targetWgtAud— weighted projected audience; multiply byAudienceReportUnitsfor the absolute figureStbl—0stable,1unstable (low respondent counts — use with caution)
AudienceReportUnits— audience unit multiplier (e.g.1000meansWgtAudis in thousands).
Stbl of 1 means the result is unstable. Unstable results indicate low
respondent counts and should be used with caution.
GET /docs
Returns the full OpenAPI specification for this service as a JSON object. Useful for programmatic discovery of the API schema. No authentication is required.
curl 'https://engines.api.telmar.com/omg/prd/v1/docs' \
-H 'Accept: application/json'
The full (abridged) response is in the gallery below.
OPTIONS /crosstab
CORS preflight for the /crosstab path. Browsers issue this automatically before
cross-origin POST requests. Returns 200 — everything useful is in the headers.
curl -X OPTIONS 'https://engines.api.telmar.com/omg/prd/v1/crosstab' \
-H 'Origin: https://app.example.com' \
-H 'Access-Control-Request-Method: POST' -i
Access-Control-Allow-Methods and Access-Control-Allow-Headers tell the
browser what it may send. This call is not billed.
Errors
Failures use ResultCode / ResultDescription, optionally with a nested
error object for machine-readable branching:
{
"ResultCode": 400,
"ResultDescription": "TargetCodes must contain between 1 and 2 items.",
"error": {
"code": "invalid_target_codes",
"message": "TargetCodes must contain between 1 and 2 items.",
"field": "TargetCodes",
"hint": "Split the request into multiple crosstab calls of at most two targets each."
}
}
| HTTP | ResultCode | Meaning | What to do |
|---|---|---|---|
200 | 0 | Success | Use Results as normal |
200 | > 0 | Partial or conditional result | Check ResultDescription |
400 | — | Bad request — malformed JSON or missing required fields | Fix the payload |
401 | — | Unauthorized — verify API key or Cognito credentials | See Authentication |
403 | — | Forbidden — no access to the requested dataset | Confirm permissioning with TelmarHelixa |
500 | — | Internal server error | Contact TelmarHelixa support |
Prefer error.code when present; fall back to ResultCode. Treat
ResultDescription / error.message as human-facing text that may change.
Two rules worth building in from the start:
400,401and403are not retryable. The same request will fail the same way. Fix it or surface it.5xxare retryable with exponential backoff.
Example gallery
Distinct request and response shapes for this endpoint, including the errors you are most likely to hit first. Pick a scenario to see the payloads and when to use it.
Sample data used in these examplesSample data
Every example on this page reuses the same synthetic constants. They are not real credentials or real identifiers, and they will not authenticate against any environment. Substitute your own values from the Developer Portal once you are provisioned.
| Name | Value | What it means |
|---|---|---|
| Base URL | https://engines.api.telmar.com/omg/prd/v1 | The documented base URL for the Sample API. All paths below are relative to it. |
| API key | SAMPLE.ENGINE.AUTHORIZER | A non-functional stand-in for the value you send as the 'Telmar-Engine-Authorizer' header. Retrieve yours from the Developer Portal. |
| Survey code | M20F | Survey dataset identifier used throughout the examples (from the Explore API docs). |
| Authorization group | _ALL_ | Authorization group filter. Use '_ALL_' to include all groups. |
| Population base | AR18_24 | Population base code for the query (from the Explore API docs). |
| Target codes | OMEN, OWOMEN | Target segment codes — OMEN (Men) and OWOMEN (Women). Each request accepts between one and two. |
Successful responses
Client errors
Auth and access errors
Discovery
Basic crosstab for two targets, one population base
POST/crosstab200 OK
When to use this shape
The default call shape from the Explore API docs. Queries M20F with AR18_24 as the population base and returns results for OMEN (Men) and OWOMEN (Women).
Request
{
"SurveyCode": "M20F",
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": "AR18_24",
"TargetCodes": [
"OMEN",
"OWOMEN"
]
}
curl
curl -X POST 'https://engines.api.telmar.com/omg/prd/v1/crosstab' \
-H 'Telmar-Engine-Authorizer: SAMPLE.ENGINE.AUTHORIZER' \
-H 'Content-Type: application/json' \
-d '{
"SurveyCode": "M20F",
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": "AR18_24",
"TargetCodes": [
"OMEN",
"OWOMEN"
]
}'
Response
{
"ResultCode": 0,
"ResultDescription": "",
"Results": [
{
"Resps": 1000,
"WgtAud": 10000,
"Stbl": 0
},
{
"Resps": 123,
"WgtAud": 4444,
"Stbl": 1
}
],
"AudienceReportUnits": 1000
}
Response headers
Content-Type: application/json
Access-Control-Allow-Origin: *
`TargetCodes` accepts 1–2 members. Multiply `WgtAud` by `AudienceReportUnits` for the absolute projected audience. `Stbl` of `0` means stable; `1` means unstable (use with caution).
Crosstab for a single target code
POST/crosstab200 OK
When to use this shape
Use when you only need one target against the population base — for example a single demographic cut on a dashboard tile.
Request
{
"SurveyCode": "M20F",
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": "AR18_24",
"TargetCodes": [
"OMEN"
]
}
curl
curl -X POST 'https://engines.api.telmar.com/omg/prd/v1/crosstab' \
-H 'Telmar-Engine-Authorizer: SAMPLE.ENGINE.AUTHORIZER' \
-H 'Content-Type: application/json' \
-d '{
"SurveyCode": "M20F",
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": "AR18_24",
"TargetCodes": [
"OMEN"
]
}'
Response
{
"ResultCode": 0,
"ResultDescription": "",
"Results": [
{
"Resps": 1000,
"WgtAud": 10000,
"Stbl": 0
}
],
"AudienceReportUnits": 1000
}
Response headers
Content-Type: application/json
Access-Control-Allow-Origin: *
`Results` always has one entry per target. With a single `TargetCodes` member the array length is 1.
More than two TargetCodes in one request
POST/crosstab400 Bad Request
When to use this shape
This is the most common first failure. `TargetCodes` is capped at two members per call. Split larger universes across multiple requests.
Request
{
"SurveyCode": "M20F",
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": "AR18_24",
"TargetCodes": [
"OMEN",
"OWOMEN",
"OTEENS"
]
}
curl
curl -X POST 'https://engines.api.telmar.com/omg/prd/v1/crosstab' \
-H 'Telmar-Engine-Authorizer: SAMPLE.ENGINE.AUTHORIZER' \
-H 'Content-Type: application/json' \
-d '{
"SurveyCode": "M20F",
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": "AR18_24",
"TargetCodes": [
"OMEN",
"OWOMEN",
"OTEENS"
]
}'
Response
{
"ResultCode": 400,
"ResultDescription": "TargetCodes must contain between 1 and 2 items.",
"error": {
"code": "invalid_target_codes",
"message": "TargetCodes must contain between 1 and 2 items.",
"field": "TargetCodes",
"hint": "Split the request into multiple crosstab calls of at most two targets each."
}
}
Response headers
Content-Type: application/json
Rejected requests are not billed. Fix the request and retry — retrying unchanged will fail identically.
Caller is not entitled to the requested survey
POST/crosstab403 Forbidden
When to use this shape
You will hit this when the authorizer is valid but your agreement does not cover the survey or authorization group you requested.
Request
{
"SurveyCode": "RESTRICTED_SURVEY",
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": "AR18_24",
"TargetCodes": [
"OMEN"
]
}
curl
curl -X POST 'https://engines.api.telmar.com/omg/prd/v1/crosstab' \
-H 'Telmar-Engine-Authorizer: SAMPLE.ENGINE.AUTHORIZER' \
-H 'Content-Type: application/json' \
-d '{
"SurveyCode": "RESTRICTED_SURVEY",
"AuthorizationGroup": "_ALL_",
"PopulationBaseCode": "AR18_24",
"TargetCodes": [
"OMEN"
]
}'
Response
{
"ResultCode": 403,
"ResultDescription": "The caller is not entitled to survey RESTRICTED_SURVEY.",
"error": {
"code": "forbidden_survey",
"message": "The caller is not entitled to survey RESTRICTED_SURVEY.",
"field": "SurveyCode",
"hint": "Contact Sales to add this survey to your agreement."
}
}
Response headers
Content-Type: application/json
This is a commercial boundary, not a bug. Confirm the survey code and authorization group with Sales — no code change will resolve a missing entitlement.
CORS pre-flight for crosstab
OPTIONS/crosstab200 OK
When to use this shape
Call this from a browser-based integration to confirm the CORS policy before your first real request, or as a cheap liveness probe. It is not billed.
Request
No request body — this operation is driven entirely by the method, path and headers.
curl
curl -X OPTIONS 'https://engines.api.telmar.com/omg/prd/v1/crosstab' \
-H 'Origin: https://app.example.com' \
-H 'Access-Control-Request-Method: POST'
Response
{}
Response headers
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Telmar-Engine-Authorizer
Everything useful is in the response headers — `Access-Control-Allow-Methods` and `Access-Control-Allow-Headers` tell the browser what it may send.
OpenAPI specification as JSON
GET/docs200 OK
When to use this shape
Call this when you need the machine-readable OpenAPI document for this service — for example to feed a client generator or to confirm the live contract matches what you integrated against.
Request
No request body — this operation is driven entirely by the method, path and headers.
curl
curl -X GET 'https://engines.api.telmar.com/omg/prd/v1/docs' \
-H 'Accept: application/json'
Response
{
"openapi": "3.0.1",
"info": {
"title": "Explore API",
"description": "TelmarHelixa Explore / Crosstab API.",
"version": "1.0.0"
},
"paths": {
"/docs": {
"get": {
"operationId": "docs"
}
},
"/crosstab": {
"post": {
"operationId": "crosstab"
},
"options": {
"operationId": "crosstabOptions"
}
}
}
}
Response headers
Content-Type: application/json
The response body is this service's OpenAPI document in JSON. No authorizer header is required. The payload below is abridged for readability.