Getting your AI visibility data into your own tools
Two ways in: a key that lets anything pull your data on its own schedule, and webhooks that push the moment something changes. Both are on Scale and Enterprise, and neither needs a developer.
Everything the Tracker measures is yours to take. This page covers both routes and gives working recipes for the tools people actually ask about.
Which one do you want?
Pull, with an API key, when something else owns the schedule: a BI dashboard that refreshes every morning, a warehouse job, a spreadsheet somebody opens on a Monday.
Push, with a webhook, when the point is to react: a Slack channel, an alert, a ticket. Nothing to poll and no delay.
Have it emailed, when nobody wants to build anything. Switch it on and a link to the file arrives after every scan.
All three are on Scale and Enterprise. Create a key or a webhook in Settings → Integrations; switch on the email in Settings → Data sharing.
Pulling your data
One request returns every observation behind every number on your dashboard, one row per question, engine and scan.
GET https://api.searchscore.io/api/tracker/export?format=csv
X-API-Key: <your key>
The key already knows which account it belongs to, so there is no domain to pass. It cannot return anybody else’s data, and there is no parameter you can get wrong.
Useful parameters:
| Parameter | Does |
|---|---|
format=csv or format=json |
CSV for spreadsheets and BI, JSON for code |
table=competitors |
One row per rival per scan instead, with each engine’s rate and, where the scan classified it, how the answers characterise that rival |
scans=20 |
How many scans back to include |
offset=20 |
Skip that many, to page through history |
answers=1 |
Include the full answer text each engine gave |
Every row carries the measurement epoch and, where it was recorded, the retrieval mode, so you can recompute any figure we publish rather than taking it on trust.
Looker Studio, Google Sheets and Excel
These fetch a URL and cannot set a custom header, so pass the key as a parameter instead:
https://api.searchscore.io/api/tracker/export?format=csv&api_key=<your key>
In Google Sheets: =IMPORTDATA("..."). In Excel: Data → From Web. In Looker Studio: add a CSV-by-URL source pointing at the same address.
If you open the file in Excel by double-clicking it, add &bom=1. Excel reads a saved file rather than the response that delivered it, so it cannot see the encoding we declare and needs a byte-order mark to read accented characters correctly. It is off by default because every other reader shows that mark stuck to your first column name, which breaks anything matching on headers.
One caveat we would rather state than have you discover. A key in a URL is visible to anything that logs URLs: browser history, proxy logs, the sharing settings of the document holding it. That is the price of tools that cannot send headers. Use a separate key for each of these so you can revoke one without breaking the others, and keep the document private. Revoking is instant.
Zapier and Make
There is no SearchScore app in either directory yet. There does not need to be:
- Zapier: use Webhooks by Zapier → Custom Request → GET, with the URL above and the
X-API-Keyheader. Schedule it, then feed the result into any of the 6,000 apps Zapier already talks to. - Make: an HTTP → Make a request module, same URL and header.
If you want the other direction, with SearchScore starting the Zap rather than Zapier polling us, use a webhook instead, below. It is faster and costs no tasks.
Emailed after each scan
If you would rather not build anything at all, switch on Email me the export after each scan in Settings → Data sharing. After every scan you get a short email with a link to the CSV and a link to the same data as JSON.
It rides the scan rather than a calendar. The file always contains the scan the email is announcing, and a scan that does not run sends nothing rather than mailing last week’s numbers under this week’s date. Since every plan scans weekly, that is a weekly email.
The links carry a download token rather than your sign-in token. It opens that one export for that one domain, it expires after seven days, and it cannot be used to reach your dashboard, your settings or your billing. Still worth not forwarding the email, because the file is your data, but a leaked link is not a leaked account. Add &answers=1 to the CSV link if you want the full response text with it.
We send a link rather than an attachment on purpose. An attached CSV arrives with no encoding the mail client can trust, and every client we tested guessed wrong: the first column name came through as scan_id and accented characters as ü. Fetched over HTTPS the file is served with an explicit charset=utf-8, which the client cannot override.
Pushing events
Add an endpoint in Settings → Integrations and we POST to it when something happens:
| Event | Fires when |
|---|---|
scan.completed |
A scan finishes, with the headline numbers |
citation.lost |
An engine that used to cite you stops |
citation.gained |
An engine starts citing you |
rival.appeared |
A brand we had not seen before shows up in your answers |
watchlist.confirmed |
A watched question changed on an engine, and the change held for two days running |
rival.threshold |
A rival you are watching crossed a threshold you set, in either direction |
rival.threshold fires on the CROSSING, not on the state. A rival sitting above your line for
three months produces one alert when they pass it and one when they drop back, rather than one
every scan. There is a small hysteresis band, so a value hovering on the threshold does not
alternate. It carries the rival, the metric, your threshold, the measured value and a
direction of crossed or recovered.
watchlist.confirmed is deliberately separate from citation.lost and citation.gained. Those
report one scan differing from the one before it. A Watchlist change has been re-asked on
consecutive days and moved the same way both times, so it is a stronger claim, and folding the two
together would let you act on “confirmed” and “seen once” as though they were the same thing. It
carries the question, the engine and the direction, because on a question you chose to watch
those are the whole message. Watchlist is a paid add-on and is bundled with Enterprise.
Slack and Microsoft Teams
Paste your incoming-webhook URL into the same box. We detect it and send a readable message instead of raw JSON, with nothing else to configure:
SearchScore: 3 citations lost for acme.com
Verifying it was us
Every request carries X-SearchScore-Signature, an HMAC-SHA256 of the exact body under the secret shown once when you created the endpoint, and X-SearchScore-Event-Timestamp. To verify:
expected = HMAC_SHA256(secret, timestamp + "." + rawBody)
Compare it with the header value after sha256=. The timestamp is inside the signed material, so a captured request cannot be replayed later with a fresh one. Reject anything more than a few minutes old.
Verify before you act on a webhook. An endpoint that accepts unsigned POSTs is a URL anyone who learns it can write into.
When an endpoint stops working
We try once per event, with a short timeout, and record the outcome. There is no retry queue on purpose: a webhook that retries into an outage makes a bad afternoon worse, and one that blocks a scan would cost you a datapoint.
Settings shows the last status and the current failure run for every endpoint. After 10 consecutive failures we switch it off and say so, rather than posting into a void indefinitely. Fix it and re-enable.
Asking an AI assistant about your visibility
There is an MCP server in the repository at tools/mcp-server.js. Point Claude Desktop, or any
MCP client, at it and you can ask questions in plain language instead of reading a CSV: which
engine ignores us, who is ChatGPT recommending instead of us, did anything change this week.
{
"mcpServers": {
"searchscore": {
"command": "node",
"args": ["/path/to/mcp-server.js"],
"env": { "SEARCHSCORE_API_KEY": "ss_..." }
}
}
}
It runs on your machine, not ours. It needs no packages installed, only Node 18 or newer, and it uses the same key and the same read-only API described above. Nothing it can do changes anything: an assistant given this server can answer questions about your visibility and that is all.
What this is not
There is no write API. Nothing here changes your configuration, adds questions or triggers a scan. Everything is a read of data we have already collected, which is why a leaked key is a disclosure problem rather than a billing one, and still worth revoking immediately.
Part of Pillar Article - see all guides in this series →