Admetrics · API Reference
v3 · stable Knowledge base ↗ OpenAPI ↗
Query API · Developer Reference

Turn data into profit - programmatically.

One HTTP endpoint to query the metrics and dimensions in your Admetrics workspace, with supported attribution settings applied per metric. Pull ROAS, POAS, contribution margin and customer data into any tool, in real time.

300+Metrics
80+Dimensions
2 yrsAPI key validity

Introduction

The Admetrics API is the data engine behind your dashboard. It exposes a single, expressive query interface: you describe the metrics and dimensions you want, the filters and date range to apply, and the shape of the response — Admetrics resolves attribution, blends ad-platform spend with shop revenue, and returns analysis-ready rows.

Composable queries

Mix any metrics and dimensions in one request. Group by date, campaign, product or customer — Admetrics handles the joins.

Attribution built in

Use the attribution settings your stack exposes and apply them per metric in the query payload.

Any output format

JSON records, columnar, CSV or XLSX. Queue a job, poll its status, then fetch the result when it's ready.

Base URLs & environments #

All requests go to the production host. Append the API path (for example /apiv3/queue_query) to the base URL.

Production
https://app.admetrics.io
Live workspace data
The public query API is versioned through the URL path. Use the documented /apiv3 endpoints for all new integrations.

Authentication #

Admetrics authenticates every request with a JWT bearer token, sent in the Authorization header:

Authorization: Bearer <token>

Option A — API key (recommended for integrations)

Contact Admetrics support to be issued a long-lived API token for your workspace. API keys are valid for two years and carry the permissions (allowed clients, metrics) of the account they are minted for. Treat the key as a secret.

Option B — Login & refresh (programmatic)

Exchange dashboard credentials for a short-lived access_token and a longer-lived refresh_token via POST /api/users/login. When the access token expires (≈1 hour), mint a new one with GET /api/users/refresh using the refresh token as the bearer.

login string required
The account email address, e.g. [email protected].
password string required
The account password.
Never embed tokens in client-side code or commit them to source control. Server-side requests only.
Request
curl -X POST 'https://app.admetrics.io/api/users/login' \
  -H 'Content-Type: application/json' \
  -d '{
    "login": "[email protected]",
    "password": "••••••••"
  }'
import requests

r = requests.post(
    "https://app.admetrics.io/api/users/login",
    json={"login": "[email protected]",
          "password": "••••••••"},
)
tokens = r.json()
access_token = tokens["access_token"]
const res = await fetch(
  "https://app.admetrics.io/api/users/login",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      login: "[email protected]",
      password: "••••••••",
    }),
  }
);
const { access_token } = await res.json();
200 OKResponse
{
  "user": "[email protected]",
  "host": "app.admetrics.io",
  "proto": "https",
  "url": "https://app.admetrics.io",
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…"
}
Refresh the access token
curl -X GET 'https://app.admetrics.io/api/users/refresh' \
  -H 'Authorization: Bearer <REFRESH_TOKEN>'

Quickstart #

Pull last month's spend, revenue and ROAS broken down by traffic source. Queries run asynchronously: you POST the job to /apiv3/queue_query, poll its status, then fetch the result.

If you need the final result in one round-trip, send the same payload to POST /apiv3/query. That synchronous endpoint is best for smaller server-side calls that can wait for completion.

  1. Choose your metrics (spend, revenue, roas) and dimensions (traffic_source).
  2. Add a date filter for the period, and set the response shape (here, JSON records).
  3. Submit to queue_query — you get back a status_url and a result_url.
  4. Poll status_url until done_ok, then GET result_url.
Not sure which metric IDs exist? Call GET /apiv3/context to list everything available in your stack, or browse the metrics and dimensions catalogs below.
POST/apiv3/queue_query
# 1 · submit the job
curl -X POST 'https://app.admetrics.io/apiv3/queue_query' \
  -H 'Authorization: Bearer <TOKEN>' \
  -H 'Content-Type: application/json' \
  -H 'Accept-Language: en-US' \
  -d '{
    "query_id": "8e0abc8c-4d0e-152f-901c-e1fed3cb8da5",
    "info": {
      "stack_name": "chprod",
      "request_source": "api|CLIENT_NAME"
    },
    "select": {
      "dimensions": [{ "id": "traffic_source" }],
      "metrics": [{ "id": "spend" }, { "id": "revenue" }, { "id": "roas" }]
    },
    "filters": [
      { "id": "date", "filter": { "$gte": "2026-05-01", "$lte": "2026-05-31" } }
    ],
    "shape": { "format": "records", "limit": 100, "offset": 0 },
    "options": { "aggregates": ["sum"] }
  }'
# ← { "status_url": "…", "result_url": ".../apiv3/query_result/<ID>", … }

# 2 · fetch once status is done_ok
curl -H 'Authorization: Bearer <TOKEN>' \
  'https://app.admetrics.io/apiv3/query_result/<RESULTS_ID>'
import requests, time, uuid

payload = {
    "query_id": str(uuid.uuid4()),
    "info": {
        "stack_name": "chprod",
        "request_source": "api|CLIENT_NAME",
    },
    "select": {
        "dimensions": [{"id": "traffic_source"}],
        "metrics": [{"id": "spend"}, {"id": "revenue"}, {"id": "roas"}],
    },
    "filters": [
        {"id": "date", "filter": {"$gte": "2026-05-01", "$lte": "2026-05-31"}}
    ],
    "shape": {"format": "records", "limit": 100, "offset": 0},
    "options": {"aggregates": ["sum"]},
}
h = {"Authorization": f"Bearer {access_token}", "Accept-Language": "en-US"}

# 1) submit
job = requests.post("https://app.admetrics.io/apiv3/queue_query",
                    headers=h, json=payload).json()

# 2) poll until ready
while True:
    st = requests.get(job["status_url"], headers=h).json()
    if st["task_status"] in ("done_ok", "done_fail"):
        break
    time.sleep(1)

# 3) fetch the rows
rows = requests.get(job["result_url"], headers=h).json()
const payload = {
  query_id: crypto.randomUUID(),
  info: {
    stack_name: "chprod",
    request_source: "api|CLIENT_NAME",
  },
  select: {
    dimensions: [{ id: "traffic_source" }],
    metrics: [{ id: "spend" }, { id: "revenue" }, { id: "roas" }],
  },
  filters: [
    { id: "date", filter: { $gte: "2026-05-01", $lte: "2026-05-31" } },
  ],
  shape: { format: "records", limit: 100, offset: 0 },
  options: { aggregates: ["sum"] },
};
const h = { Authorization: `Bearer ${accessToken}`,
            "Content-Type": "application/json",
            "Accept-Language": "en-US" };

// 1) submit
const job = await (await fetch(
  "https://app.admetrics.io/apiv3/queue_query",
  { method: "POST", headers: h, body: JSON.stringify(payload) }
)).json();

// 2) poll until ready
let st;
do {
  await new Promise((r) => setTimeout(r, 1000));
  st = await (await fetch(job.status_url, { headers: h })).json();
} while (!["done_ok", "done_fail"].includes(st.task_status));

// 3) fetch the rows
const rows = await (await fetch(job.result_url, { headers: h })).json();
200 OKresult_url → records
{
  "status": 200,
  "api_version": "v3",
  "query_id": "8e0abc8c-4d0e-152f-901c-e1fed3cb8da5",
  "query_info": {
    "stack_name": "chprod"
  },
  "shape": {
    "format": "records",
    "results": 3
  },
  "data": [
    { "traffic_source": "facebook", "spend": 48210.55, "revenue": 213880.10, "roas": 4.44, "index": 0 },
    { "traffic_source": "google",   "spend": 31544.00, "revenue": 158992.74, "roas": 5.04, "index": 1 },
    { "traffic_source": "tiktok",   "spend": 12087.21, "revenue": 39114.66,  "roas": 3.24, "index": 2 }
  ]
}

Conventions #

Headers

Authorization string required
Bearer <token> — your API key or access token.
Content-Type string required
application/json for all POST bodies.
Accept-Language string optional
BCP-47 locale (e.g. en-US, de-DE) controlling number, currency and date formatting. Defaults to en-US.

Data conventions

  • Dates are ISO-8601 strings, YYYY-MM-DD. Date ranges are typically half-open or inclusive depending on the operator you choose.
  • Currency & rate metrics are returned as numbers; formatting/precision is governed by Accept-Language and options.precision.
  • IDs for metrics and dimensions are lowercase identifiers. stack_name is the client's Admetrics stack identifier: fetch /api/shopify/activeclients, find your client_id, and copy its stack value.
  • Idempotency: supply a UUID-v4 query_id per request. Identical payloads are cache-keyed, so a repeated query_id+payload may return a cached result.

POST/apiv3/queue_query

Run a query #

Queries run asynchronously. Submit a job to queue_query; the API validates it, returns a set of URLs, and runs the query in the background. Then poll query_status until it's done_ok and fetch the rows from query_result.

The request body is a single JSON object — the query — composed of five blocks: select, filters, shape, options and info. The same payload also works with POST /apiv3/query if you want the result returned synchronously.

Lifecycle

pendingprocessingdone_ok done_fail

Top-level fields

query_id string (uuid) recommended
Client-generated UUID v4 identifying the request. Used for tracing and cache keys.
select object required
The metrics and dimensions to return. See schema.
filters array optional
Row filters, including the all-important date range. See filters & operators.
shape object optional
Output format, pagination and presentation.
options object optional
Execution and rendering options such as totals, timeout, locale, and CSV formatting.
info object optional
Caller metadata such as stack_name and request_source.
POSTrequest body
{
  "query_id": "8e0abc8c-4d0e-152f-901c-e1fed3cb8da5",
  "info": {
    "stack_name": "chprod",
    "request_source": "api|CLIENT_NAME"
  },
  "select": {
    "dimensions": [
      { "id": "month" },
      { "id": "campaign_name" }
    ],
    "metrics": [
      { "id": "impressions" },
      { "id": "spend" },
      { "id": "revenue" },
      {
        "id": "roas",
        "params": {
          "attribution_model": "last_touch_non_direct",
          "attribution_window": "30"
        }
      },
      { "id": "poas" },
      { "id": "cm2" }
    ]
  },
  "filters": [
    { "id": "date", "filter": { "$gte": "2026-01-01", "$lte": "2026-03-31" } },
    { "id": "client_id", "filter": { "$in": ["2133416"] } }
  ],
  "shape": {
    "format": "records",
    "offset": 0,
    "limit": 500
  },
  "options": {
    "aggregates": ["sum"],
    "noise_filter": false,
    "totals": true,
    "timeout": 25,
    "iso8601": true,
    "pretty": true
  }
}
200 OKqueue response
{
  "status": 200,
  "api_version": "v3",
  "status_url": "https://app.admetrics.io/apiv3/query_status/2133416:86bba14a…",
  "result_url": "https://app.admetrics.io/apiv3/query_result/2133416:86bba14a…"
}
400401validation / auth error

Query payload schema #

Reference for every field across the five query blocks.

select — what to return

select.dimensions[] array<object>
Group-by columns. Each item is { "id": "<dimension>" } with an optional params object. Order defines column order. Omit dimensions if you want a single aggregated row.
select.metrics[] array<object>
Measures to compute. Each item is { "id": "<metric>", "params": {…} } where params may carry context-driven values such as attribution_model, attribution_window, and horizon_days.

filters — which rows

An array of filter objects. Use the canonical form { "id": "<field>", "filter": { "<op>": value } }. See operators.

shape — how to render

format enum
records · columnar · rows · csv · xlsx · txt · arrow. Current server default is columnar, but new integrations should set it explicitly. See output formats.
limit integer
Maximum rows to return. Default -1 (server-controlled / no explicit client cap).
offset integer
Row offset for pagination. Default 0.
sort object | array
Optional sort definition such as { "id": "spend", "direction": "desc", "output": "vals" }. Sorting by a dimension requires that dimension to also appear in select.dimensions.
is_relative_date boolean
Set to true to let the API generate the date range from relative_date_type and relative_date_delta instead of relying on explicit date boundaries.
relative_date_type string
Relative window type. Supported examples include year, quarter, month, isoWeek, today, yesterday, last-d-7, and last-m-6.
relative_date_delta object
Offset object { years, quarters, months, weeks, days }. Use the matching key for the selected type, for example months with month, weeks with isoWeek, and days with last-d-7.
When you use relative dates, omit fixed date boundaries from your query and let the API expand the window for you.
{
  "shape": {
    "format": "records",
    "is_relative_date": true,
    "relative_date_type": "month",
    "relative_date_delta": {
      "years": 0,
      "quarters": 0,
      "months": 1,
      "weeks": 0,
      "days": 0
    }
  }
}
Examples: this month = "relative_date_type": "month" with "months": 0; yesterday = "relative_date_type": "yesterday" with all delta values set to 0; last 7 days = "relative_date_type": "last-d-7" with "days": 7.

options — execution

aggregates array<string>
Aggregations to apply across the grouping, e.g. ["sum"]. Default [].
totals boolean
Compute a totals row. Default true.
noise_filter boolean
Suppress statistically insignificant rows. Default false.
timeout integer (s)
Max seconds for synchronous execution. 0 uses the server default.
lang string
Locale override; otherwise taken from Accept-Language.
pretty boolean
Human-formatted values (thousands separators, % signs). Default false.
simple_colnames boolean
Use plain metric/dimension IDs as column names. Default true.
column_desc · column_infos boolean
Include column descriptions and per-column metadata when supported. Defaults false.
precision integer
Decimal precision for columnar/rows/records. -1 = automatic.
iso8601 boolean
Emit dates in ISO-8601. Default true.
csv_sep · csv_header · csv_decimal string · bool · string
CSV rendering controls (separator ,, header row true, decimal mark .).

info — context

stack_name string
Fetch /api/shopify/activeclients, find the object for the client_id you want to query, and copy its stack value here. Example: if that response includes { "client_id": "2133416", "stack": "chprod" }, send "stack_name": "chprod".
request_source string
Caller identifier. Use a stable format such as api|CLIENT_NAME so requests can be attributed consistently.
Example flow: call /api/shopify/activeclients, locate { "client_id": "2133416", "stack": "chprod" }, then use "info": { "stack_name": "chprod" } in query bodies and stack_name=chprod when calling context or index.

GET/apiv3/query_status/{results_id}

Query status #

Non-blocking poll for an enqueued query. Returns the current task_status and an updates array that may be empty. Responds 404 if the results_id is unknown or expired.

results_id string (path) required
The URL-encoded ID returned by queue_query (the tail of status_url).
200 OK
{
  "status": 200,
  "api_version": "v3",
  "query_id": "86bba14a-f8f9-11eb-af0b-98fa9b830118",
  "task_status": "done_ok",
  "updates": []
}
GET/apiv3/query_result/{results_id}

Query result #

Retrieve the finished result of an enqueued query. The body is rendered in the shape.format requested at enqueue time — JSON for records/columnar/rows, or a file download for csv/xlsx. The call blocks briefly if the result is still being finalized; a still-running query returns 504.

results_id string (path) required
The ID from queue_query (the tail of result_url).
200 OKrecords
{
  "status": 200,
  "api_version": "v3",
  "query_id": "8e0abc8c-4d0e-152f-901c-e1fed3cb8da5",
  "query_info": {
    "stack_name": "chprod"
  },
  "shape": {
    "format": "records",
    "results": 2
  },
  "data": [
    { "month": "2026-01", "campaign_name": "Spring – Prospecting", "spend": 84120.0, "roas": 3.91, "poas": 1.42, "index": 0 },
    { "month": "2026-02", "campaign_name": "Spring – Prospecting", "spend": 79330.5, "roas": 4.10, "poas": 1.55, "index": 1 }
  ]
}

Output formats #

Set shape.format to control how results are serialized.

formatContent-TypeShape
recordsapplication/jsonJSON envelope with data as an array of objects — one object per row, keyed by column.
columnarapplication/jsonJSON envelope with data as an object of arrays — one array per column. Current default when shape.format is omitted.
rowsapplication/jsonJSON envelope with data as an array of arrays.
csvtext/csvCSV download. Tune with csv_sep, csv_header, csv_decimal.
xlsxspreadsheetml.sheetExcel workbook download.
txttext/plainFixed-width ASCII table — handy for quick CLI inspection.
arrowvnd.apache.arrow.streamApache Arrow IPC stream for high-throughput pipelines.

GET/apiv3/context

Context #

Discover everything your stack supports: the full list of metrics, dimensions, attribution models, attribution windows, and locale formatting tokens — with display names and types. Use it to build dynamic UIs or validate IDs before querying.

keys string (query) required
Comma-separated sections to return. One or more of:
dimensionsmetricstype_defsattribution_modelsattribution_windowshorizon_daysformats
stack_name string (query) optional
Stack to introspect. Use the same stack value you got for that client from /api/shopify/activeclients and send in info.stack_name. If omitted, Admetrics resolves it from the request context or the token's stack restrictions when possible.
Accept-Language string (header) optional
Controls localized formats and labels in the response. Use this instead of relying on undocumented locale query parameters.
GET/apiv3/context?keys=dimensions,type_defs,metrics,attribution_models,attribution_windows,formats,horizon_days
curl -X GET \
  'https://app.admetrics.io/apiv3/context?keys=dimensions,type_defs,metrics,attribution_models,attribution_windows,formats,horizon_days' \
  -H 'Authorization: Bearer <TOKEN>' \
  -H 'Accept-Language: en-GB'
{
  "status": 200,
  "api_version": "v3",
  "data": {
    "dimensions": {
      "month":          { "id": "month", "name": "Month", "type": "date", "index": true },
      "traffic_source": { "id": "traffic_source", "name": "Traffic source", "type": "string" }
    },
    "type_defs": {
      "currency": { "params": { "attribution_model": {}, "attribution_window": {} } }
    },
    "metrics": {
      "spend": { "id": "spend", "name": "Spend", "type": "currency" },
      "roas":  { "id": "roas",  "name": "ROAS",  "type": "ratio", "display_formula": "{{revenue}}/{{spend}}" }
    },
    "formats": {
      "percent": "#,##0.00%"
    }
  }
}
GETPOST/apiv3/index

Dimension index #

Enumerate the distinct values of a dimension — for example, every campaign name or every client ID — with optional text filtering and row counts. Ideal for powering autocomplete and filter pickers. Use GET with query params for simple lookups, or POST a JSON body when you need to scope by other filters.

dimension string required
The dimension to enumerate, e.g. campaign_name, client_id, dow.
like / filter string optional
Case-insensitive substring filter on the value.
filters array optional (POST)
Scope to other dimensions, e.g. only values seen for a given client_id.
tables / views string optional
Restrict the search to specific views.
offset · limit integer optional
Pagination. Defaults 0 / 100.
POST/apiv3/index
{
  "dimension": "dow",
  "stack_name": "chprod",
  "offset": 0,
  "limit": 200,
  "filters": [
    { "id": "client_id", "filter": { "$in": ["2133416"] } }
  ]
}
{
  "status": 200,
  "data": [
    { "id": "Monday",  "count": 12345 },
    { "id": "Tuesday", "count": 11234 }
  ]
}

Metrics catalog #

A representative catalog of metric IDs you can request in select.metrics. Your stack may expose more or fewer — call GET /apiv3/context?keys=metrics for the authoritative list. Many metrics accept attribution parameters.

Metric IDDescription
Spend & delivery
spendAdvertising spend (currency)
base_spendSpend excluding commission
spend_shareSpend as a share of total
impressionsAd impressions
clicksAd clicks
cpm · cpcCost per mille / per click
ctr · ctvClick-through rate / click-to-visit rate
video_viewsVideo views (with p25p100 completion variants)
reactions · engrReactions / engagement rate
Conversions & cost
conversionsTotal conversions
purchasesPlatform-reported purchases (purchases_v1d, purchases_v7d)
cvr · cvr_ncConversion rate / new-customer conversion rate
cpo · cpl · cpatcCost per order / lead / add-to-cart
cac · ncac · rcacCustomer / new-customer / reactivated acquisition cost
add_to_cart_rate · cart_cvrAdd-to-cart and cart conversion rates
ROAS, MER & profitability
roasReturn on ad spend (with confidence intervals)
roas_gross · roas_netGross / net ROAS (roas_nc, roas_net_nc for new customers)
poasProfit on ad spend (poas_nc, poas_ac)
mer · amerMarketing efficiency ratio / acquired MER
mpr · amprMarketing profit ratio / acquired MPR
acos · crrAd cost of sales / cost-revenue ratio
Revenue & orders
revenue · revenue_netGross / net revenue (revenue_nc, revenue_rc by cohort)
orders · orders_netOrders, net of cancellations/returns
gross_sales · net_salesGross / net sales
aov · aov_netAverage order value (aov_nc, aov_rc by cohort)
aopAverage order profit
quantity · subscriptionsItems sold / new subscriptions
Customers & retention
customers · new_customersTotal / new customers (repeat_customers, reactivated_customers)
retention · repurchaseRetention and repurchase rates
ncr · racrNew-customer rate / reactivation rate
rpc · rpvRevenue per customer / per visit
Contribution margin & costs
cm1 · cm2 · cm3Contribution margin 1–3 (cm2_nc, cm2pi variants)
gross_profit · gross_marginGross profit / margin %
cogsCost of goods sold (cogs_rate, returned_cogs)
shipping · shipping_costShipping revenue / cost
tax · discountsTax collected / total discounts
transaction_costPayment & transaction fees (base_fee, variable_fee)
This is a curated subset of 300+ metrics. Product-level (product_roas, product_cac), attribution-window (roas_click_v7d) and lifetime (ttc, tbo, opc) families are all available — discover them via context.

Dimensions catalog #

Dimensions are the columns you group by in select.dimensions. A representative set is below; call context for your stack's full list.

Dimension IDDescription
Time
dateCalendar date (YYYY-MM-DD)
week · isoweekWeek / ISO week
month · quarter · yearMonth, quarter, year buckets
dowDay of week
Campaign & creative
campaign_id · campaign_nameCampaign (campaign_status, campaign_type)
adset_name · ad_nameAd set / ad (with _id and _status)
account_nameAd account
traffic_sourceChannel/source (channel_group, media_source)
utm_source · utm_campaignUTM parameters (utm_term, utm_content)
ad_text · headline1Creative copy (ad_preview, description1)
Product & order
product · product_idProduct (product_vendor, product_type, sku)
product_variantVariant (product_variant_id)
order_id · order_numberOrder identifiers (lineitem_id)
discount_code · discount_typeDiscounts applied
sales_channel · shopSales channel / shop (marketplace_platform)
payment_gatewayPayment method
Customer & geography
customer_id · customer_typeCustomer + New/Returning/Reactivated
customer_order_indexOrder sequence number
billing_countryBilling country (shipping_country, shipping_city)
device_categoryDesktop / Mobile / Tablet (browser_name, os)
Account
client_id · client_nameWorkspace / client
market · exchange_nameMarket region / ad exchange

Attribution & metric parameters #

Many metrics accept a params object that tunes how conversions are attributed. Set them per metric inside select.metrics. Discover the allowed attribution values for your stack via context; the examples below are illustrative only.

attribution_model string
How credit is assigned across touchpoints. Use one of the model IDs returned by GET /apiv3/context?keys=attribution_models.
first_touchlast_touch_non_directlast_platformlinearu_shapedinflatedcustom
attribution_window string
Look-back window in days for crediting a conversion. Use one of the window IDs returned by GET /apiv3/context?keys=attribution_windows.
1273060max
horizon_days string
Revenue horizon for LTV-style metrics. Use one of the horizon IDs returned by GET /apiv3/context?keys=horizon_days.
0306090120180365-1 (max)
lift boolean
Compute incremental (lift) values where supported.
baseline enum
debiased baseline for lift analysis.
Per-metric attribution
"metrics": [
  {
    "id": "roas",
    "params": {
      "attribution_model": "last_touch_non_direct",
      "attribution_window": "30",
      "horizon_days": "90"
    }
  },
  {
    "id": "aov",
    "params": { "attribution_model": "first_touch", "attribution_window": "7" }
  }
]
Available models, windows, and horizons vary by stack and metric. Use context to discover the values your account exposes (keys=attribution_models,attribution_windows,horizon_days).

Filters & operators #

Filters narrow the rows a query scans. The canonical form pairs a field id with an operator map, and may include a params object when a filter needs attribution-aware settings:

"filters": [
  { "id": "date",           "filter": { "$gte": "2026-01-01", "$lte": "2026-03-31" } },
  { "id": "client_id",      "filter": { "$in": ["2133416", "2119108"] } },
  { "id": "spend",          "filter": { "$gt": 100000 } },
  { "id": "campaign_name",  "filter": { "$regex": "Prospecting|Retargeting" } },
  { "id": "traffic_source", "filter": { "$eq": "facebook||google||tiktok" } }
]
OperatorMeaningAlias
$eq · $neEqual / not equal — accepts || as OR (see below)= · !=
$gt · $gteGreater than / or equal> · >=
$lt · $lteLess than / or equal< · <=
$in · $ninIn / not in a list
$regex · $matchRegular-expression match (RE2, contains)
$notregex · $notmatchNegated regular-expression match
$exists · $notexistsField is / isn't null

Regular expressions #

String dimensions can be matched with full RE2 regular expressions via $regex (alias $match) and its negation $notregex (alias $notmatch). Matching is partial — the pattern matches anywhere in the value (like REGEXP_CONTAINS), so anchor with ^…$ for an exact match and use the (?i) flag for case-insensitivity. Inside a pattern, | is the standard regex alternation (OR).

"filters": [
  // contains "Prospecting" OR "Retargeting"
  { "id": "campaign_name", "filter": { "$regex": "Prospecting|Retargeting" } },

  // exact, case-insensitive match of either seasonal sale
  { "id": "ad_name", "filter": { "$match": "(?i)^(spring|summer) sale$" } },

  // exclude anything that looks like a test/draft campaign
  { "id": "campaign_name", "filter": { "$notregex": "(?i)test|draft|wip" } }
]
|| as OR in $eq / $ne. For quick multi-value matching you don't need a full regex — join values with || and $eq matches any of them, while $ne excludes all of them:
{ "$eq": "facebook||google||tiktok" } { "$ne": "test||draft" }

Errors & status codes #

Errors return a JSON envelope with a numeric status, a human-readable msg, and the api_version. The HTTP status mirrors status.

CodeMeaning
200Success.
400Validation error — unknown metric/dimension, malformed filter, bad date.
401Missing or invalid bearer token.
404Unknown results_id or resource.
500Internal error.
504Result not ready yet — the job is still running. Keep polling query_status.
400 Bad Request
{
  "status": 400,
  "msg": "Unknown metric id: 'roass'. Did you mean 'roas'?",
  "api_version": "v3"
}

Limits & timeouts #

Execution timeout

Set options.timeout (seconds) to bound query execution. While a job is still running, query_result returns 504 — keep polling query_status until done_ok.

Pagination

Page with shape.limit and shape.offset. For very large exports prefer csv/xlsx/arrow over deep offset paging.

No fixed request-rate limit is currently published. Be a good citizen — batch metrics into single queries rather than fanning out many small requests, and use async for heavy pulls.
GET/apiv3/health/api

Health #

Lightweight liveness checks for monitoring.

GET /apiv3/health/api
Unauthenticated liveness probe. Returns 200 ok.
GET /apiv3/health/jwt
Authenticated probe — verifies your bearer token is accepted. Returns 200 ok.
200 OK
curl 'https://app.admetrics.io/apiv3/health/api'
# → ok