Developers
Ads Lighthouse API
Read saved observations, histories and reports. Update projects, workspace settings and reviews, with the same rules and limits as the app.
The REST API is included in the Scale plan and above, including trials of those plans. The MCP server is included in every plan.
Authentication
Create a key in Settings > API and MCP. The account owner and account admins can create keys. The full key is shown only once. Choose read only, or read and write.
Send the key in the Authorization header of every request. A key acts for the whole account. It stops working as soon as it is revoked, or when the person who created it leaves the account or stops being an admin.
The API does not accept browser sessions or cross-origin browser requests. Keep keys on a server or in a secret manager.
Authorization: Bearer als_your_keyQuick start
List your projects, then read the last 7 days of saved checks for one of them. Every project endpoint accepts the project id, the brand domain or the exact project name.
# List your projects
curl -s https://adslighthouse.com/api/v1/projects \
-H "Authorization: Bearer $ADS_LIGHTHOUSE_API_KEY"
# Saved checks for one project in the last 7 days, Google on mobile
curl -s -G https://adslighthouse.com/api/v1/projects/nike.example/observations \
-H "Authorization: Bearer $ADS_LIGHTHOUSE_API_KEY" \
--data-urlencode "range=7d" \
--data-urlencode "engine=google" \
--data-urlencode "device=mobile"const base = "https://adslighthouse.com/api/v1";
const headers = { Authorization: `Bearer ${process.env.ADS_LIGHTHOUSE_API_KEY}` };
// Advertisers seen on the project's searches, busiest first
const response = await fetch(`${base}/projects/nike.example/advertisers?range=30d`, { headers });
if (!response.ok) {
const { error, request_id } = await response.json();
throw new Error(`${error.code}: ${error.message} (${request_id})`);
}
const report = await response.json();
for (const advertiser of report.data)
console.log(advertiser.domain, advertiser.visibility, report.note ?? "");Endpoints
All paths are relative to the base URL below. Read endpoints need the read scope, and changes need write access. Each endpoint lists its scope and side effects.
https://adslighthouse.com/api/v1| Method | Path | What it does | Scope |
|---|---|---|---|
GET | /account | Plan, monthly allowances, usage and rate limit | read |
GET | /projects | Projects in the account | read |
POST | /projects | Create a project and start its first checks | write |
GET | /projects/{project_id} | One project's configuration and data coverage | read |
PATCH | /projects/{project_id} | Change a project's monitoring plan, brand or affiliate settings | write |
DELETE | /projects/{project_id} | Permanently delete a project and its saved data | write |
GET | /projects/{project_id}/keywords | Monitored keywords with saved checks and ads in a window | read |
POST | /projects/{project_id}/keywords | Add keywords to a project | write |
DELETE | /projects/{project_id}/keywords | Stop monitoring several keywords | write |
DELETE | /projects/{project_id}/keywords/{keyword_id} | Stop monitoring one keyword | write |
GET | /projects/{project_id}/observations | Saved checks with the paid ads they found | read |
GET | /projects/{project_id}/advertisers | Advertiser domains with visibility and signals | read |
GET | /projects/{project_id}/affiliate-findings | Your affiliate IDs seen behind ads that use your brand | read |
GET | /alert-events | Alerts fired for the account | read |
POST | /projects/{project_id}/checks | Start an on-demand check of a project's keywords | write |
GET | /projects/{project_id}/checks | A project's recent background activity and queued searches | read |
GET | /projects/{project_id}/checks/{run_id} | Progress of an on-demand check | read |
GET | /projects/{project_id}/analytics | Chart-ready paid-search and Shopping aggregates for one project | read |
GET | /projects/{project_id}/organic-observations | Organic search observations with detailed result content | read |
GET | /projects/{project_id}/summary | Headline numbers for a project and window | read |
GET | /projects/{project_id}/timeseries | Checks, ads and advertisers by local day, week or month | read |
GET | /projects/{project_id}/advertisers/{domain} | One advertiser's metrics, category and saved ads | read |
GET | /projects/{project_id}/competitors | Other advertisers ranked by ad occurrences, with your categories | read |
POST | /projects/{project_id}/advertisers/{domain}/classification | Save your team's category for an advertiser domain | write |
GET | /projects/{project_id}/keywords/{keyword_id}/report | One keyword's saved checks, ads and advertisers in a window | read |
GET | /projects/{project_id}/keywords/{keyword_id}/ads | Advertisers or distinct ads seen for one keyword | read |
GET | /projects/{project_id}/affiliate-ids | Your affiliate IDs seen in saved ad URLs | read |
POST | /projects/{project_id}/affiliate-findings/{affiliate_id}/status | Set the review status of a non-compliant affiliate ID | write |
POST | /projects/{project_id}/affiliate-findings/status | Set one review status on several non-compliant affiliate IDs at once | write |
GET | /projects/{project_id}/shopping-products | Sponsored product listings seen on Google Shopping captures | read |
GET | /projects/{project_id}/exports/paid-results | The rows of the Paid results CSV export, as JSON | read |
GET | /projects/{project_id}/exports/paid-results-by-keyword | The rows of the Paid results By keyword view, as JSON | read |
GET | /projects/{project_id}/exports/affiliate-cases | The rows of the Non-compliant affiliates CSV export, as JSON | read |
GET | /projects/{project_id}/exports/affiliate-cases/{affiliate_id}/ads | Every ad behind one non-compliant affiliate ID, as in the Send report CSV | read |
GET | /projects/{project_id}/advertisers/{domain}/history | When and where one advertiser appeared, with the observation schedule | read |
GET | /projects/{project_id}/advertisers/{domain}/heatmap | Presence by local hour and weekday | read |
GET | /projects/{project_id}/advertisers/{domain}/ad-copy | One advertiser's distinct ad copy, newest first | read |
GET | /projects/{project_id}/ad-copy-changes | Recent ad copy changes across advertisers | read |
GET | /projects/{project_id}/advertisers/{domain}/identity | Who Google's Ads Transparency Center says advertises to a domain | read |
POST | /projects/{project_id}/advertisers/{domain}/identity | Read Google's Ads Transparency record for an advertiser domain (1 on-demand check) | write |
GET | /projects/{project_id}/advertiser-identity-settings | Whether new advertiser domains are looked up automatically | read |
POST | /projects/{project_id}/advertiser-identity-settings | Turn automatic advertiser identity lookups on or off | write |
POST | /check-demand | Forecast the monthly checks and allowance for a proposed change | read |
GET | /monitoring-options | Markets, search engines, devices and schedules you can configure | read |
GET | /locations | Find cities and regions available for monitoring in a market | read |
GET | /account/time-zone | Your personal time zone preference | read |
PATCH | /account/time-zone | Change your personal time zone preference | write |
GET | /account/theme | Your personal appearance preference | read |
PATCH | /account/theme | Change your personal appearance preference | write |
GET | /alert-rules | Alert rules configured in the account | read |
POST | /alert-rules | Create an alert rule (email, Slack or webhook) | write |
GET | /alert-rules/{rule_id} | One alert rule | read |
POST | /alert-rules/{rule_id} | Enable, disable or change an alert rule | write |
DELETE | /alert-rules/{rule_id} | Delete an alert rule and its alert history | write |
POST | /alert-rules/{rule_id}/test | Queue a synthetic alert through a rule's channel | write |
GET | /alert-rules/{rule_id}/preview | What a summary rule's next delivery would contain so far | read |
POST | /alert-rules/{rule_id}/rotate-secret | Replace a webhook rule's signing secret | write |
GET | /alert-events/{event_id} | One alert with its delivery record | read |
GET | /team | Members, roles and open invitations | read |
POST | /team/invitations | Email an invitation to join the account | write |
POST | /team/invitations/{invitation_id}/resend | Send an open invitation again with a new link | write |
DELETE | /team/invitations/{invitation_id} | Revoke an open invitation | write |
POST | /team/members/{user_id} | Make a member an admin or an admin a member | write |
DELETE | /team/members/{user_id} | Remove a person from the account | write |
GET | /accounts | The account this credential can use | read |
GET | /account/overview | Plan limits, subscription dates, meters and forecast | read |
GET | /me/email-preferences | Your product email and newsletter preferences | read |
POST | /me/email-preferences | Turn product emails or the newsletter on or off | write |
GET | /projects/{project_id}/google-connections | Your Google Ads and Search Console connections in a project | read |
GET | /projects/{project_id}/google-connections/{connection_id}/accounts | Google Ads customers or Search Console sites a connection can read | read |
GET | /projects/{project_id}/google-connections/{connection_id}/ads-report | Keyword or search term performance from Google Ads | read |
GET | /projects/{project_id}/google-connections/{connection_id}/search-console-report | Search Console clicks, impressions, CTR and position | read |
POST | /projects/{project_id}/redirect-traces | Queue a server-side trace of a saved ad destination | write |
GET | /projects/{project_id}/redirect-traces | Traced redirect chains of a project | read |
GET | /projects/{project_id}/redirect-traces/{trace_id} | One traced redirect chain | read |
GET | /projects/{project_id}/redirect-traces/{trace_id}/archive-link | A short-lived link to download a trace's web archive (.warc.gz) | read |
GET | /projects/{project_id}/policy-rules | A project's policy rules | read |
POST | /projects/{project_id}/policy-rules | Declare a policy rule for a project | write |
GET | /projects/{project_id}/policy-rules/{rule_id} | One policy rule | read |
POST | /projects/{project_id}/policy-rules/{rule_id} | Rename, pause, reconfigure or rescope a policy rule | write |
DELETE | /projects/{project_id}/policy-rules/{rule_id} | Delete a policy rule and keep its cases | write |
POST | /projects/{project_id}/policy-rule-preview | What a draft rule would match, without saving it | read |
POST | /projects/{project_id}/policy-rule-evaluation | Check saved ads against the enabled rules and record cases | write |
GET | /projects/{project_id}/policy-cases | Cases opened by policy rules | read |
GET | /projects/{project_id}/policy-cases/{case_id} | One case with its timeline | read |
POST | /projects/{project_id}/policy-cases/{case_id} | Change a case's status or owner | write |
GET | /projects/{project_id}/policy-cases/{case_id}/evidence | The saved ads that matched a case's rule | read |
POST | /projects/{project_id}/policy-cases/{case_id}/notes | Add a note to a case's timeline | write |
GET | /projects/{project_id}/trademark | The project's trademark, registrations, owner and contact | read |
POST | /projects/{project_id}/trademark | Save the project's trademark details for complaints | write |
GET | /projects/{project_id}/complaint-package | What a platform's trademark complaint form asks for, from one case | read |
GET | /projects/{project_id}/case-complaints | The complaints recorded on a case and their outcomes | read |
POST | /projects/{project_id}/case-complaints | Record that a complaint was filed on a platform's form | write |
POST | /projects/{project_id}/case-complaints/{complaint_id}/outcome | Record what the platform decided about a filed complaint | write |
GET | /outreach-templates | The account's message templates for partners and advertisers | read |
POST | /outreach-templates | Add one of the account's own outreach templates | write |
POST | /outreach-templates/{template_id} | Edit a default or one of the account's own templates | write |
DELETE | /outreach-templates/{template_id} | Delete the account's own template, or restore a default | write |
GET | /projects/{project_id}/outreach-message | A ready-to-send message for a case from a template | read |
POST | /projects/{project_id}/outreach-records | Record on a case that a message was sent to the partner or advertiser | write |
POST | /projects/{project_id}/evidence-packs | Request a PDF of one case for legal teams, networks or a complaint | write |
GET | /projects/{project_id}/evidence-packs/{pack_id} | Status of one case evidence pack | read |
GET | /projects/{project_id}/evidence-packs/{pack_id}/download-link | A short-lived link to download a ready evidence pack | read |
GET | /projects/{project_id}/affiliate-findings/{affiliate_id}/case | One non-compliant affiliate case with its timeline | read |
POST | /projects/{project_id}/affiliate-findings/{affiliate_id}/notes | Add a note to an affiliate case's timeline | write |
POST | /projects/{project_id}/reports | Request a project PDF report for a window and filters | write |
GET | /projects/{project_id}/reports | A project's PDF reports, newest first | read |
GET | /projects/{project_id}/reports/{report_id} | Status of one PDF report | read |
GET | /projects/{project_id}/reports/{report_id}/download-link | A short-lived link to download a ready report | read |
GET | /account/report-branding | The account's agency branding for white-label PDFs | read |
PATCH | /account/report-branding | Change the account's agency branding for white-label PDFs | write |
DELETE | /account/report-branding | Remove the account's agency branding | write |
POST | /feedback | Send product feedback to the Ads Lighthouse team | write |
GET | /projects/{project_id}/reports/{report_id}/pdf | Download a ready PDF report | read |
GET | /projects/{project_id}/evidence-packs/{pack_id}/pdf | Download a ready case evidence pack | read |
GET | /projects/{project_id}/screenshots/{screenshot_id} | Download a results-page screenshot | read |
GET | /projects/{project_id}/shopping-products/{product_id}/image | Fetch a saved Shopping product image | read |
GET | /projects/{project_id}/landing-screenshots/{page_id} | Download a captured page preview | read |
Dates and filters
Reports use the same filters as the app: engine, device, os, country and location. Send one value, repeat the parameter, or pass a JSON array such as engine=["google","bing"]. Values in one filter combine with OR, and different filters combine with AND.
Dates default to the last 30 days. Use range=7d, 14d, 30d or 12m, or range=custom with from and to (YYYY-MM-DD). Days start and end in the time zone of the person who created the key, or in the IANA time zone you pass as time_zone. The response echoes the exact window it used.
Pagination
Lists return data and next_cursor. Pass next_cursor as cursor to get the next page, with the same filters. It is null on the last page. limit accepts 1 to 200 and defaults to 50.
Report rows, such as advertisers, are computed for the whole filtered selection before paging, so shares do not depend on the page size.
Changes and paid checks
Write operations can update projects, keywords, alert rules, team access, policy and affiliate reviews, and personal settings. Some also send invitations or test alerts, request reports, or trace saved ad destinations. Check each endpoint's scope and effects before you call it.
Creating a project and running an on-demand check start searches that use your plan's allowance. Both need an Idempotency-Key header with a unique value, such as a UUID. Repeating a request with the same key returns the first result and does not use your allowance or run the checks again. Reusing a key for a different request returns 409.
Checks run in the background. Poll the check status endpoint, then read the results from the observations endpoint.
curl -s -X POST https://adslighthouse.com/api/v1/projects/nike.example/checks \
-H "Authorization: Bearer $ADS_LIGHTHOUSE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"device": "mobile"}'How to read the results
An observation is one saved check: one search result page for a keyword, engine, device and location at one moment. It shows that an ad appeared. It does not prove a purchased keyword, spend or an infringement.
visibility is the share of saved observations in the selection where a domain showed at least one ad. It is not impression share. ads_observed counts ad occurrences, not unique advertisers. When a report is based on few observations, the note field says so.
get_analytics returns chart-ready aggregates for the selected project, window and filters. Its active_keywords count covers the whole project and ignores the window and observation filters. Imported studies do not record engine or country, so they are left out when you filter by either. Shopping data is null when the plan does not include Shopping.
Observations and related history rows are kept for three UTC calendar months. An empty older window does not prove an advertiser or ad was absent: the records may have expired.
Errors
Errors use one envelope with a stable code, a message and, for invalid input, field details. Every response carries a request_id; include it if you contact us.
{
"error": {
"code": "invalid_request",
"message": "The request has invalid parameters.",
"details": [{ "field": "os", "message": "Operating system does not match device" }]
},
"request_id": "5f0c1c1e-8f7a-4c52-9a55-2f1c3e8b7d10"
}| Status | Codes | Meaning |
|---|---|---|
| 400 | invalid_request, idempotency_key_required | Invalid parameters, body or cursor. |
| 401 | unauthorized | Missing, invalid or revoked key. |
| 403 | insufficient_scope, plan_required, quota_exceeded | The key is read only, the plan does not include the API, or the allowance is used up. |
| 404 | not_found | No such project, keyword or check in this account. |
| 409 | idempotency_key_reused | The key was used for a different request. |
| 429 | rate_limited | Too many requests. Wait for Retry-After. |
| 503 | unavailable | A required file or service is temporarily unavailable. |
Rate limits
Each key or connected app may make 120 requests per minute. Responses include X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. A 429 response includes Retry-After in seconds. After repeated failed authentication, an address is blocked for a few minutes.
Questions
Can I use the API on the Starter or Growth plan?
The REST API and API keys are included in Scale, Business and Enterprise, including trials of those plans. Every plan, Starter and Growth included, can connect an AI assistant to the MCP server by signing in and export any report table to CSV or Excel.
Does the API run searches when I read data?
No. Read endpoints only return saved checks. Searches run on your monitoring schedule, or when you create a project or start an on-demand check.
Are landing page captures available?
Some ad reports include metadata for a saved landing-page preview. REST clients can fetch its private JPEG when one exists, and MCP returns the preview metadata and an app link. New previews are built from saved HTML and may load static styles, images and fonts when the preview is generated, so those assets can differ from the original capture. Scripts and nested documents stay disabled. The API does not return captured page text or full HTML.
See who's advertising on your brand today.
Start your 7-day free trial. Cancel anytime.