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

# Paid advertising

> Create and operate paid campaigns through a connected advertiser account.

Google Search is the first supported provider. Connect the advertiser account through
[Connections](/docs/api/connections) before calling these routes. Its auth configuration must include a
Google Ads developer token; connections created from an older configuration without one must be
recreated.

<Warning>Media spend is billed by the connected Google Ads account, not from Naive credits. Creating
a campaign cannot spend: the campaign starts paused and is the single spend gate. Activation can
incur external charges up to the campaign's finite budget.</Warning>

## Create a search campaign

`POST /v1/ads/search_campaigns` — scope `billing:write`, live key and `Idempotency-Key` required

```json theme={"system"}
{
  "provider": "google",
  "connection_id": "conn_google",
  "customer_id": "1234567890",
  "name": "Founder Frame launch",
  "final_url": "https://founderframehq.com/",
  "budget_micro_usd": 50000000,
  "cpc_ceiling_micro_usd": 4000000,
  "start_date": "2026-10-01",
  "end_date": "2026-10-08",
  "keywords": ["b2b content agency"],
  "headlines": ["Content That Earns Attention", "Founder Frame", "B2B Content Systems"],
  "descriptions": ["Turn expert insight into demand.", "Build a repeatable content engine."]
}
```

The total campaign budget and CPC ceiling are integer micro-USD. Customer IDs contain ten digits
without dashes. The operation creates the finite custom-period budget, US/English targeting, search
ad group, phrase-match keywords and responsive search ad. The children are ready but the campaign
is paused, so nothing serves until activation. The configured deployment ceiling is \$100 by default
(`VETTA_AD_MAX_BUDGET_MICRO_USD=100000000`), and the primitive never raises a budget.

## List and inspect

`GET /v1/ads/campaigns?connection_id={connection}&customer_id={customer}` — scope `agents:read`

`GET /v1/ads/campaigns/{campaign}/insights?connection_id={connection}&customer_id={customer}` —
scope `agents:read`

Both read current provider state. A campaign with no ad has `final_url: null` rather than being
omitted from the list. Insights report impressions, clicks, conversions and `spend_micro_usd`;
Naive does not copy OAuth credentials or maintain a second campaign ledger.

## Activate or pause

`POST /v1/ads/campaigns/{campaign}/activate` — scope `billing:write`, live key required

```json theme={"system"}
{
  "connection_id": "conn_google",
  "customer_id": "1234567890",
  "acknowledge_external_spend": true
}
```

The literal acknowledgement is required because activation starts external media spend. Naive only
activates a campaign it created for that exact connection and customer, after re-reading the
provider budget and dates and confirming the custom-period total remains within the deployment
ceiling. To stop a campaign, call `POST /v1/ads/campaigns/{campaign}/pause` with `connection_id` and
`customer_id` under scope `agents:write`.


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