Quickstart
Create a site in the Ironfang portal, or create it directly through the API. The returned site ID is used when adding rules and starting audits.
curl -X POST https://api.ironfang.uk/auditwolf/v1/sites \
-H "Authorization: Bearer $IRONFANG_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Finance",
"url": "https://www.example.com"
}'The whole API is also a public Postman collection generated from the OpenAPI contract. Its Getting started folder creates a site, triggers an audit and polls it; the first request needs no key.
API keys
Automation can use a platform API key instead of a user token: mint one in the portal with the Ironfang Audit scopes it needs and send it as the bearer. A key acts only in the organisation it was minted for, and each scope stands for one permission - auditwolf:read, auditwolf:run, auditwolf:manage, auditwolf:evidence, auditwolf:integrations, or auditwolf:* for all of them. A key without an Ironfang Audit scope is refused with 403 insufficient_scope.
Deterministic rules
Rules retain their exact version in every result. Supported foundations include text contains or does not contain, regular expressions, element presence and text, links, metadata, HTTP status, HTTPS and response headers.
{
"name": "Company number is present",
"rule_type": "text_contains",
"severity": "failure",
"configuration": { "value": "12764014" }
}A crawler failure is operational evidence state, not a failed compliance rule.
Audit lifecycle
Audits are asynchronous. Use the returned permanent audit ID to poll the resource or consume HMAC-signed lifecycle webhooks. S3 exports and webhook delivery retry independently from evidence completion.
Evidence chain
Each page manifest contains the hashes of its raw screenshot, HTML, visible text, headers and network metadata. Page hashes become domain-separated Merkle leaves. Ironfang Audit signs the canonical audit manifest with Ed25519 and submits the audit root hash, not website content, to an RFC 3161 timestamp authority.
Raw captures remain immutable. Screenshot tiles and reports are presentation derivatives with provenance.
POST /verify/v1/bundles
Upload an evidence ZIP with Content-Type: application/zip, or verify it fully offline with the command-line verifier.
auditwolf-verify -bundle evidence.zip \
-trusted-public-key auditwolf-ed25519.pub \
-tsa-ca tsa-chain.pemThe verifier recalculates artifact hashes, validates every page's Merkle membership and checks the Ironfang Audit signature against an independently trusted signing key. With a configured trusted TSA CA it also validates the RFC 3161 response. The key embedded in a ZIP is never accepted as its own trust anchor.
Linux, macOS and Windows builds are published under Apache 2.0. Each release includes checksums and signed Sigstore build provenance.
GET /v1/sites
List every Ironfang Audit site available to the current organisation.
POST /v1/sites
Register a public website and its crawl boundary. The response contains the permanent site ID used by rules and audits.
| Field | Type | Notes |
|---|---|---|
url | string | Required public HTTP or HTTPS URL. |
name | string | Display name. Defaults to the website hostname. |
timezone | string | IANA timezone used by the controlled browser. Defaults to UTC. |
crawl_policy | object | Optional allowed hosts, page limits and crawl controls. |
GET /v1/sites/{siteId}
Return one site and its current crawl policy.
GET /v1/sites/{siteId}/rules
List the versioned deterministic rules configured for a site.
POST /v1/sites/{siteId}/rules
Create the first immutable version of a deterministic rule.
| Field | Type | Notes |
|---|---|---|
name | string | Required human-readable rule name. |
description | string | Optional explanation of the requirement. |
rule_type | string | Required deterministic evaluator type. |
severity | string | Result severity. Defaults to failure. |
configuration | object | Required configuration consumed by the selected evaluator. |
GET /v1/audits
List audits for the current organisation. Supply site_id as a query parameter to restrict the response to one site.
POST /v1/sites/{siteId}/audits
Queue an asynchronous audit. Supply an Idempotency-Key header when a client may retry the request.
| Field | Type | Notes |
|---|---|---|
trigger_type | string | Origin of the audit. Defaults to manual. |
reason | string | Optional human-readable reason for the audit. |
GET /v1/audits/{auditId}
Poll the audit status, compliance state, page counts and evidence root hash.
GET /v1/audits/{auditId}/pages
List captured page observations, rule outcomes and change classifications.
GET /v1/audits/{auditId}/evidence
Download the independently verifiable evidence ZIP after the audit reaches completed or partial. The response is application/zip.
GET /v1/artifacts/{artifactId}
Stream one tenant-scoped evidence artifact using its recorded media type.
GET /verify/v1/signing-keys
Return the public signing-key ledger used by the hosted verifier.
GET /v1/sites/{siteId}/monitors
List the monitors on a site: what is watched, how often, and when the next run is due.
POST /v1/sites/{siteId}/monitors
Create a monitor. mode is full_site (crawl) or url_set (the pages in urls); cadence is manual, daily, six_hourly or hourly, limited by the plan; anchor_minute and timezone fix the daily slot. Every scheduled run is a full audit with the same evidence chain as a manual one.
| change_policy field | Type | Notes |
|---|---|---|
ignored_selectors | string[] | Regions removed from the comparison text (cookie banners, counters). Same selector subset as rules. |
min_text_change | number | 0-1 share of lines that must differ before the page counts as changed. |
min_visual_change | number | 0-1 share of sampled pixels. |
ignore_numbers | boolean | Mask numbers and dates that tick over on every visit. |
notify_only_on_rule_change | boolean | Only a rule outcome moving counts as material. |
The policy shapes the comparison and the notification, never the record: the raw screenshot, HTML and visible text are stored untouched and the normalised text is kept alongside as a derivative.
POST /v1/monitors/{monitorId}/run
Run now. /pause, /resume and /archive change the status; PUT /urls replaces the page set; GET /runs lists the audits the monitor produced.
GET /v1/page-observations/{observationId}/comparison
What changed against the capture before it, computed from stored evidence under the audit's change policy: normalised text hunks with line numbers, text and visual scores, URL, title and HTTP status changes, rule outcomes that moved, screenshot artifact ids for both sides and whether the change was material. A first capture has no previous side and says why.
GET /v1/pages/{pageId}/observations
A page's history across audits, newest first. limit up to 200; pass the returned next_cursor to continue.
GET /v1/audits/{auditId}/pages?change=changed&compliance=fail
The page list takes change (new, changed, moved, unchanged), compliance (pass, fail, error), capture (captured, failed) and q (URL or title substring); each is a comma list. total is the unfiltered count.
GET /v1/events
The organisation's recent events - audit.started, audit.completed, audit.partial, audit.failed, change.detected, compliance.failed, monitor.skipped, quota.threshold_reached - with the payload each webhook received. Webhook envelopes carry schema_version and the event id as the idempotency key; an endpoint is disabled after 20 consecutive failures and re-enabled with PATCH /v1/webhooks/{endpointId} (enabled, events). DELETE retires an endpoint and keeps its history; POST .../deliveries/{deliveryId}/retry queues one delivery again.
GET /v1/notification-preferences
Which events are emailed, to whom, and whether at once or as one daily digest (07:00 UTC). PUT with events, recipients and digest; recipients must be current members of the organisation, and an API key may keep the list but not change it. Emails carry counts and a portal link, never captured content. GET /v1/notifications is the send log.
GET /v1/webhooks
List webhook endpoints registered for the current organisation.
POST /v1/webhooks
Register a public HTTPS endpoint. The HMAC signing secret is returned once in the creation response.
| Field | Type | Notes |
|---|---|---|
url | string | Required public HTTPS destination. |
events | string[] | Defaults to audit.completed. |
GET /v1/export-destinations
List configured S3 and S3-compatible evidence destinations.
POST /v1/export-destinations
Create an encrypted S3 destination. Required fields are region, bucket, access_key and secret_key. Optional fields include endpoint, prefix, path_style, session_token and export_mode.
POST /v1/audits/{auditId}/exports
Queue a completed audit for export using the supplied destination_id.
GET /v1/usage
Return the organisation's total captured pages, audits and consumed page-capture credits, plus the plan it is held to (the same catalogue as /v1/plans) so a client can tell which cadences and how many sites are allowed before asking.
GET /v1/plans
Return the plan catalogue: price in pence, monthly credits, site limit, minimum cadence, hosted retention in days and whether checkout is open. No authentication; it is the same data the pricing page is checked against.
