# API filters and date periods

> One filter syntax for the dashboard, the API, MCP and exports. Learn the period, comparison and segment inputs and how to combine conditions with AND and OR.

Every stats operation accepts the same inputs:

| Parameter | Description |
|---|---|
| `period` | `today`, `yesterday`, `24h`, `7d`, `14d`, `28d`, `30d` (default), `90d`, `mtd`, `last_month`, `qtd`, `last_quarter`, `ytd`, `12mo`, `last_year`, `all`, `custom` |
| `from`, `to` | Dates (`YYYY-MM-DD`, inclusive) in the site's timezone, with `period=custom` |
| `compare` | `none` (default), `previous_period`, `previous_year`, `custom` |
| `compare_from`, `compare_to` | With `compare=custom` |
| `match_weekday` | `true` to align the comparison by day of the week |
| `filters` | See below |
| `segment_id` | Apply a saved segment (`seg_…`), combined with `filters` |

## Syntax

`filters` is a JSON array. Each item is a condition
`[dimension, operator, value]`. Items are combined with **AND**. Wrap
conditions in `{"any": [...]}` to combine them with **OR**.

```json
[
  ["page", "starts_with", "/blog"],
  ["country", "any_of", ["DE", "FR", "NL"]],
  { "any": [["channel", "is", "email"], ["utm_medium", "is", "newsletter"]] }
]
```

In URLs, send it URL-encoded:

```sh
curl -G "https://privatusanalytics.com/sites/pa_7Q2K9XH3AB/stats/aggregate.json" \
  --data-urlencode 'filters=[["page","starts_with","/blog"],["country","any_of",["DE","FR"]]]' \
  -H "Authorization: Bearer $PRIVATUS_TOKEN"
```

In JSON bodies and MCP tool calls, pass the array itself. Conditions can
also be objects: `{"dimension": "page", "operator": "is", "value": "/"}`.

Limits: 20 conditions in total, regular expressions up to 200 characters.

## Operators

| Operator | Value | Meaning |
|---|---|---|
| `is`, `is_not` | a string | Equals / doesn't equal |
| `any_of`, `none_of` | a list | Equals one of / none of |
| `contains`, `not_contains` | a string | Case-insensitive substring |
| `starts_with` | a string | Prefix |
| `regex`, `not_regex` | a string | Regular expression |
| `gt`, `lt` | a number | Greater / less than (numeric properties) |
| `between` | `[min, max]` | Inclusive range (numeric properties) |

## Dimensions

The same keys are used for filters and for
`/sites/{site_id}/breakdown/{dimension}`.

| Dimension | Label | Scope |
|---|---|---|
| `channel` | Channel | Visit (first touch) |
| `referrer` | Referrer | Visit (first touch) |
| `referrer_url` | Referrer URL | Visit (first touch) |
| `utm_source` | UTM source | Visit (first touch) |
| `utm_medium` | UTM medium | Visit (first touch) |
| `utm_campaign` | UTM campaign | Visit (first touch) |
| `utm_content` | UTM content | Visit (first touch) |
| `utm_term` | UTM term | Visit (first touch) |
| `ref` | Ref | Visit (first touch) |
| `hostname` | Hostname | Visit (first touch) |
| `country` | Country | Visit (first touch) |
| `language` | Language | Visit (first touch) |
| `device` | Device | Visit (first touch) |
| `browser` | Browser | Visit (first touch) |
| `browser_version` | Browser version | Visit (first touch) |
| `os` | Operating system | Visit (first touch) |
| `os_version` | OS version | Visit (first touch) |
| `screen` | Screen size | Visit (first touch) |
| `entry_page` | Entry page | Visit only |
| `exit_page` | Exit page | Visit only |
| `interaction` | Interaction | Visit only |
| `page` | Page | Event / page |
| `event` | Event | Event / page |
| `goal` | Goal | Goal |
| `prop:<key>` | Custom property value, e.g. `prop:plan` | Event |

- **Visit (first touch)** dimensions describe how a visit started. Events
  carry their visit's values, so "country is DE" works for events too.
- **Visit only**: entry and exit pages.
- **Event / page**: `page` filters visits that viewed a page, and `event`
  filters visits in which an event happened.
- **Goal**: `["goal", "is", "<goal id>"]` filters visits that converted.
- **Properties:** `prop:<key>`, e.g. `["prop:plan", "is", "pro"]`, or
  `["prop:seats", "gt", 5]`.

Channel values are the keys listed in [Channels](/docs/metrics/channels)
(`organic_search`, `ai_assistants`…). Countries are ISO 3166-1 alpha-2
codes. There are no region or city dimensions.

## Errors

An unknown dimension or operator, a list operator without a list, or an
invalid regex returns `422 validation_failed` with the reason in
`message`. Filters that aren't valid JSON return `400 bad_request`.
