The AZi API
The same engine behind our free tools, as an endpoint. Audit any public page for technical SEO, AI citation readiness or its tech stack — 60 requests an hour, free.
No card · key working in about a minute · v1 will not change shape under you
curl "https://azi.solutions/api/v1/seo?url=example.com" \ -H "Authorization: Bearer azi_live_xxxx"
const r = await fetch(
"https://azi.solutions/api/v1/seo?url=example.com",
{ headers: { Authorization: "Bearer azi_live_xxxx" } }
);
const { data } = await r.json();
$ch = curl_init("https://azi.solutions/api/v1/seo?url=example.com");
curl_setopt($ch, CURLOPT_HTTPHEADER,
["Authorization: Bearer azi_live_xxxx"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
{ "score": 78, "grade": "B", "checks": [ { "status": "fail", "label": "XML sitemap", "fix": "Publish a sitemap" } ] }
Every failing check carries its own fix. A score alone tells you nothing you can act on.
Quickstart
Authentication
Send your key as a Bearer token in the Authorization header. That keeps it out of server logs and browser history.
Authorization: Bearer azi_live_xxxxxxxxxxxxxxxx
A ?api_key= query parameter also works, but it is discouraged for exactly the reason above — query strings end up in access logs, referrer headers and analytics.
Endpoints
/api/v1/seo
Twenty weighted technical checks — title, meta, headings, canonical, indexability, schema, images, content depth, links, sitemap, compression, response time and security headers. Returns a 0–100 score, an A–F grade, and every check with its own fix.
/api/v1/ai-search
Whether a page is built to be quoted by AI answer engines. The heaviest weights go to the two things that decide it: whether the content exists in the raw HTML at all, and whether AI crawlers are allowed in robots.txt.
/api/v1/tech
Platform, framework, analytics, CDN and hosting, detected from response headers and page signatures.
/api/v1/me
Your key’s tier, limits and current usage. Does not count against your quota.
Parameters
| Name | Required | Notes |
|---|---|---|
url | Required | On the three analysis endpoints. A public http or https address. Bare domains are accepted and https is assumed. |
/api/v1/me takes no parameters. | ||
Response shape
Every successful call returns the same envelope. Your result is under data; everything beside it is metadata.
{
"ok": true,
"tool": "seo",
"url": "https://example.com",
"cached": false,
"took_ms": 842,
"data": {
"score": 78,
"grade": ["B", "Good, with gaps", "pass"],
"counts": { "pass": 14, "warn": 4, "fail": 2, "info": 1 },
"checks": [
{
"status": "fail",
"label": "XML sitemap",
"detail": "No sitemap.xml and none declared in robots.txt.",
"weight": 2,
"fix": "Publish a sitemap and submit it in Search Console."
}
]
},
"usage": { "hour": 3, "day": 11, "hourLimit": 60, "dayLimit": 500 }
}
Rate limits
The free tier is 60 requests an hour and 500 a day. Every response carries your current position.
X-RateLimit-Limit: 60 X-RateLimit-Remaining: 57 X-RateLimit-Reset: 1840
Go over and you get a 429 carrying retry_after_seconds. Repeat calls for the same URL are served from cache for an hour — they still count against your quota, but they return in milliseconds.
Errors
Every failure returns the same shape with a stable, machine-readable code. Switch on the code, never on the message.
{ "ok": false, "error": { "code": "bad_url", "message": "That is not a valid public http or https address." } }
| Code | HTTP | Meaning |
|---|---|---|
no_key | 401 | No key sent |
bad_key | 401 | Key invalid, revoked or expired |
missing_url | 422 | No url parameter |
bad_url | 422 | Not a valid public address |
rate_limited | 429 | Hourly or daily limit reached |
fetch_failed | 502 | We could not reach that page |
upstream_error | 502 | That page returned a 4xx or 5xx |
What this API will not do
Version stability
The v1 path will not change shape under you. New fields may be added to data; existing fields will not be renamed or removed. Anything breaking ships as v2 with the old version left running.
