Docs

AIMentionTracker API errors and rate limits

Ten error codes, each one saying something a client can act on, and one rate limit that is the same on every plan.

Card required, nothing charged for 7 days

The error envelope

An error replaces data with an error object. There is no partial success: you get the data or you get one of these.

Any non-2xx response
{
  "error": {
    "code": "brand_required",
    "message": "This organisation has 3 brands. Pass ?brand=<id>; GET /v1/brands lists them."
  }
}

Branch on code. Four separate conditions return 404 and two return 402, so the status alone does not tell you what went wrong. The message is written for a human reading a log and its wording may change; the code will not.

Every error code

Ten codes. The middle column is what happened; the rest is what to do about it.

Branch on error.code, never on the message. The wording may change; the code will not.
CodeStatusWhat it means, and what to do
unauthorized401No key, or a key that is malformed, revoked or expired. Create a key at /api-keys. Send it as X-API-Key or Authorization: Bearer.
no_subscription402This organisation has never had a plan. Choose a plan. A lapsed plan is not refused: if you have subscribed before, you keep read access to the answers you already own.
api_not_on_plan402This plan does not include API access. Every plan includes the API, so this should not occur in practice. If you see it, contact support.
insufficient_scope403The key was not granted the scope this endpoint needs. Mint a key with the required scope. Every current endpoint needs `read`.
brand_required400The organisation has several brands and the request did not say which. Pass ?brand=<id>. GET /brands lists them. Deliberately not defaulted: a silent default files one customer's numbers under another's.
no_such_brand404No brand with that id that this key may read. 404 rather than 403 on purpose — a 403 would confirm the brand exists in somebody else's organisation.
no_brand404This organisation has no brand at all, or the brand a pinned key is bound to has been deleted. Finish setup in the dashboard. For a pinned key whose brand is gone, mint a new key.
brand_not_configured404The brand exists but setup was never finished, so there is nothing to report. 404 rather than a page of zeroes, which would read as measured absence.
bad_cursor400The pagination cursor does not belong to this brand. Start again without a cursor. Not a silent restart from the top, which would produce undetectable duplicates.
rate_limited429Either the per-key quota of 300 requests a minute, or the per-address limit of 200 failed authentications an hour, which is applied before the key is checked. Retry-After says how long to wait. Back off using Retry-After. If you are seeing this with a key you believe is valid, it is the second cause: the key is being rejected.

AI visibility API rate limits

300 requests a minute, per key, on every plan. The cheapest plan gets the same ceiling as the most expensive one, because a rate limit that scales with price is a way of selling the same data twice.

The headers are on every response, not only the 429. A client should learn it is near the limit from a request that worked — finding out on the failure is finding out too late.

Response headers
X-RateLimit-Limit:     300
X-RateLimit-Remaining: 287
X-RateLimit-Reset:     41     # seconds until the window rolls

# and on a 429 only
Retry-After:           41

The window is fixed rather than sliding, so X-RateLimit-Reset counts down the seconds left in the current minute and the allowance returns in full when it hits zero.

The other 429

Failed authentications are throttled separately, by IP address, at 200 an hour, before the key is looked up at all. This exists because verification is the expensive part: without it, an unauthenticated caller could force an indexed database read per request, unbounded and metered by nothing.

Only failures are counted. Metering successful requests by address too would give one office behind a single NAT a second, lower ceiling that nothing in the product documents. If you are being refused with rate_limited and your key is new, check the key before you check your request rate.

Handling errors well

  • Read error.code, never the message. The message is prose for a log line. The code is the contract.
  • Retry only on 429 and 5xx, and only after Retry-After. Retrying a 401 in a loop trips the IP throttle and makes the problem harder to see.
  • Treat brand_required as a setup step, not an error to surface. Call /brands once, cache the id, and pass it from then on. See working with multiple brands.
  • Do not paper over brand_not_configured with zeroes. A page of zeroes is a claim that we looked and found nothing. Say the brand has not finished setup.
  • Pass meta.next_cursor back verbatim. Constructing one yourself earns bad_cursor, which is better than the alternative — silently restarting at page one and reporting the first fifty answers twice.

Checking your key

Most integration failures are one of three things: the wrong header, a revoked key, or a scope that was never granted. GET /me distinguishes all three in one request.

curl
curl -i -H "X-API-Key: $AMT_API_KEY" https://app.aimentiontracker.ai/api/v1/me

A 200 returns key.scopes alongside key.available_scopes, so a client can tell “this key was not granted that scope” from “that scope does not exist”. A 401 means the key itself is the problem; keys are stored as a SHA-256 hash, so we cannot tell you which one you sent, only that it is not one of ours.

What a client does with this

An alert email is what the API's data looks like once a client has read it correctly: both counts present, the gap stated, and no percentage quoted off a sample that cannot carry one.

A finding reporting that a competitor was named in 27 of 40 answers while our own brand was named in 0 of 40 — a 68 percentage point gap, pooled across engines and stated with both counts.
A real overtake, with both counts and the gap stated plainly. Our own workspace — Posteverywhere is our company, and these are its real numbers.

Questions about API errors

Answered from the implementation.

What is the rate limit on the AIMentionTracker API?
300 requests a minute per key, the same on every plan including the cheapest. Every response — not just the 429 — carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, so a client learns it is close to the limit from a successful request rather than from a failed one.
Why did I get a 429 before my key was even checked?
Because there are two separate limits. The per-key quota is the one above. There is also a throttle on failed authentications from one address, 200 an hour, which runs before the key is looked up — otherwise an unauthenticated caller could force a database read per request, unbounded. If you are seeing rate_limited with a key you believe is valid, it is this one, and the real problem is that the key is being rejected.
Should I branch on the status code or the error code?
The code. Four distinct conditions return 404 and two return 402, so status alone cannot tell you what to do. error.code is stable; error.message is human-readable and its wording may change.
Why does an unknown brand return the same error as a forbidden one?
So a key pinned to one brand cannot discover its siblings by probing ids. A distinct "exists but not yours" would confirm the id is real, which is exactly the thing an agency's client key must not be able to establish.
Why does an unconfigured brand return 404 rather than empty data?
Because a successful response full of zeroes reads as measured absence. It would say your brand was named in none of the answers, when the truth is that no answers have been collected. The error is the honest answer.
Does a lapsed subscription lose API access?
No. A lapsed plan still reads — you own the answers we collected for you, and cutting off your export the hour a trial expires is how a renewable customer becomes a churned one. An organisation that never subscribed at all gets 402 no_subscription.

7-day trial

Measure it before you automate it

The API reads what AIMentionTracker has already collected. Add your brand and the prompts your buyers type, and the first answers land within minutes.

Card required, nothing charged for 7 days.

On every plan

  • Every answer stored in full, with its citations.
  • Every rate shown with the number of checks behind it.
  • Cited-but-not-named reported as its own state.