> ## Documentation Index
> Fetch the complete documentation index at: https://docs.upstackdata.com/llms.txt
> Use this file to discover all available pages before exploring further.

# upstack query-ads

> List ads with optional daily metrics and a compare period from the command line. Wraps POST /api/query-ads.

List ads as flat rows — one row per ad, with optional daily metrics and an
optional compare period — from the ads-platform integrations connected to
your pixel. Wraps `POST /api/query-ads` — see the
[API reference](/api-reference/introduction).

Unlike [`upstack query`](/cli/query) (nested result blocks) or
[`upstack query-channel-details`](/cli/query-channel-details) (entity
listing with basic details), `query-ads` always returns a flat
`{ rows, pagination }` shape, which makes it the simplest command to script
or consume programmatically.

When `--measures` is omitted, the command is a **listing-only** call: every
ad on the pixel comes back with its metadata and no metric series. Adding
`--measures` with a date range attaches a daily metric series per ad.

## Usage

```bash theme={null}
upstack query-ads
```

## Required flags

None. A bare `upstack query-ads` lists ads with pagination.

## Optional flags

| Flag | Description | Default |
| - | - | - |
| `--measures <m1,m2,...>` | Comma-separated measure ids (e.g. `google.spend`, `meta.spend`). Omit for listing-only. | |
| `--date-start <YYYY-MM-DD>` `--date-end <YYYY-MM-DD>` | Date range. Required together with `--measures`. | |
| `--compare-date-start <YYYY-MM-DD>` `--compare-date-end <YYYY-MM-DD>` | Compare period. Requires `--measures` and a primary range; both bounds required together. | |
| `--timezone <tz>` | IANA timezone used to bucket date-based metrics. | `UTC` |
| `--currency <code>` | ISO currency code to convert amounts to. Omit for the server default. `nativeCurrency` reports the source currency. | `USD` |
| `--filter <json>` | Canonical [Filter](/cli/filters) as JSON. Valid in the `query_ads` context — run `upstack filters --detail` to list fields. `or`/`not` groups must stay within one scope (basic-details vs metric fields). | |
| `--limit <n>` | Max rows (1–500). | `50` |
| `--offset <n>` | Skip the first N rows. | `0` |
| `--sort-by <field>` | `sourceUpdatedAt`, `sourceCreatedAt`, or `resourceName`. | `sourceUpdatedAt` |
| `--sort-direction <dir>` | `asc` or `desc` (case-insensitive). | `desc` |
| `--output <format>` | `json`, `table`, or `csv`. | `json` |
| `--file <path>` | Write output to a file. | (stdout) |
| `--from-file <path>` | Load query parameters from a JSON file. | |

## From-file schema

`--from-file` takes a JSON file of **parameter-style keys** — the same keys as the
flags, not the API request body. CLI flags override file values.

```json theme={null}
{
  "measures": [{ "measure": "google.spend" }],
  "dateStart": "2026-09-14",
  "dateEnd": "2026-09-20",
  "compareDateStart": "2026-09-07",
  "compareDateEnd": "2026-09-13",
  "timezone": "UTC",
  "currency": "USD",
  "filter": { "and": [{ "field": "channel.campaign_id", "op": "equals", "value": "<campaign_id>" }] },
  "limit": 50,
  "offset": 0,
  "sortBy": "sourceUpdatedAt",
  "sortDirection": "desc",
  "output": "json"
}
```

Accepted keys: `measures` (array of `{ "measure": "<id>" }` or a comma-separated
string), `dateStart`, `dateEnd`, `compareDateStart`, `compareDateEnd`, `timezone`,
`currency`, `filter`, `limit`, `offset`, `sortBy`, `sortDirection`, `output`.
Do not use the API body shape (`dateRange`, `compareDateRange`) — those keys are
ignored and the request fails validation with `"dateRange" is required`.

## Response shape

```json theme={null}
{
  "rows": [
    {
      "adId": "555488308710",
      "adName": "Ad name",
      "accountId": "...",
      "accountName": "...",
      "campaignId": "...",
      "campaignName": "...",
      "adsetId": "...",
      "adsetName": "...",
      "resourceSource": "googleAdsIntegration",
      "basicDetails": { "status": "ACTIVE", "currency": "USD" },
      "data": {
        "primary": [{ "dt": "2026-09-14T00:00:00.000", "google.spend": "5.0100" }],
        "compare": []
      }
    }
  ],
  "pagination": { "limit": 50, "offset": 0, "total": 73127, "hasMore": true }
}
```

Listing-only calls return `rows` with `basicDetails` and an empty `data`.
Metric calls fill `data.primary` (one entry per date bucket that has data —
ads with no data in the period return an empty `data.primary` array, not
zero-filled buckets) and, when a compare range is given, `data.compare`.
`pagination.hasMore` tells you whether to page with `--offset`.

## Examples

```bash theme={null}
# List 50 ads (listing-only, no metrics)
upstack query-ads

# Daily google.spend per ad for a week
upstack query-ads \
  --measures google.spend \
  --date-start 2026-09-14 --date-end 2026-09-20

# Scope to one campaign and pull a compare period
upstack query-ads \
  --measures google.spend \
  --date-start 2026-09-14 --date-end 2026-09-20 \
  --compare-date-start 2026-09-07 --compare-date-end 2026-09-13 \
  --filter '{"and":[{"field":"channel.campaign_id","op":"equals","value":"<campaign_id>"}]}'

# Bucket in the ad account's timezone and export JSON to a file
upstack query-ads \
  --measures google.spend \
  --date-start 2026-09-14 --date-end 2026-09-20 \
  --timezone Pacific/Midway \
  --output json --file ads.json
```

## See also

* [`upstack filters`](/cli/filters) — discover valid filter fields, operators,
  and applicable contexts (`query_ads` marks the fields valid here).
* [`upstack measures`](/cli/measures) — list measure ids available across all
  query endpoints.
* [`upstack query-channel-details`](/cli/query-channel-details) — account /
  campaign / adset / ad listing with basic entity details.
* [AI agent workflow](/cli/ai-agent-workflow) — using the CLI from an AI agent.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.