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

# Tool API reference

> Developer reference for `/v1/tools/*` endpoints.

If you use OpenRush through an AI agent, you do not need to memorize these tool names. Ask normal marketing questions and let your agent choose the right tool.

This page is for developers who call the REST API directly.

Tool endpoints require authentication. Send `Authorization: Bearer <key>` or `X-API-Key: <key>`.

Every successful tool response is an Open Fact Envelope. The `data` shape changes per tool, but the top-level envelope stays the same.

## Plain-language map

| If you want to... | Use this tool |
| - | - |
| Understand one domain | `inspect_domain` |
| Find search competitors | `discover_competitors` |
| Find keyword ideas | `research_keywords` |
| Find competitor keyword gaps | `compare_keyword_coverage` |
| Inspect a domain's backlink profile | `inspect_backlinks` |
| Run a backlink gap (who links to rivals but not you) | `compare_backlink_gap` |
| See today's Google results for a query | `inspect_serp` |
| Check where a site ranks for specific keywords | `inspect_search_visibility` |
| See where a domain stands in AI answers | `inspect_ai_visibility` |
| See which domains AI cites on a topic | `discover_ai_citations` |
| Audit a website for issues | `audit_site` |
| Drill into one keyword | `inspect_keyword` |
| Drill into one page | `inspect_page` |
| See my own measured search traffic | `get_search_performance` |
| See my own measured website traffic | `get_website_analytics` |
| See my own measured ad performance | `get_ad_performance` |
| List my connected websites and ad accounts | `list_connections` |
| Download full rows from a previous response | `export_dataset` |

## Inspect domain

`POST /v1/tools/inspect_domain`

Compact factual snapshot for one domain. Use this as the starting map for top keywords, top pages, estimated traffic, dominant intents, and likely competitors.

Credit cost: `9`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `domain` | string | Yes | | 2-253 characters |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |

Example:

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/inspect_domain" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"stripe.com"}'
```

`data` includes `domain`, `location`, `summary`, `top_keywords`, `top_pages`, `likely_competitors`, and `intent_mix`.

`inspect_domain` uses the organic search index only. It does not call the backlink index or include link-authority metrics. When backlink tools are enabled, `next_actions` can suggest `inspect_backlinks` and an executable `compare_backlink_gap` call seeded with the likely competitors returned here.

## Discover competitors

`POST /v1/tools/discover_competitors`

Find organic competitors by domain overlap or by seed keywords.

Credit cost: `7`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `domain` | string | No | | Use for keyword-overlap mode |
| `seed_keywords` | string\[] | No | | 1-20 seed queries |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |
| `limit` | integer | No | `10` | 1-100 |

Provide `domain` or `seed_keywords`. Domain mode is cheap and broad. Seed keyword mode needs the seeds indexed, not the target.

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/discover_competitors" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"seed_keywords":["seo for ai agents","keyword gap api"],"limit":10}'
```

`data` includes `domain`, `location`, and `competitors`.

In domain mode, a successful result can suggest `compare_backlink_gap` with the discovered competitors already filled in, to find referring domains that link to rivals but not you.

## Research keywords

`POST /v1/tools/research_keywords`

Expand a seed term into a ranked demand list.

Credit cost: `3`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `seed` | string | Yes | | 1-200 characters |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |
| `mode` | string | No | `ideas` | `ideas`, `suggestions`, or `related` |
| `limit` | integer | No | `25` | 1-200 |
| `min_volume` | integer | No | | Minimum monthly volume |
| `intent` | string | No | | `informational`, `navigational`, `commercial`, or `transactional` |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/research_keywords" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"seed":"crm software","mode":"ideas","limit":25}'
```

`data` includes `seed`, `location`, `mode`, and `keywords`.

## Compare keyword coverage

`POST /v1/tools/compare_keyword_coverage`

Find keyword gaps where competitors rank and the target does not, plus keywords where the target is losing.

Credit cost: `12`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `domain` | string | Yes | | Target domain |
| `competitors` | string\[] | Yes | | 1-5 competitor domains |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |
| `limit` | integer | No | `50` | 1-100. Max gap keywords and max losing keywords returned (each) |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/compare_keyword_coverage" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"pipedrive.com","competitors":["hubspot.com"],"limit":20}'
```

`data` includes `domain`, `location`, `competitors`, `gaps`, `losing`, and `intent_clusters`.

## Inspect backlinks

`POST /v1/tools/inspect_backlinks`

Inspect a domain's link profile from the backlink index, **sliced by `view`** so you pay only for the slices you ask for (each view is one vendor call). This is a lean primitive, not a bundle.

Credit cost: `9` (one flat price whatever views you request)

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `domain` | string | Yes | | Target domain. URLs are normalized to their domain |
| `view` | string\[] | No | `["authority"]` | Any subset of `authority`, `referring_domains`, `anchors`, `backlinks` |
| `limit` | integer | No | `100` | Rows per list view, 1-1000 (priced per call, so pull deep) |
| `offset` | integer | No | `0` | Row offset for paging a deep list view |
| `since` | string (ISO date) | No | | Limit `referring_domains`/`backlinks` to links new or lost on/after this date |
| `status` | string | No | `live` | `live`, `lost` (for reclaim), or `new` |
| `domain_from` | string | No | | `backlinks` view only: return just the links from this source domain (the drill-down after a `compare_backlink_gap` row). Ignored by other views |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/inspect_backlinks" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"stripe.com","view":["authority","referring_domains"],"limit":1000}'
```

The views:

* `authority`: `domain_rank` (0-1000), referring-domain and backlink totals, `dofollow_ratio`, spam score. The cheap "how established is this site" call.
* `referring_domains`: a deep, paginated list of domains that link to the target. Its row-level rank is **page-level, not true domain authority**. For a ranked, authority-filtered competitor gap, use `compare_backlink_gap`.
* `anchors`: anchor-text distribution.
* `backlinks`: individual links (from-url, anchor, dofollow, first\_seen, lost\_date). Use `status=lost` for reclaim, the full list for disavow. Set `domain_from` to one source domain to see exactly where and how it links to the target in a single call — the drill-down after a `compare_backlink_gap` row.

Facts use `backlinks.domain_authority`, `backlinks.referring_domain`, `backlinks.anchor`, and `backlinks.backlink` types with `backlink_index` provenance.

For a competitor link gap, do **not** page these lists and union them yourself — call `compare_backlink_gap`, which runs that whole join server-side.

## Backlink gap

`POST /v1/tools/compare_backlink_gap`

The backlink **gap** (a.k.a. link intersect), computed server-side in one call: the referring domains that link to several of a client's competitors, ranked by how many competitors link them then by true authority, spam- and authority-filtered, with the ones the client already earned flagged. This replaces the old hand-run recipe — pull each competitor's referring domains, union thousands of rows, dedupe against the client, re-enrich for true authority, filter, sort — all of which used to run in the calling agent's context. Here it is one call and a compact, report-ready result.

Credit cost: `40`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `domain` | string | Yes | | The client the gap is measured against |
| `competitors` | string\[] | Yes | | 1-20 rival domains (get a real, in-vertical set from `discover_competitors`) |
| `min_competitors` | integer | No | `2` | A referring domain must link to at least this many competitors to count |
| `min_authority` | integer | No | `100` | Drop referring domains below this true `domain_rank` (0-1000). Set `0` to keep all |
| `max_spam` | integer | No | `30` | Drop referring domains at/above this spam score (0-100) |
| `include_earned` | boolean | No | `true` | Keep domains the client already links from, flagged `earned=true`. Set `false` for the pure "what's left" list |
| `limit` | integer | No | `50` | Top rows returned inline. The full ranked set is always in `resources` |
| `exclude_domains` | string\[] | No | `[]` | Up to 500 referring domains to drop, including all their subdomains (e.g. your own "never pitch" list) |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/compare_backlink_gap" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"michiganautolaw.com","competitors":["buckfirelaw.com","sinasdramis.com","theclarklawoffice.com"]}'
```

How it works: ranks the competitors by true authority, fans out referring-domain pulls to the strongest of them (fan-out and per-competitor depth are chosen internally; the top ones recover essentially the full intersect), unions and counts the overlap, drops shared hosting, site-builder, shortener, and CDN domains (such as `wixsite.com`, `netlify.app`, `bit.ly`, with all subdomains, since one row there is many unrelated sites) and any `exclude_domains`, attaches true authority and spam through an internal bulk engine, drops spam and low-authority rows, flags each row `earned` or gap, and sorts by (competitor count desc, authority desc).

`data` includes `domain`, `competitors` (the set the pulls fanned out to), `filters`, `gap` (the top `limit` rows), and `summary` — the funnel counts (`union_referring_domains`, `candidates`, `after_filter`, `gap_count`, `earned_count`, `dropped_platform`, `dropped_excluded`, `dropped_spam`, `dropped_low_authority`) plus per-competitor coverage. Facts use the `backlinks.link_gap` type (domain, `links_to`, `competitor_count`, `earned`, `domain_rank`, `spam_score`) with `backlink_index` provenance.

Read `coverage.scope_note` for what was and wasn't covered, and fetch the **full ranked candidate set** from `resources` with `export_dataset` — don't re-run per-competitor pulls to get the long tail. A short gap list is a good result: if the client already owns the strong domains, that shows up as `earned=true`, not as padding.

> [!NOTE]
>
> These endpoints are independent. `inspect_backlinks` makes only profile calls. `compare_backlink_gap` computes the whole intersect server-side, but no search, audit, or owned-data endpoint invokes either one automatically.

## Inspect SERP

`POST /v1/tools/inspect_serp`

Fetch a live SERP snapshot for one query.

Credit cost: `2`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `query` | string | Yes | | 1-200 characters |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |
| `depth` | integer | No | `10` | 10-100 |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/inspect_serp" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"best crm for startups","depth":10}'
```

`data` includes `query`, `location`, `fetched_at`, `item_types_present`, `organic`, optional `ai_overview`, `paid`, `local_pack`, optional `featured_snippet`, `people_also_ask`, and `related_searches`.

## Inspect search visibility

`POST /v1/tools/inspect_search_visibility`

Check where a domain ranks across a keyword set.

Credit cost: `10`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `domain` | string | Yes | | Target domain |
| `keywords` | string\[] | Yes | | 1-100 keywords |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |
| `mode` | string | No | `auto` | `auto`, `index`, or `live` |

`auto` tries the index first and falls back to live SERPs when the target is underindexed. `index` is fast and cheap. `live` reflects today's Google.

Live SERP lookups are capped at 10 keywords per call. `index` mode checks all keywords in one call, and so does `auto` when the index has the answers. When live lookups run (`live` mode, or `auto` falling back to live), only the first 10 keywords are checked. `coverage` then reports how many keywords were resolved out of how many were requested, and `next_actions` includes a follow-up call for the rest.

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/inspect_search_visibility" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"hubspot.com","keywords":["best crm for startups","crm software"]}'
```

`data` includes `domain`, `location`, `fetched_at`, `positions`, and `summary`.

## Inspect AI visibility

`POST /v1/tools/inspect_ai_visibility`

How often a domain is cited as a source in AI answers, alone or against named competitor domains.

Credit cost: `20`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `domain` | string | Yes | | 2-253 characters. Pass a domain, never a brand name |
| `competitors` | string\[] | No | | Up to 9 competitor domains |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/inspect_ai_visibility" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"notion.so","competitors":["coda.io","clickup.com"]}'
```

Coverage is Google AI Overview only. It does not cover ChatGPT, Claude, Gemini, Perplexity, or CoPilot, and the number is "your domain cited as a source," not "how often AI talks about you." Call it solo (no competitors) to also get `data.sample_answers` — real questions where the domain is cited, with the sources cited alongside it. With competitors you get the ranked comparison and share-of-citations gap instead. A domain with no AI citations returns a `brand_mentions` fact with `mentions: 0` plus a `next_actions` pointer to `discover_ai_citations`.

`data` includes `domain`, `location`, `platform`, `competitors`, `mentions`, and, in the solo case, `sample_answers`.

## Discover AI citations

`POST /v1/tools/discover_ai_citations`

Which domains AI cites across a category — the map of where to earn a mention.

Credit cost: `22`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `topic` | string | No\* | | 1-200 characters. The real category keyword |
| `domain` | string | No\* | | 2-253 characters. Category is derived from the domain's top keywords |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |
| `limit` | integer | No | `20` | 1-100 |

\*Provide `topic` or `domain`; one is required. If both are given, `topic` wins. Prefer `topic` whenever you know the brand's real category.

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/discover_ai_citations" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"topic":"project management software"}'
```

Coverage is Google AI Overview only. When the category is derived from a thin domain that barely ranks, `data.category_confidence` returns `derived_weak` and a `next_actions` entry asks you to re-run with an explicit `topic`. Results are domain-anchored (which domains are cited as sources), never brand-name matched.

`data` includes `topic`, `source`, `location`, `platform`, `citation_map`, `low_signal`, and `category_confidence`.

## Audit site

`POST /v1/tools/audit_site`

Run a fast technical and content health audit over sampled pages.

Credit cost: `9`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `domain` | string | Yes | | Domain to audit |
| `max_pages` | integer | No | `10` | 1-20 |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/audit_site" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"stripe.com","max_pages":10}'
```

`data` includes `domain`, `discovery_source`, `pages_discovered`, `pages_audited`, `pages_excluded`, `fetch_failures`, `render_warning`, `templates_sampled`, `onpage_score`, `issues_summary`, `excluded_summary`, `page_class_summary`, `worst_page`, `recommendations`, `issue_clusters`, and compact `pages`.

Scope: the audit reads raw HTML. It does not execute JavaScript or measure Core Web Vitals.

## Inspect keyword

`POST /v1/tools/inspect_keyword`

Drill into one keyword.

Credit cost: `5`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `keyword` | string | Yes | | 1-200 characters |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/inspect_keyword" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"keyword":"best crm for startups"}'
```

`data` includes `keyword`, `location`, `monthly_volume`, `cpc_usd`, `competition_level`, `intent`, `trend`, `serp_top`, and `serp_features`.

## Inspect page

`POST /v1/tools/inspect_page`

Drill into one exact URL.

Credit cost: `3`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `url` | string | Yes | | 8-2048 characters |
| `location` | string | No | `United States` | Market location |
| `language` | string | No | `English` | Search language |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/inspect_page" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://stripe.com/payments"}'
```

`data` includes `url`, `location`, `organic_keywords`, `estimated_organic_traffic_per_month`, and `top_keywords`.

## Export dataset

`POST /v1/tools/export_dataset`

Fetch a full dataset by URI from a previous response `resources` entry.

Credit cost: `1`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `uri` | string | Yes | | 8-512 characters. Must be a valid OpenRush dataset URI. |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/export_dataset" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"uri":"openrush://dataset/..."}'
```

`data` includes `uri`, `items`, `available`, and optional `note`.

## Owned data (Search Console, Analytics & Google Ads)

These tools read your own data through a connected Google source — Search Console for search performance, Google Analytics for website traffic, Google Ads for ad performance. They appear only when owned data is enabled for your account, so check `/v1/capabilities` first. See [Connections](https://openrush.com/docs/api-reference/connections.md) to connect a property or ad account.

### Get search performance

`POST /v1/tools/get_search_performance`

Your measured Search Console performance: real clicks, impressions, CTR, and impression-weighted position. This is Google's own data, not an estimate.

Credit cost: `2`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `website_id` | string | No | | Selector. Omit both to auto-select the only connected website |
| `domain` | string | No | | Interchangeable with `website_id` |
| `period` | string | No | `last_28_days` | `last_7_days`, `last_28_days`, `last_3_months`, `last_6_months`, `last_12_months`, `last_16_months` |
| `compare_to` | string | No | `previous_period` | `previous_period`, `previous_year`, `none` |
| `group_by` | string\[] | No | `[]` | Any of `query`, `page`, `date`, `device`, `country`. Up to 2. Omit for the site total |
| `search_type` | string | No | `web` | `web`, `image`, `video`, `news`, `discover` |
| `filters` | object\[] | No | `[]` | Up to 10. Each: `dimension`, `operator`, `expression` |
| `limit` | integer | No | `100` | 1-1000 |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/get_search_performance" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"period":"last_28_days","group_by":["query"]}'
```

`data` includes `website_id`, `domain`, `search_type`, `period`, `date_range`, `compare_to`, `data_state`, `group_by`, `summary`, `rows`, and `notes`.

If the account has several connected websites, the call returns a `website_required` error listing safe options. If nothing is connected it returns `connection_required` or `binding_required`. See [Errors](https://openrush.com/docs/fundamentals/errors.md).

### Get website analytics

`POST /v1/tools/get_website_analytics`

Your measured Google Analytics traffic: real sessions, users, new users, engaged sessions, page views, and engagement time. This is Google's own data, not an estimate. Every reported ratio (engagement rate, average engagement time, views per session) is recomputed from the base counts.

Credit cost: `2`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `website_id` | string | No | | Selector. Omit both to auto-select the only connected website |
| `domain` | string | No | | Interchangeable with `website_id` |
| `period` | string | No | `last_28_days` | `last_7_days`, `last_28_days`, `last_3_months`, `last_6_months`, `last_12_months` |
| `compare_to` | string | No | `previous_period` | `previous_period`, `previous_year`, `none` |
| `report` | string | No | `overview` | A prebuilt slice: `overview`, `channel`, `source_medium`, `source`, `medium`, `campaign`, `landing_page`, `country`, `city`, `device`, `browser`, `operating_system`, `date` |
| `group_by` | string\[] | No | `[]` | Lower-level equivalent of `report`; the first meaningful token decides the slice. Omit for the `overview` |
| `filters` | object\[] | No | `[]` | Up to 10. Each: `dimension`, `operator`, `expression` |
| `limit` | integer | No | `100` | 1-1000 |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/get_website_analytics" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"period":"last_28_days","report":"channel"}'
```

`data` includes `website_id`, `domain`, `report`, `period`, `date_range`, `compare_to`, `data_state`, `summary`, and — for a grouped report — `group_by` and `rows`.

If the account has several connected websites, the call returns a `website_required` error listing safe options. If nothing is connected it returns `connection_required` or `binding_required`. See [Errors](https://openrush.com/docs/fundamentals/errors.md).

### Get ad performance

`POST /v1/tools/get_ad_performance`

Your measured Google Ads performance: real spend, impressions, clicks, conversions, and conversion value, with CTR, average CPC, CPM, conversion rate, cost per conversion, and ROAS recomputed from those base counts. This is Google's own data, not an estimate. One call reads one ad account, so every amount is in that account's currency and is never converted.

Credit cost: `2`

Request body:

| Field | Type | Required | Default | Notes |
| - | - | - | - | - |
| `platform` | string | No | | `google_ads`. Omit to auto-select when one ad platform is connected |
| `ad_account` | string | No | | An OpenRush ad-account id from `list_connections` or an `account_required` error. Not a raw Google customer id. Omit to auto-select the only activated account |
| `period` | string | No | `last_28_days` | `last_7_days`, `last_28_days`, `last_3_months`, `last_6_months`, `last_12_months` |
| `compare_to` | string | No | `previous_period` | `previous_period`, `previous_year`, `none` |
| `report` | string | No | `overview` | A prebuilt slice: `overview`, `campaign`, `ad_group`, `asset_group`, `ad`, `date`, `device`, `network`, `keyword`, `search_term` |
| `group_by` | string\[] | No | `[]` | Lower-level equivalent of `report`; the first meaningful token decides the slice. Omit for the `overview` |
| `filters` | object\[] | No | `[]` | Up to 10. Each: `dimension` (`campaign`, `device`, `network`), `operator` (`equals`, or `contains` for campaign), `expression` |
| `limit` | integer | No | `100` | 1-1000 |

```bash theme={null}
curl -X POST "https://api.openrush.com/v1/tools/get_ad_performance" \
  -H "Authorization: Bearer $OPENRUSH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"period":"last_28_days","report":"campaign"}'
```

`data` includes `platform`, `ad_account`, `account_name`, `customer_id_display`, `currency`, `account_timezone`, `attribution`, `report`, `period`, `date_range`, `compare_to`, `data_state`, `summary`, and `notes`. The `overview` report adds `overview` with top campaigns, a daily trend, and a network split; a grouped report adds `group_by`, `rows`, and `row_count`. Each campaign row carries `campaign_type`, so Performance Max campaigns (which report through `asset_group` rather than `ad_group` and `ad`) are easy to tell apart. `keyword` and `search_term` cover Search campaigns only.

If several ad platforms are connected the call returns `platform_required`; if several ad accounts are activated it returns `account_required` listing safe options; if nothing is connected or activated it returns `connection_required`. See [Errors](https://openrush.com/docs/fundamentals/errors.md).

### List connections

`GET /v1/me/websites`

List the websites on the account with each one's connection state per source, plus the activated ad accounts. This is exposed to agents as the `list_connections` tool (`list_websites` still works as an alias); over the REST API it is the account endpoint below. Free.

Credit cost: `0`

```bash theme={null}
curl "https://api.openrush.com/v1/me/websites" \
  -H "Authorization: Bearer $OPENRUSH_KEY"
```

Returns `websites`, each with `website_id`, `name`, `primary_domain`, `is_default`, and `connections` (per-source state such as `{"gsc":"connected","website_analytics":"connected"}`), and `ad_accounts`, each with `ad_account` (the opaque id to pass to `get_ad_performance`), `platform`, `name`, `currency`, `customer_id_display`, and `connection_status`. Only activated ad accounts are listed. An account with nothing connected returns empty lists, which agents surface as `connection_required`.


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