Zoekworden Ad AI Automate
Inloggen

Documentation

Zoekworden REST API v1 - closed beta - English only

What this page covers. Zoekworden ("Ad AI Automate") is a campaign management tool for Google Ads. An advertiser links their own Google Ads account to our manager account 548-189-4317 and then manages that account through the AI assistant they already use. The assistant never talks to Google directly: it talks to the Zoekworden REST API documented here, and our server executes the operation after validating it. The machine-readable version of this contract is openapi.json, which is public and needs no key to read.

Status. The service is in closed beta and free. Accounts are issued on request - write to main@zoekworden.nl. Figures shown inside the product are simulated demo data until the Google Ads connection goes live.

Setting up the connection

  • Sign in at zoekworden.nl and open the Connection page (log in).
  • Generate an API key. Give it a name and decide whether it may write. Keys are read-only by default; write access - the ability to create campaigns at all - is a separate opt-in per key.
  • Paste the skill block into your AI assistant. The Connection page renders one block of instructions with your key already embedded, so onboarding is a single copy-paste. There is no OAuth dance, no Google password to hand over and nothing to install.

Linking the advertising account itself happens in Google's own interface: the advertiser links their Google Ads account to manager account 548-189-4317 from their side. That action is the consent record. We never ask for a Google password and never hold the advertiser's Google credentials, and unlinking there ends our access immediately.

Authentication

Every request carries the key in a header. Either form works:

Authorization: Bearer zw_...
X-Api-Key: zw_...

Keys are stored as SHA-256 hashes, displayed once at creation, revocable at any time, and limited to ten active keys per account. A lost key cannot be recovered because the plaintext was never stored - revoke it and generate a new one. The API is stateless: no sessions, no cookies, no CSRF token.

Endpoints

Base URL: https://zoekworden.nl/api. The paths below are relative to it, exactly as they are declared in openapi.json and in the skill block, so GET /v1/me is https://zoekworden.nl/api/v1/me.

Endpoint What it returns
GET /v1/me Identifies the key: account, key prefix, scope and server time.
GET /v1/keywords/trends Keyword metrics and a daily search-volume series from third-party providers. Parameters: q, country, days, limit.
GET /v1/campaigns The key owner's own campaigns with budgets, keywords and status.
POST /v1/campaigns Creates exactly one campaign, paused. Requires write scope and an Idempotency-Key header.
GET /v1/campaigns/{id} One campaign with its daily series: impressions, clicks, spend, conversions, ROAS and ACOS.
GET /v1/usage Requests and errors this month, remaining quota and the rate limit in force.
GET /v1/recommendations Open optimisation suggestions produced by the service. During the closed beta this is the shared demo suggestion set, identical for every beta account; it is scoped per advertiser when the live Google Ads connection is switched on.
GET /v1/openapi.json The OpenAPI 3.1 contract. Public, no key required.

Creating a campaign

This is the only endpoint that changes anything. The assistant reads trends and performance, reasons about them on its own side, and then sends one POST request describing the campaign:

POST https://zoekworden.nl/api/v1/campaigns
Authorization: Bearer zw_****************
Idempotency-Key: 6f1c9c1e-8f5e-4a3b-9d2a-1b7f0e5c4d21
Content-Type: application/json

{ "name": "NL Search - Winter Tyres",
  "daily_budget_eur": 25.0,
  "budget_cap_eur": 50.0,
  "target_country": "nl",
  "keywords": ["winterbanden kopen", "winterbanden aanbieding"],
  "final_url": "https://example.nl/winterbanden" }

201 Created
{ "id": 7, "status": "paused", "external_resource": "customers/.../campaigns/...",
  "note": "Campaign created in PAUSED state. Enabling it is a human decision
           made in the Google Ads UI - the API cannot activate spending." }
  • Paused only. The status is fixed at creation. No endpoint in our API surface can set a campaign to enabled - that verb does not exist. A human reviews the campaign in the Google Ads interface and enables it there.
  • Budget ceiling. budget_cap_eur is set by the account owner. A daily_budget_eur above it is rejected, and the API offers no way to raise the ceiling.
  • Idempotency-Key is mandatory. One key maps to exactly one campaign, enforced by a database constraint. If a request times out, retry it with the same key: you get the original campaign back, flagged as a replay, never a duplicate.
  • Schema validation. The body is checked against a JSON Schema server-side. Required: name, daily_budget_eur, budget_cap_eur, keywords. Optional: target_country (ISO 3166 alpha-2, default nl) and final_url. Unknown fields are rejected, not ignored.
  • Audit log. Every mutation is recorded immutably: which key, what payload, when, and the resulting Google Ads resource name.

Errors

Failures come back with the matching HTTP status and one envelope:

{ "error": { "message": "human readable explanation", "code": "machine_code" } }
  • 401 missing_api_key or invalid_api_key - no key was sent, or the key is unknown or revoked.
  • 403 insufficient_scope - a read-only key tried to create a campaign. Generate a key with write access instead.
  • 400 schema_validation - the body failed validation; the message names the offending field. Fix the body, do not resend it unchanged.
  • 400 missing_idempotency_key - the POST arrived without the required header.
  • 429 rate_limited - too many requests in one minute. Wait and retry.

Limits

The default limit is 60 requests per minute per key. Every authenticated request is metered, and an optional monthly quota per account can be set on top of it. Both the current counts and the limits in force are readable at any time from GET /v1/usage.

Data policy

Google Ads API data is used only to serve the advertiser whose account it came from, and is never redistributed to third parties. Because the advertiser's assistant runs on a third-party LLM platform, we treat our public API boundary as the line Google Ads API data does not cross.

  • Returned through the API: statistics of the advertiser's own account (spend, clicks, impressions, conversions, ROAS and ACOS per campaign and per day), the status and IDs of their own operations, keyword and trend data sourced from providers outside Google, and the service's own optimisation suggestions, which during the beta are demo content and contain no Google Ads API data at all.
  • Never returned: raw Keyword Planner output - search volumes, bid estimates, keyword idea lists. Planning services are called server-side only, scoped to the advertiser's own account, while a campaign is being built or reviewed for them. Also never returned: Google Ads data belonging to another advertiser, or any aggregated or derived feed built from Google Ads API data.

The service runs on servers in the European Union (Amsterdam) over HTTPS with HSTS. The website uses functional cookies only - session, CSRF and language - and carries no analytics or advertising trackers, which is why there is no cookie banner. Details are in the privacy policy and the terms of service.

Questions

Zoekworden is built and operated by Serhii Nasanovych, an independent Google Ads developer based in the Netherlands. There is no registered company: this is an individual developer project. Write to main@zoekworden.nl for an account or with a question about the contract. See also about and pricing.