JSON over HTTPS, included on every plan. Everything you see in the app, from every ad and advertiser to share of voice, landing pages and alerts, is available to your scripts, BI tool or CRM. Webhooks push alerts to your own endpoint (Starter and Pro).
Create an account and copy your key from Settings → API key. Send it on every request:
Authorization: Bearer bw_your_key
Base URL: https://serpbids.com. Keywords are addressed by numeric id or slug.
curl https://serpbids.com/v1/keywords/crm-for-small-business/ads \ -H "Authorization: Bearer bw_your_key"
{"keyword": {"id": 1, "keyword": "crm for small business", "country": "US", ...},
"data": [{"advertiser": "acme-crm.com", "position": "top-1",
"headline": "...", "description": "...",
"destination": "acme-crm.com/small-business",
"seen_at": "2026-10-09T14:02:00Z", ...}]}| Method | Path | What it does |
|---|---|---|
| GET | /v1/keywords | List tracked keywords with next and last scan times. |
| POST | /v1/keywords | Add keywords. Body: {"keywords": ["..."], "country": "US", "every_hours": 24}. every_hours: 4, 6, 12, 24, 48 or 168 (or frequency in scans a day). Plan limits apply. |
| PATCH | /v1/keywords/{id|slug} | Change every_hours (or frequency) or set paused. |
| DELETE | /v1/keywords/{id|slug} | Stop tracking and delete the history. |
| GET | /v1/keywords/{id|slug}/ads | Every ad seen. Query: days (default 30), since (ISO time), limit. |
| GET | /v1/keywords/{id|slug}/ads.csv | Same as CSV. |
| GET | /v1/keywords/{id|slug}/share-of-voice | Share of voice per advertiser plus a daily series. Query: days. |
| GET | /v1/keywords/{id|slug}/landing-pages | Landing pages per advertiser: exact landing hosts (subdomains included), pages shown in the ads, tracking hosts. Query: days. |
| GET | /v1/keywords/{id|slug}/metrics | Search demand: monthly searches (12 months), % change, cost per click, top-of-page bids, competition, intent, AI Overview. |
| GET | /v1/keywords/{id|slug}/spend | Estimated monthly ad spend per advertiser, with margin and time-of-day pattern. Query: days. |
| GET | /v1/keywords/{id|slug}/scans | Scan log with status and ad count. |
| GET | /v1/advertisers | Every advertiser on your keywords with keyword count and top-of-page rate. |
| GET | /v1/advertisers/{domain} | One advertiser: keywords, ad copy versions, landing pages. |
| GET | /v1/alerts | Alerts. Query: since, limit. |
If a slug is tracked in several countries, add ?country=GB or use the numeric id. Errors return JSON {"detail": "..."} with 401, 403 (plan limit), 404 or 409.
Starter and Pro. Set an https endpoint in Settings and we POST every alert to it as JSON, the moment the scan that found it finishes.
| Event | When |
|---|---|
brand_bid | An advertiser starts bidding on one of your brand keywords. |
new_advertiser | An advertiser shows up on a keyword for the first time. |
new_ad | An advertiser runs an ad with a headline we haven't seen on that keyword. |
new_destination | An advertiser sends the click to a new landing page. |
test | Sent by the "Send test event" button in Settings. |
Headers: X-Serpbids-Event (the event), X-Serpbids-Timestamp (unix seconds) and X-Serpbids-Signature: sha256= + HMAC-SHA256 of timestamp + "." + raw body, keyed with your signing secret from Settings. Compare it in constant time and reject old timestamps.
import hmac, hashlib
expected = "sha256=" + hmac.new(secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, request.headers["X-Serpbids-Signature"])
{"event": "brand_bid",
"data": {"id": 41, "event": "brand_bid", "created_at": "2026-11-02T09:41:00Z",
"message": "brightdesk.com started bidding on \"yourbrand crm\".",
"advertiser": "brightdesk.com",
"keyword": {"id": 7, "text": "yourbrand crm", "slug": "yourbrand-crm", "country": "US"},
"ad": {"advertiser": "brightdesk.com", "position": "top-1",
"headline": "Switching From YourBrand? Try BrightDesk", "description": "Import everything in one click.",
"destination": "brightdesk.com/switch", "seen_at": "2026-11-02T09:41:00Z", ...}}}
Answer with any 2xx within 10 seconds. Failed deliveries are listed in Settings; they are not retried.
Serpbids · Terms · Privacy · Made by the team behind Adyntel