API reference

Run scans and read results from your own code. Available on the Advanced plan.

Last updated 18 September 2026

Authentication

Create a key on the API page and send it as a bearer token:

Authorization: Bearer aw_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The key is shown once, at the moment it is created. We keep only a hash of it, so nobody — including us — can read it back to you. If you lose it, generate a new one and revoke the old one.

Only Bearer is accepted. Sending the bare key is refused, because every system that logs request headers would then be logging a credential.

Endpoints

MethodPathWhat it does
GET/api/v1/meYour plan, your limits, and how much of them you have used in the last 24 hours.
GET/api/v1/scansRecent scans, newest first. ?limit= accepts 1–100 and defaults to 20.
POST/api/v1/scansRun a scan and return it. Long request — the server allows up to 120 seconds.
GET/api/v1/scans/{id}One scan in full, including the text of every answer it is based on.

Check the key before you spend anything

curl https://mossagents.com/api/v1/me \
  -H "Authorization: Bearer $ANSWERWATCH_API_KEY"

Returns your plan, your limits and your usage, without running a scan:

{
  "account": { "id": "usr_…", "email": "you@example.com", "plan": "advanced", "planName": "Advanced" },
  "limits":  { "projects": 10, "promptsPerScan": 20, "engineScope": "all", "scansPerDay": 10 },
  "usage":   { "projects": 3, "scansLast24h": 1 }
}

This endpoint exists so that the usual first question — "is this key working, and what am I entitled to?" — is not answered by running a real scan and paying for it.

Run a scan

curl -X POST https://mossagents.com/api/v1/scans \
  -H "Authorization: Bearer $ANSWERWATCH_API_KEY" \
  -H 'content-type: application/json' \
  -d '{"domain":"acme.com"}'

The body accepts:

FieldTypeNotes
domainstringRequired. The site being measured.
brandNamestringOptional. How the brand is normally written, when that differs from the domain.
categorystringOptional. Narrows the generated questions to a market.
locale'en' | 'zh'Optional. The language the questions are asked in.
questionsstring[]Optional. Your own buying questions, asked before the generated ones. They are stored on the project, so a later scan without them keeps asking the same set instead of silently reverting to ours.
webSearchbooleanOptional. Ask the engines to search the live web, on the engines that can. This changes the bill: a browsing answer costs roughly twenty times one answered from memory, which is why it is something the caller opts into rather than something every scan does quietly.

Read the result

curl https://mossagents.com/api/v1/scans/scan_xxxxxxxxxxxx \
  -H "Authorization: Bearer $ANSWERWATCH_API_KEY"

The stored answer text is the point of this endpoint. Every number in a report is derived from those answers, so you can verify the score yourself rather than trusting it.

Errors

StatusMeaning
401No key, a malformed key, or a key that has been revoked.
403The key is fine, but the account is not on Advanced. Do not regenerate the key — change the plan.
402The account has reached its project limit for the plan.
429This project's daily scan allowance is used up. Resets on a 24-hour window.
404No such scan — or it belongs to a different account.
500The scan ran but could not be saved. See the note below.

401 and 403 are deliberately different. An integrator who receives 401 goes and replaces the credential; if a plan problem also returned 401, they would spend an afternoon fixing something that was never wrong.

A scan id belonging to somebody else returns 404, not 403. A 403 would confirm the id exists, which turns the endpoint into a tool for enumerating other customers' scans.

Limits

The API and the dashboard enforce the same numbers from the same table — not two rules that happen to agree today:

  • Scans per project per day, by plan (Advanced allows 10). Rolling 24-hour window.
  • Questions and engines per scan follow the plan, and the dashboard shows the same ones.

This is deliberate. If the API had its own allowance, the two paths together could exceed what the price covers.

Two things that look odd, and why

A scan is attached to a tracked project. The first time you scan a domain, a project is created for it; later calls reuse it. That costs you a project slot (Advanced allows 10), but it means an API-only customer still gets score history and competitor comparison instead of a one-off snapshot, daily monitoring covers those projects automatically, and both paths write the same rows — so the dashboard and the API cannot contradict each other. Scanning a domain you already track uses no extra project slot.

A failure to save returns 500, not 201. The scan itself is valid even when persistence fails, so it is not thrown away. But a caller that receives an id will come back to read it, and telling you "created" and then returning 404 on the next request is worse than failing now — failing now is at least something a client can see and retry.

A failed engine call is "not measured", never "not mentioned". If an engine does not answer, that is recorded as a gap in the measurement. Counting it as an absence would understate your visibility and blame the wrong thing.

Questions

Limits, behaviour under load, and anything the contract above does not cover — write to us before building around an assumption, and we will answer with the truth about what the code does rather than what we wish it did.