Website Audit API: A Developer Guide to Scans and Webhooks

A developer's guide to using a site audit API: queue scans, poll or use webhooks, verify HMAC signatures, handle rate limits and run crawls and batches safely.

By the MakeItFlow team Updated 9 min read
Share LinkedIn X Facebook WhatsApp
Website Audit API: A Developer Guide to Scans and Webhooks

A website audit API lets your own code start an audit of any public URL and read the results as structured data, so you can build site checks into deploy pipelines, client dashboards or onboarding flows. A typical site audit API works asynchronously: you queue a scan, receive an ID, then poll for the result or receive a webhook when it finishes.

This guide walks through that pattern using the Make It Flow website audit API as the worked example, with the exact endpoints, request shapes and limits from our API documentation. The same principles apply to most audit APIs: authenticate, queue, wait, verify, store.

Key takeaways

  • A website audit API lets your code queue an audit, then collect the scores and issues as JSON instead of reading a dashboard.
  • Audits are asynchronous: expect a 202 Accepted with a queued status, then poll the scan or wait for a webhook.
  • Verify every webhook with its HMAC signature and timestamp, compare in constant time and deduplicate on the delivery ID.
  • Plan for rate limits, daily allowances and failures from the start, and store results so you can compare runs over time.

When a site audit API is worth using

The dashboard is fine for checking a handful of sites by hand. An API starts to pay off when:

  • You deploy often and want an audit after each release to catch a dropped security header or a new noindex tag.
  • You manage many sites, for example as an agency, and want scores in your own spreadsheet, CRM or client portal.
  • You build a product that should show website health to your own customers.
  • You need a history in your own database rather than in someone else's dashboard.

If you only want speed metrics, Google's PageSpeed Insights API may be enough on its own. Our guide to automating website audits compares Lighthouse CI, the PageSpeed Insights API and broader audit APIs.

What the Make It Flow API covers

The API is versioned in the path (/api/v1) and covers three kinds of job:

Job Endpoints What it does
Scans POST /scans, GET /scans, GET /scans/{id}, DELETE /scans/{id} A full audit of one URL: performance, SEO, security, DNS and email, with an overall score and grade
Crawls POST /crawls, GET /crawls, GET /crawls/{id}, GET /crawls/{id}/map, DELETE /crawls/{id} A whole-site crawl. ?include=pages lists every URL found, and /map returns the internal link graph as nodes and edges
Batches POST /batches, GET /batches, GET /batches/{id}, DELETE /batches/{id} Up to 100 audits in one request, grouped under a label with one progress figure

GET /me returns your plan, entitlements and remaining allowance. The documentation lists API access and crawls on Pro and above and batches on Agency, so check /me before you build a feature that depends on one of them.

Step 1: Authenticate with a bearer token

Create a token in your account under API tokens and send it in the Authorization header. The plaintext token is shown once, at creation, and only a hash is stored, so put it straight into your secrets manager.

curl https://makeitflow.si/api/v1/me \
  -H "Authorization: Bearer ibmb_your_token_here" \
  -H "Accept: application/json"

A missing or unknown token returns 401. A valid token on a plan without API access returns 403. Never commit tokens to a repository or ship them in front-end JavaScript, where anyone can read them.

Step 2: Queue a scan

curl -X POST https://makeitflow.si/api/v1/scans \
  -H "Authorization: Bearer ibmb_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{"url": "example.com", "strategy": "mobile"}'

The body takes:

  • url (required): any public web address.
  • strategy (optional): mobile or desktop. The default is mobile.
  • force (optional): true to insist on a fresh audit.

The response comes back immediately with 202 Accepted and "status": "queued". MDN describes 202 as meaning a request "has been accepted for processing, but processing has not been completed", which is exactly the situation: the audit runs in the background, and the documentation says a scan usually takes 20 to 40 seconds.

Two behaviors are worth designing around:

  1. Recent-scan reuse. If you submit the same target again inside the cooldown window, you get 200 with the existing report instead of a new run. Pass "force": true when you genuinely need a fresh audit, for example right after a deploy.
  2. Private targets are refused. Only public addresses can be audited. A hostname that resolves to a private, loopback or reserved address is rejected at submission when that is obvious, or comes back as a failed scan with the reason in failure_reason.

Step 3: Get the result by polling or webhook

Polling

The response includes links.self. Request it until status is completed or failed:

curl "https://makeitflow.si/api/v1/scans/{id}?include=checks" \
  -H "Authorization: Bearer ibmb_your_token_here"

Without include=checks you get the scores (overall, grade, performance, SEO, security, DNS and email), a summary count of critical, improve and passed checks, and links to the HTML report and PDF. With it, you also get the full per-check breakdown. Poll gently, every few seconds with a cap on attempts, rather than in a tight loop.

Webhooks

Polling works, but webhooks are cleaner. Register a callback URL under Account, then Webhooks, and the API will POST to it when an audit finishes. The events are scan.completed, scan.failed and batch.completed. Each request carries these headers:

X-IBMB-Event: scan.completed
X-IBMB-Delivery: 9f2c1e7a-...
X-IBMB-Timestamp: 1785000000
X-IBMB-Signature: sha256=4f8c...

The body contains the event name, a timestamp and the scan in the same shape as GET /scans/{id}?include=checks.

Step 4: Verify webhook signatures

Anyone who knows your webhook URL can send it a request, so verify every delivery before acting on it. The signature is an HMAC-SHA256 computed over "{timestamp}.{raw body}" with your endpoint's signing secret. In PHP:

$timestamp = $request->header('X-IBMB-Timestamp');
$expected  = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $request->getContent(), $secret);

abort_unless(hash_equals($expected, $request->header('X-IBMB-Signature')), 401);
abort_if(abs(time() - (int) $timestamp) > 300, 401);

Three details matter:

  • Use the raw body. Parsing and re-encoding JSON can change whitespace or key order and break the signature.
  • Compare in constant time. PHP's manual describes hash_equals as a "timing attack safe string comparison", unlike ===, whose run time can leak information about the secret. Most languages have an equivalent.
  • Reject old timestamps. The timestamp is inside the signed material so a captured request cannot be replayed later. Rejecting anything older than a few minutes closes that gap.

Step 5: Handle retries and duplicates

Return any 2xx status quickly to acknowledge a delivery, then do slow work in a background job. If your endpoint returns anything else, the delivery is retried four times with backoff (10 seconds, 1 minute, 5 minutes and 15 minutes). After 10 consecutive failures the endpoint is disabled automatically, and the reason appears in your dashboard so you can fix it and re-enable it. The last 50 deliveries per endpoint are logged with status and error.

Because of retries, the same event can arrive more than once. Store the X-IBMB-Delivery ID and skip any you have already processed, so your handler is idempotent. Redirects are never followed, so register the final URL of your handler.

Step 6: Respect rate limits and allowances

Limit Value
Overall requests 120 per minute
Scan and batch creation 20 per minute
Counted per Account, not IP address
Daily scan allowance Set by your plan, visible at /me

When you hit a limit you get 429. Back off and retry later rather than hammering the API. Other errors to handle: 404 for a scan that is not on your account and 422 for validation failures, with details in errors.

Batches and crawls

For portfolios, POST /batches takes a label and up to 100 urls. Each URL becomes an ordinary report with its own link and PDF. Entries that are not recognized are returned in skipped rather than silently dropped, and anything beyond your per-batch limit is returned in truncated, so always check both arrays.

POST /crawls crawls a whole site and returns 202 with the crawl ID. You can pass max_pages up to your plan's limit. Read the crawl with ?include=pages for every URL found, or request /map for the internal link graph, which is useful for spotting orphan pages and checking your internal linking.

A simple deploy-check workflow

  1. Your CI pipeline finishes a production deploy.
  2. It calls POST /scans with "force": true for the home page and one key template.
  3. Your webhook handler receives scan.completed, verifies the signature and stores the scores.
  4. If the overall score dropped by more than your threshold, or a critical check now fails, it posts a message to your team chat with the report link.
  5. A person reviews the report and decides whether to roll back or fix forward.

Keep a person in that last step. An automated score change is a prompt to look, not a verdict. For one-off checks while debugging, our free HTTP status code checker and security headers checker are quicker than a full scan.

Frequently asked questions

What is a site audit API?

A site audit API is an interface that lets software request a website audit and receive the results as structured data, usually JSON, instead of viewing them in a dashboard. It is used to automate checks after deploys, feed client dashboards and track site health over time.

How long does a website audit API scan take?

It depends on the provider and the site. Our documentation says a scan usually takes 20 to 40 seconds. Because audits run asynchronously, design your code to poll or to wait for a webhook rather than holding a request open.

Should I poll or use webhooks?

Use webhooks when you can receive inbound HTTPS requests, because you get the result as soon as it is ready without repeated calls. Polling is simpler for scripts and local testing. Many integrations use webhooks in production and polling as a fallback.

How do I verify a webhook from an audit API?

Recompute the HMAC of the timestamp and raw body with your signing secret, compare it to the signature header in constant time, and reject requests with old timestamps. Then deduplicate on the delivery ID so retries are harmless.

Can I audit a staging site or intranet through the API?

Not with ours. Only public web addresses can be audited, and hosts that resolve to private, loopback or reserved addresses are refused. Run internal checks with tools inside your own network instead.

Sources

#website audit api #site audit api #rest api #webhooks #automation

More guides for your industry

Free checklist (PDF)

Free software & saas website checklist

31 practical checks for software & saas: website speed and mobile, Google Business Profile and reviews, email security, booking and enquiry handling, and AI search visibility. Each one says why it matters, and many link to a free tool that checks it.

We email you the PDF and nothing else unless you tick the box. See the privacy policy.

Written by the MakeItFlow team

We build the website audit these guides are based on. Every fact is checked against the primary sources listed above and this guide was last reviewed on 12 November 2026 . How we research and check

Share LinkedIn X Facebook WhatsApp

Check your own site in 30 seconds

Run a free audit covering speed, SEO, DNS, email authentication and security headers — and get a prioritised fix list.

Weekly newsletter

One practical website fix, every week

New guides on speed, SEO, email deliverability and security — straight to your inbox. No spam, unsubscribe in one click.

Keep reading