---
title: "Create an audit run"
method: POST
path: "/v1/agent-runs"
tags: ["Audits"]
---

# Create an audit run

`POST /v1/agent-runs`

## Request

- Base URL: `https://api.squirrelscan.com`
- URL: `https://api.squirrelscan.com/v1/agent-runs`
- Auth: HTTP bearer

Start a new cloud audit run. With `trigger: "api"` the run is dispatched to the cloud crawler immediately and progresses asynchronously; poll `GET /v1/agent-runs/{id}` for status. Cloud features are credit-gated. If the requested page count exceeds the org's plan ceiling, the run still starts at the plan's max (clamp, never a hard error) and the response carries a `notice` field (`type: "page_limit_clamped"`) saying so.

## Request body

- CreateAuditRunRequest
  - `url` string, uri, required: Site URL to audit.
  - `trigger` 'api', required: Run origin. Public API callers must send `api`, which dispatches the cloud crawler. (`cli`/`github`/`scheduled` are internal-origin values that skip cloud dispatch and are not accepted here.)
  - `mode` 'audit' | 'audit-fix' | 'fix' | 'recommend'
  - `model` string
  - `config` string: Optional run config as a JSON-**encoded string** (not a nested object — the field is parsed server-side). Keys: coverageMode, maxPages, disabledRulePatterns, externalLinksEnabled. NOTE the round-trip asymmetry: you send a string here, but `AuditRun.config` is returned as a parsed object.
  - `websiteId` string
  - `auditId` string

## Response `201`

Run created (status `pending`).

- CreateAuditRunResponse
  - `id` string, required
  - `status` 'pending', required
  - `createdAt` string, date-time, required
  - `notice` PageLimitClampNotice: Present only when the run's requested page count exceeded the org's plan ceiling. The run is never rejected for this (clamp-and-notify, not a hard error) — it dispatches at `applied` pages instead of `requested`, and this field says so.
    - `type` 'page_limit_clamped', required
    - `requested` integer, required: Pages that were actually asked for (stored crawl config or an explicit request override).
    - `applied` integer, required: Pages the run actually dispatched with — equal to `planCap`.
    - `planId` 'free' | 'starter' | 'team', required
    - `planCap` integer, required: The org's plan's effective max-pages-per-audit ceiling at dispatch time.
    - `upgradeHint` string, required: Human-readable upgrade suggestion, always including a pricing URL.

## Other responses

- `400`: Request body or query failed validation. `error.issues` lists up to 10 failed fields (`{ path, message }`); when more failed, `error.truncated: true` and `error.totalIssues` indicate the full count.
- `401`: Missing or invalid credentials (including the shared auth middleware: no/invalid bearer token). Typed envelope with code `UNAUTHORIZED`. Branch on the `401` status, not the message.
- `429`: Too many requests. Retry after the window resets. (Rate limiting is planned — issue #69 — these headers document the intended contract.)
- `502`: Failed to dispatch the cloud audit (upstream crawler/sandbox unavailable). Typed envelope with code `UPSTREAM_ERROR`; the upstream cause is carried under `error.reason`.

---

[API](https://skmtc.dev/squirrelscan/apis/squirrelscan-public-api.md) · [All operations](https://skmtc.dev/squirrelscan/apis/squirrelscan-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/squirrelscan/apis/squirrelscan-public-api/revisions/82c8183fe8bc?raw)
