Topics
Getting Started
Audit Flows
Overview
UX, IA, A11y, ConversionVertaaUX gives you programmatic audits across usability, information architecture, accessibility, and conversion signals. The API is fully asynchronous: start an audit, receive a job_id, then poll or subscribe to a webhook for completion. All examples below use the public base URL https://vertaaux.ai/v1.
What you get
- Scores per dimension (usability, clarity, IA, a11y, performance).
- Issue list with severity, selector, and recommendations.
- Heatmap prediction and optional HTML snapshot (if enabled).
Typical flow
- Send
POST /auditwith your target URL. - Poll
GET /audit/{job_id}until completed. - Store scores/issues in your system or wait for webhook delivery.
Authentication
Authenticate every request with an API key using the X-API-Key header. Keep the key in server-side environments or CI secrets; do not expose it to browsers or client-side code.
Development Testing
For development and testing, create test users with different tier levels. See docs/TEST-USERS.md for test data setup.
Test API keys in a controlled environment before using in production. All audit data is persistent - use test organizations for development.
Get your API key
Create and manage your API keys in the Dashboard → API Keys section. You'll need to be signed in to access this page.
Header format
X-API-Key: your_api_key_here
Requests without a valid key return 401 Unauthorized.
SDKs & Clients
Official SDK scaffolds are available for JS/TS and Python. They include retries, idempotency helpers, webhook verification, and typed responses. Base URL defaults to production; override for staging/test mode.
Copy-paste starter (JS/TS)
import { createVertaauxClient } from "@vertaaux/sdk-js";
const client = createVertaauxClient({ apiKey: "your_api_key_here" });
const audit = await client.createAudit({ url: "https://example.com", mode: "basic" });
const status = await client.getAudit(audit.job_id);JS/TS
pnpm add ./sdk/jsimport { createVertaauxClient, generateIdempotencyKey } from "@vertaaux/sdk-js";
const client = createVertaauxClient({
apiKey: "your_api_key_here",
baseUrl: "https://vertaaux.ai/v1", // or staging host
idempotencyKey: generateIdempotencyKey(),
});
const audit = await client.createAudit({ url: "https://example.com", mode: "basic" });
const status = await client.getAudit(audit.job_id);See docs/SDK-QUICKSTART.md and sdk/js/README.md for publish steps.
Python
pip install -e ./sdk/pythonfrom vertaaux_api_client import AuthenticatedClient from vertaaux_api_client.api.audits import create_audit, get_audit from vertaaux_api_client.models import AuditRequest client = AuthenticatedClient( base_url="https://vertaaux.ai/v1", token="YOUR_API_KEY", ) resp = create_audit.sync(client=client, json_body=AuditRequest(url="https://example.com", mode="basic")) status = get_audit.sync(client=client, job_id=resp.job_id)
Generated from OpenAPI; update sdk/python/pyproject.toml before publishing.
Making Your First Request
- Set your API key in a secure env variable.
- POST to
/auditwith a fully qualified URL. - Save the returned
job_id. - Poll for status or subscribe via webhook.
curl -X POST https://vertaaux.ai/v1/audit \
-H "X-API-Key: $VERTAA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"mode": "standard"
}'const response = await fetch("https://vertaaux.ai/v1/audit", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "your_api_key_here",
},
body: JSON.stringify({ url: "https://example.com", mode: "standard" }),
});
const { job_id } = await response.json();import os, requests
api_key = os.environ["VERTAA_API_KEY"]
payload = {"url": "https://example.com", "mode": "standard"}
res = requests.post(
"https://vertaaux.ai/v1/audit",
headers={"X-API-Key": api_key, "Content-Type": "application/json"},
json=payload,
)
print(res.json()["job_id"])Poll until complete
curl -X GET https://vertaaux.ai/v1/audit/{job_id} \
-H "X-API-Key: $VERTAA_API_KEY"const res = await fetch(`https://vertaaux.ai/v1/audit/${jobId}`, {
headers: { "X-API-Key": "your_api_key_here" },
});
const audit = await res.json();
if (audit.status === "completed") {
console.log(audit.scores, audit.issues?.length);
}Audit Flows
Use the same endpoint for different targets. Choose mode to control depth: basic,standard, or deep.
Web (single-page)
- Pass the page URL in the body.
- Use
mode: basicfor faster screening ordeepfor thorough coverage. - Store the
job_idto retrieve scores and issues later.
curl -X POST https://vertaaux.ai/v1/audit \
-H "X-API-Key: $VERTAA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://shop.example.com/checkout",
"mode": "deep"
}'Multi-page runs
- Send one
POST /auditper URL and aggregate results on your side. - Throttle concurrency to respect rate limits and avoid 429 responses.
- Use webhooks to reduce polling load when running larger batches.
const urls = [
"https://example.com/",
"https://example.com/pricing",
"https://example.com/checkout",
];
const results = [];
for (const url of urls) {
const res = await fetch("https://vertaaux.ai/v1/audit", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "your_api_key_here",
},
body: JSON.stringify({ url, mode: "standard" }),
});
results.push(await res.json());
}
console.log(results.map((r) => r.job_id));Responses & Error Codes
The audit status endpoint returns the full payload once processing is complete. Common HTTP responses are listed below.
Sample completed audit
{
"job_id": "audit_01HF2YAJDQZ98X2M2YB1T5R9SJ",
"status": "completed",
"progress": 100,
"scores": {
"usability": 92,
"clarity": 88,
"ia": 86,
"accessibility": 90,
"performance": 82
},
"issues": [
{
"id": "iss_001",
"severity": "high",
"category": "accessibility",
"description": "Button lacks accessible label",
"recommendation": "Add aria-label or text content.",
"selector": "button.primary",
"wcag_reference": "2.5.3"
}
],
"heatmap_prediction": "https://cdn.example.com/heatmaps/audit_01HF2YA.png",
"version": "1.0.0"
}CI/CD gating: send fail_on_score or fail_on_drop with POST /audit. Responses include gating.failed and gating.reason when thresholds are crossed.
Success codes
202 Accepted— audit queued; returnsjob_id.200 OK— current audit status or completed result.204 No Content— webhook deleted.
Error codes
400 Bad Request— malformed body (e.g., missing URL).401 Unauthorized— missing or invalid API key.404 Not Found— unknownjob_id.429 Too Many Requests— rate limit exceeded.500— transient error; retry with backoff.
Error format
{
"error": "Validation error",
"message": "Quota exceeded",
"details": [...]
}On 429, use Retry-After and backoff; SDK retries handle this by default. Responses include X-API-Version and ruleset_version for traceability.
- Reduce concurrency or move to webhooks to avoid heavy polling.
- Check
GET /quotabefore large batches.
Pagination
Issue payloads support server-side filtering and pagination to avoid oversized responses. Use page and per_page on GET /audit/{job_id} to page through issues. Filters:severity=error|warning|info and fields=severity,selector,category to trim the payload. Responses include total and total_pages.
Streaming is available for large sets: GET /audit/{job_id}/issues/stream returns NDJSON so you can process issues incrementally.
Webhooks
Receive a POST callback when an audit finishes. Register a target URL and optional signing secret using POST /webhooks.
Delivery logs & replay
- List deliveries:
GET /api/webhooks/logs(filter bywebhook_id). - Replay a delivery:
POST /api/webhooks/logswithdelivery_id.
Signature verification
// Node/TS
import { verifyWebhookSignature } from "@vertaaux/sdk-js";
const isValid = await verifyWebhookSignature({
secret: "your_webhook_secret_here",
payload: rawBodyString,
signature: req.headers["x-vertaaux-signature"] as string,
timestamp: req.headers["x-vertaaux-signature-timestamp"] as string,
toleranceSeconds: 300,
});# Python
import hmac, hashlib, time
def verify(secret: str, payload: str, signature: str, timestamp: str, tolerance_seconds: int = 300) -> bool:
try:
ts_int = int(timestamp)
except (TypeError, ValueError):
return False
if abs(time.time() - ts_int / 1000) > tolerance_seconds:
return False
digest = hmac.new(secret.encode(), f"{timestamp}.{payload}".encode(), hashlib.sha256).hexdigest()
if len(digest) != len(signature):
return False
return hmac.compare_digest(digest, signature)Webhooks include X-Vertaaux-Signature and X-Vertaaux-Signature-Timestamp. Signatures are HMAC-SHA256 overtimestamp.payload (millisecond timestamp). Reject stale requests (>5 minutes).
curl -X POST https://vertaaux.ai/v1/webhooks \
-H "X-API-Key: $VERTAA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/vertaa",
"secret": "your-shared-secret"
}'import crypto from "crypto";
import { NextRequest, NextResponse } from "next/server";
const secret = "your_webhook_secret_here";
export async function POST(req: NextRequest) {
const rawBody = await req.text();
const signature = req.headers.get("x-vertaaux-signature") ?? "";
const timestamp = req.headers.get("x-vertaaux-signature-timestamp") ?? "";
if (!timestamp || Math.abs(Date.now() - Number(timestamp)) > 5 * 60 * 1000) {
return NextResponse.json({ ok: false, reason: "stale" }, { status: 400 });
}
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
if (signature !== expected) return NextResponse.json({ ok: false }, { status: 401 });
const payload = JSON.parse(rawBody);
// payload.job_id, payload.status, payload.completed_at, payload.scores
return NextResponse.json({ received: true });
}Webhook expectations
- Payload includes
job_id,status, timestamps, scores, and issues if completed. - Return any
2xxstatus to acknowledge delivery. - Use your shared secret to verify authenticity before processing.
- Delivery attempts: 6 retries over ~24h with exponential backoff; signature headers include
X-Vertaaux-SignatureandX-Vertaaux-Signature-Timestamp. Reject stale requests (>5 minutes).
Rate Limiting & Quotas
The API enforces per-account limits based on your subscription tier. Exceeding limits returns 429 Too Many Requests with rate limit headers.
Tier Limits
- Free: Limited audits for evaluation
- Pro: Higher limits with API access
- Agency: Organization features + scheduled audits (up to 20)
- Enterprise: Unlimited audits + scheduled audits (up to 100)
Best Practices
- Use
GET /api/v1/quotato check remaining quota before large batch operations. - Implement exponential backoff when receiving 429 responses.
- Use webhooks instead of polling to reduce API calls.
- For scheduled monitoring, use the Scheduled Audits feature instead of cron jobs.
Next.js Integration
Complete guide for integrating Vertaa in Next.js applications. Covers App Router, Pages Router, webhooks with signature verification, polling with exponential backoff, and caching patterns. Expected integration time: <30 minutes.
What's Included:
- App Router: Server Components, Route Handlers, Server Actions
- Pages Router: API routes, getServerSideProps patterns
- Webhook handler with HMAC-SHA256 signature verification
- Polling with exponential backoff (1s → 2s → 4s → 8s)
- Caching strategies: Next.js cache, Redis, in-memory LRU
- TypeScript types and best practices
SDK Examples
Use your preferred HTTP client; the API is language-agnostic. These snippets show minimal wrappers for common tasks.
import axios from "axios";
const client = axios.create({
baseURL: "https://vertaaux.ai/v1",
headers: { "X-API-Key": "your_api_key_here" },
});
export async function runAudit(url: string) {
const { data } = await client.post("/audit", { url, mode: "basic" });
return data.job_id;
}import requests, os
BASE_URL = "https://vertaaux.ai/v1"
HEADERS = {"X-API-Key": os.environ["VERTAA_API_KEY"]}
def get_quota():
res = requests.get(f"{BASE_URL}/quota", headers=HEADERS, timeout=10)
res.raise_for_status()
return res.json()
def delete_webhook(webhook_id: str):
res = requests.delete(f"{BASE_URL}/webhooks/{webhook_id}", headers=HEADERS)
return res.status_code == 204API Explorer
Interactive Swagger UI documentation for testing API endpoints directly from your browser. Explore schemas, try live requests, and generate code snippets.
Open API Explorer →Troubleshooting
Common issues
- 401 Unauthorized: confirm
X-API-Keyheader is present and correct. - 404 Not Found: verify the
job_idexists and belongs to your account. - 429 Too Many Requests: reduce concurrency and retry after the reset time.
- Timeouts: use
mode: basicfor faster responses or increase your client timeout.
Support checklist
- Include
job_idand timestamp when contacting support. - Share the HTTP status code and response body you received.
- Redact secrets before sending logs or examples.
Scheduled Audits
Enterprise and Agency tiers can configure recurring audits with cron expressions. Receive email and webhook notifications when scores drop or audits fail.
Features
- Automated recurring audits (5-minute to monthly intervals)
- Email and webhook alerts for failures and score drops
- Score threshold monitoring with delta tracking
- Complete run history with trend analysis
- Dashboard management for all schedules
API Endpoints
POST /api/v1/schedules- Create scheduleGET /api/v1/schedules- List schedulesPATCH /api/v1/schedules/{id}- Update scheduleDELETE /api/v1/schedules/{id}- Delete schedule
See docs/SCHEDULED-AUDITS.md for deployment guide.
Organizations & SSO
Agency and Enterprise tiers support multi-tenant organizations with SSO auto-join capabilities for domain-based onboarding.
Features
- Domain-based SSO auto-join (Google, GitHub, Azure AD)
- Role-based access control (Owner, Admin, Editor, Viewer)
- White-label branding for PDFs and reports
- Organization-scoped audits and API keys
- Complete activity logging for compliance
Organization-Scoped Audits
Include organization_id in audit requests to apply organization branding and associate results with your team.
{
"url": "https://example.com",
"mode": "standard",
"organization_id": "org_xxxxx"
}Error Codes Reference
Comprehensive catalog of all API error codes with causes, resolutions, and examples.
View Error Codes →Versioning & Deprecation Policy
Learn about our API version lifecycle, breaking change notifications, and 12-month deprecation process.
View Versioning Policy →Service Level Agreement
Uptime and response-time targets available via Enterprise agreement, plus incident-response commitments and credits (by contract).
View Enterprise SLA →