API reference.
Read your workspaces, the latest visibility run, and the open fix list straight into your own reporting. Included with the Agency plan.
Authentication
Every request carries a Bearer token. Create a key in console settings. The full key is shown once, at creation. After that we store only a hash and the first few characters, so we cannot recover it for you, and neither can anyone who reads our database.
Authorization: Bearer gts_live_xxxxxxxxxxxxxxxx
Base URL
https://greaterthanservices.com/api/v1
List your workspaces
/brandsEvery brand on the account, so a client can discover ids without being handed them. Returns the same shape the console reads.
curl https://greaterthanservices.com/api/v1/brands \
-H "Authorization: Bearer gts_live_xxxxxxxxxxxxxxxx"Response
{
"brands": [
{
"id": "b3f1…",
"name": "Sightline CRM",
"domain": "sightlinecrm.example",
"country": "us",
"countryName": "United States",
"trackedQuestions": 15,
"competitors": 5,
"createdAt": "2026-05-02T09:14:22.109Z"
}
]
}Latest visibility run
/brands/{id}/visibilityThe most recent recorded run: the score, the per-engine split, and the result for every tracked question. This reads stored data only. It never starts a run, so polling it costs you nothing and cannot burn through your weekly question allowance.
previousScore is null unless both runs separate branded questions out of the score, which is the same rule the console and the PDF apply. Two runs scored under different rules are not comparable, so we return nothing rather than a difference that means nothing.
{
"brand": { "id": "b3f1…", "name": "Sightline CRM", "domain": "sightlinecrm.example",
"country": "us", "countryName": "United States" },
"run": {
"at": "2026-08-09T04:02:11.884Z",
"score": 61,
"previousScore": 54,
"brandRecall": 0.47,
"citationShare": 0.22,
"engines": [
{ "engine": "chatgpt", "score": 68, "answered": 13, "asked": 15 }
],
"questions": [
{ "question": "best crm for field sales teams",
"mentioned": true, "cited": false,
"engines": [ { "engine": "chatgpt", "mentioned": true, "answered": true } ] }
],
"competitors": [ { "name": "…", "score": 74 } ],
"citedSites": [ { "domain": "…", "score": 31 } ]
}
}Returns 404 when the workspace has no run yet, which is the normal state for the first few days after you add a brand.
Open fix list
/brands/{id}/recommendationsWhat we think is worth changing for that brand, with the code where there is code to give. Pulling findings without what to do about them would make the endpoint a novelty, so fixCode comes back in the same payload.
| Query | Accepts | Default |
|---|---|---|
| status | open, applied, dismissed | open |
Anything else falls back to open rather than erroring. The value is whitelisted, not passed through: an arbitrary status would be a caller-chosen filter on a column.
{
"status": "open",
"recommendations": [
{
"id": "r91c…",
"title": "Answer \"does it integrate with HubSpot\" on the integrations page",
"body": "Three engines were asked…",
"fixCode": "<script type=\"application/ld+json\">…</script>",
"source": "gap",
"createdAt": "2026-08-09T04:03:02.551Z",
"appliedAt": null
}
]
}Error codes
| Status | Meaning |
|---|---|
| 401 | No Authorization header, or the key is not valid. |
| 403 | The key is valid but the account is not on Agency. |
| 404 | No workspace with that id on this account, or no run recorded yet. |
| 429 | The key has used its 1,000 calls for today. Read Retry-After. |
| 503 | We could not reach storage. Safe to retry. |
Every error carries WWW-Authenticate and a plain-English error string, so a machine client does not have to read this page to know what went wrong.
Rate limits
- 1,000 requests per day, per key. Create more than one key if you want to meter separate integrations apart.
- The counter resets at 00:00 UTC, on the database clock rather than yours.
- A 429 carries
Retry-Afterin seconds, measured to that same reset. - Reads never trigger an engine run, so no call here spends your weekly question allowance.
Managing keys
Keys are created, listed, and revoked from console settings. Listing shows the prefix and the last-used date, never the key itself. Revoking takes effect on the next request.
A key belonging to an account that drops off Agency stops working at once and answers 403. It starts working again if the account returns to Agency; you do not need to reissue it.
Legacy audit endpoint
/auditThe one-off audit that predates the workspace console still answers, so integrations built against it keep running. It uses the older per-audit quota rather than the daily request limit above, and it is not receiving new work. Build against the brand endpoints instead. If you depend on /audit, tell us before you plan around it.
Ready to integrate?
The API is included with Agency, alongside white-labelled reports and ten brand workspaces.
View pricing