API & webhooks

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).

Authentication

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.

All ads seen for a keyword

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", ...}]}
MethodPathWhat it does
GET/v1/keywordsList tracked keywords with next and last scan times.
POST/v1/keywordsAdd 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}/adsEvery ad seen. Query: days (default 30), since (ISO time), limit.
GET/v1/keywords/{id|slug}/ads.csvSame as CSV.
GET/v1/keywords/{id|slug}/share-of-voiceShare of voice per advertiser plus a daily series. Query: days.
GET/v1/keywords/{id|slug}/landing-pagesLanding pages per advertiser: exact landing hosts (subdomains included), pages shown in the ads, tracking hosts. Query: days.
GET/v1/keywords/{id|slug}/metricsSearch demand: monthly searches (12 months), % change, cost per click, top-of-page bids, competition, intent, AI Overview.
GET/v1/keywords/{id|slug}/spendEstimated monthly ad spend per advertiser, with margin and time-of-day pattern. Query: days.
GET/v1/keywords/{id|slug}/scansScan log with status and ad count.
GET/v1/advertisersEvery 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/alertsAlerts. 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.

Webhooks

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.

EventWhen
brand_bidAn advertiser starts bidding on one of your brand keywords.
new_advertiserAn advertiser shows up on a keyword for the first time.
new_adAn advertiser runs an ad with a headline we haven't seen on that keyword.
new_destinationAn advertiser sends the click to a new landing page.
testSent 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