Start a technical audit
Scan this brand’s primary domain for technical / AI-crawlability issues — the same audit the
“Run audit” button triggers. Only one audit may run per brand at a time. Returns a job_id; poll
List technical issues once it completes to see the
results.
POST /brands/{brand_id}/technical/auditsAuthorization
| Header | Type | Required |
|---|---|---|
Authorization | Bearer asky_sk_… | required |
Idempotency-Key | string | required on every write. See Idempotency |
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
brand_id | uuid | required | From List brands |
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
include_link_analysis | boolean | optional | Also check internal-link health. Defaults to true, matching the “Run audit” dialog. |
Request
cURL
curl --request POST \
--url 'https://api.askylabs.com/v1/brands/242546de-4cee-4a7d-952e-f6aa60c63ef8/technical/audits' \
--header 'Authorization: Bearer <api-key>' \
--header 'Idempotency-Key: 9c2e5f1a-3b7d-4a6e-8c1f-2d5b7a9e6f30' \
--header 'Content-Type: application/json' \
--data '{}'Response
200
{
"data": {
"job_id": "3f8a1c2e-9b4d-4a6f-8c1e-2d5b7a9e6f30",
"domain": "example.com",
"total_urls": 214,
"credit_cost": 15,
"is_free_scan": false
},
"request_id": "req_7c9e1f3a4b2d46f08a1c"
}Response fields
| Field | Type | Description |
|---|---|---|
data.job_id | uuid | required. Pass to Get technical issue queries once the audit completes to see fresh results |
data.domain | string | required. The domain that was scanned — always the brand’s primary domain, never a choice |
data.total_urls | integer | required. Pages found across the domain’s own sitemap(s) at the common locations (/sitemap.xml etc). 0 if none were found |
data.credit_cost | integer | required. 0 when is_free_scan is true |
data.is_free_scan | boolean | required |
request_id | string | required. Also returned as the x-request-id header. Quote it when contacting support |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_request | The brand has no active domain |
| 401 | invalid_token | The key is missing, malformed, or does not exist |
| 401 | token_expired | The key passed its expiry date |
| 401 | token_revoked | The key was revoked |
| 403 | quota_exceeded | Insufficient credits for this audit’s estimated cost |
| 404 | not_found | The brand does not exist, or this key is not allowed to reach it |
| 409 | conflict | An audit is already running for this brand |
| 429 | rate_limited | Over 300 requests per minute. See the Retry-After header |
Notes
Sitemap discovery is scoped to the brand’s primary domain only. This checks the common
sitemap locations (/sitemap.xml, /sitemap_index.xml, /sitemap1.xml, /sitemap-index.xml)
against the domain on file — not robots.txt-referenced sitemaps, a custom sitemap URL, or the
www/apex alternate host. If your sitemap lives somewhere else, this will undercount total_urls
and the audit will still run, just against whatever it discovers plus link-following during the
crawl itself.
total_urls is a discovery estimate, not the final page count. The real page count — and the
real charge, unless this was a free first scan — is based on how many pages the crawl actually
visits, which can differ from what the sitemap claimed.
There is no page-count or crawl-speed override. Every audit through this endpoint uses the
platform’s own cap and normal crawl speed, the same defaults the “Run audit” dialog ships with —
there is no equivalent of result_count here.
A brand’s first audit is always free, regardless of total_urls. This matches the “Run
audit” dialog exactly: the first real audit for a brand never charges credits.