API Documentation
For agents and developers: every response is JSON; billing, idempotency and error codes are all in the response.
The endpoint reference on this page is rendered from the live /api/openapi.json —
when the spec changes, this page changes, so you never hit a silent "docs are stale" bug.
Get started in 5 minutes
- Get a key: currently invite-only — email service@saler.ai; once provisioned you get a tenant key of the form
saler_…. - Try it free, no key:
GET /api/v1/diagnose?domain=example.comneeds no key and validates network shape and response shape directly. - Quote before you order: every billable endpoint has a matching quote endpoint (
*_estimate); quoting is free and returns the price only. - Call for real: send
authorization: Bearer $SALER_API_KEY; also passidempotency_key(retries won't double-charge).
curl 'https://api.saler.ai/api/v1/diagnose?domain=example.com'
Auth & response envelope
- Tenant key goes in the HTTP header:
authorization: Bearer $SALER_API_KEY. - Success envelope:
{ "code": "OK", "data": <payload>, "meta": { "locale": "…" } }. - Failure is the same shape:
{ "code": …, "message": …, "retryable": …, "action": … }. - Public endpoints (
/api/v1/diagnose,/api/v1/openapi.json) need no key but are rate-limited.
Errors & the "404 double meaning"
404 has two meanings; the discriminator is the message prefix, not the status code:
path not found: … means the route is not registered (wrong URL or that version not deployed);
not found: … means the route exists but the object doesn't (e.g. brand not authorized/not registered).
Treating both as "wrong address" misdiagnoses — fix the address in the first case, check authorization in the second.
401 also has two contexts: a response asking for a tenant key means the route is registered; asking for ADMIN_TOKEN means the path belongs to the admin surface.
Pricing quick reference
Two ways to buy: pay-per-use (pay each time you call; the quote endpoint is free and prices before ordering) and monthly subscription (window queries for covered brands are $0).
| Capability | Tier | Price | Notes |
|---|---|---|---|
| Brand AI visibility (GEO) | 30 days | $10.80 | ≈ $0.36 / brand / day |
| 90 days | $32.20 | same methodology | |
| 365 days | $130.60 | daily price doesn't fall with window | |
| SEO research (by kind) | keywords | $4.00 | up to 200 terms, with AI search volume & difficulty |
| competitor_gap | $0.50 | up to 10 competitor domains | |
| domain_overview | $0.60 | up to 10 domains | |
| backlinks | $0.40 | overview + anchor + referring domains | |
| Technical audit (Lighthouse) | per run | $0.02 | auto full refund if not delivered in 2h |
| GEO diagnosis | — | Free | public endpoint, rate-limited |
The quote endpoint returns the price only (fixed price by kind / window).
Window queries inside subscription coverage are $0: once a brand is covered by the "brand monitoring subscription" below,
reading 30 / 90 / 365-day windows is no longer billed separately. Coverage and the reason are given by the self-serve endpoint
GET /api/v1/billing/subscriptions/me and by the subscription field in every billing response —
both use the same judgment, so you never get "the self-serve page says free but it still charged".
When not covered, or when authorized brands exceed the tier cap, the window price above always applies
(fail-closed: when in doubt, bill — never silently free).
Pay-per-use windows are only open to brands already in the sampling scope: brands under active daily sampling (already being collected) can be queried on demand; new brands outside the scope should use a subscription — the subscription fee covers their ongoing collection cost, and covered queries are $0. Positionally, the pay-per-use window is the price anchor and trial entry for the subscription: query once ad hoc with pay-per-use, monitor long-term with subscription for better value.
Brand monitoring subscription (monthly)Self-serve purchase open
Brand AI visibility monitoring as a monthly plan: window queries for authorized brands within the tier are no longer billed separately ($0). For teams watching multiple brands, and for SEO / GEO agencies reporting to clients monthly.
| Tier | Monthly | Brands covered | Notes |
|---|---|---|---|
| Starter | $29 | up to 3 | single brand / small team |
| Growth | $99 | up to 10 | most common tier |
| Scale | $199 | up to 20 | multi-brand / agency |
| Custom | Contact for quote | as needed | multi-brand / agency custom (contract) |
Click to jump to the Creem checkout; after payment you'll be redirected to claim your API key with the request_id (shown once). Subscription is collected and invoiced by a licensed Merchant of Record (MoR). "Brands covered" is based on the currently authorized brand count: above the tier cap, coverage is off entirely (fail-closed) — you must revoke excess authorizations or upgrade. We don't do "first N brands free" — that boundary is unpredictable for you and indefensible for us.
Self-serve brand registration (no need to wait for us after claiming your key)
After subscribing / topping up and claiming your API key, brand registration is fully self-serve: one call with your own key — no admin back-office step. A subscription covers multiple brands (Starter 3 / Growth 10 / Scale 20) and can be set up in one shot: either declare brands at checkout or register them in bulk after claiming your key.
- Easiest · brands at checkout: send
POST /api/billing/subscribe/publicwith{"tier":"growth","brands":[{"brand_id":"acme-foods"},{"brand_id":"acme-drinks"}]}(count ≤ the tier cap). After payment, claiming your key withrequest_idauto-authorizes these brands in the same moment — ready to query on purchase. If authorization ever fails it is reported honestly asbrand_warningsand never blocks your key. POST /api/v1/brands— authorize one or many brands: a single{"brand_id":"acme-foods"}, or a batch{"brands":[{"brand_id":"acme-foods"},{"brand_id":"acme-drinks"}]}(plain strings are also accepted). If the brand already exists in the catalog it is authorized directly, otherwise acorebrand is auto-created (entering daily sampling), no approval needed.GET /api/v1/brands— see your authorized brands in detail, plus your quota bar: each entry returns brand name / domain / category / sampling state andself_editable_missing(which fields you can still fill in yourself); the top-levelquotatells you exactly how many slots remain ({tier, brand_limit, used, remaining}) — no guessing.PATCH /api/v1/brands/{brandId}— fill in the domain / category (only when the field is currently empty). An existing value is rejected with409: the brand catalog is shared across tenants, so rewriting an existing value would silently change everyone else's reporting basis — those edits are handled by us. This split is deliberate, not an omission. Display name and internal fields (sampling tier, entity kind, aliases) cannot be changed by tenants.DELETE /api/v1/brands/{brandId}— revoke one of your brand authorizations (idempotent; a repeat returnsrevoked:falsehonestly).- Two disciplines apply (same as the back office): non-subscribed tenants can only authorize brands already in sampling; subscribed tenants cannot exceed the tier cap. A batch is validated as a whole before anything is written — over the cap, the entire batch is rejected and not a single row is written (never "4 of 10 done").
Example — add two brands in one call: curl -X POST https://api.saler.ai/api/v1/brands -H "Authorization: Bearer <your key>" -d '{"brands":[{"brand_id":"acme-foods"},{"brand_id":"acme-drinks"}]}'.
Once authorized they appear in GET /api/brand-visibility, and POST /api/brand-visibility/:brandId can then read their series.
Integration channels (REST / MCP / CLI)
One account, one billing. REST and MCP authenticate with the tenant API key (Authorization: Bearer); anonymous calls are not allowed (they'd cost money). The CLI is an in-repo ops / self-host entry that needs an admin token and is not distributed externally.
- REST API: every response is JSON; the machine-readable spec is rendered from the same source at /api/openapi.json; for server-side integration and scripts.
- MCP:
POST /mcp(JSON-RPC 2.0 over Streamable HTTP); 6 tools (see the live panel below); built for AI agents to call directly, with long tasks returning ajob_idto poll. Discovery endpoint/.well-known/mcp.json(no-key GET). - CLI (
bin/saler): the local command-line entry in the repo, sharing the account and billing with REST, for our own ops tasks (sampling delivery, upstream calibration, token rotation, brand authorization). It is not a customer tool, has no subscription command, and is not distributed — customers should use REST or MCP.
MCP tools (live)
Methodology disclosure (affects how you read the data)
- An empty sampling day is not 0: when a day has no samples, visibility is
null— never padded with 0 (0 would be read as "dropped"). - Methodology is versioned: the visibility score methodology is
vs2(denominator excludes queries with no AI overview). Reports across methodologies are not directly comparable. - Samples are disclosed, not delivered: rows with
is_samplecount, but are not delivered as conclusions. - Generable ≠ deliverable: if valid samples within the window are insufficient, the response gives covered and empty days, and the trend field is
N/Arather than a fabricated number.
Endpoint reference
Rendered live from the online OpenAPI spec; to feed a machine-readable spec straight to an agent, use /api/openapi.json.
This English page now renders the same live spec as the Chinese docs (single source). The authoritative, always-current endpoint list is /api/openapi.json.