Developers

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

Request
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);
Response
{
  "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

1
Create a free accountSign up — email and a password, no card.
2
Generate a keyAt /account/api. It is shown once; we store only a hash, so it cannot be shown again. Lose it and you revoke it and make a new one.
3
Call an endpointSend the key as a Bearer token. That is the whole integration.

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

GET /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.

GET /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.

GET /api/v1/tech

Platform, framework, analytics, CDN and hosting, detected from response headers and page signatures.

GET /api/v1/me

Your key’s tier, limits and current usage. Does not count against your quota.

Parameters

NameRequiredNotes
urlRequired 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." } }
CodeHTTPMeaning
no_key401No key sent
bad_key401Key invalid, revoked or expired
missing_url422No url parameter
bad_url422Not a valid public address
rate_limited429Hourly or daily limit reached
fetch_failed502We could not reach that page
upstream_error502That page returned a 4xx or 5xx

What this API will not do

It will not fetch private addressesAnything resolving to a private or reserved IP range is refused, on every redirect hop. That is deliberate — an open fetcher is a server-side request forgery hole.
It does not run JavaScriptWe read the HTML your server actually returns, which is precisely the point: that is what a search crawler and an AI crawler see too.
It is not a rank trackerNo free, legitimate source of live ranking positions exists — anyone offering one is scraping search results against their terms. We measure the page, not the market.

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.

Get a key Free, no card, working in about a minute. Same engine as the 16 free tools.
Create an API key