The AQ API
Published August 1, 2026 · by the AQ team
AQ exposes its workspaces as a programmatic surface: a versioned REST API, signed webhooks, and an MCP server. Anything your team does from the dashboard (create a workspace, watch its events, grab the preview URL, track the PR) a script or an agent can do with an API key.
Authentication
Create an API key in Settings. Keys start with aq_, are shown once, and act as you inside your team: a key sees exactly the workspaces you can see, and it stops working the moment you leave the team. Scopes are set at creation (workspaces:read, workspaces:write, events:read, prs:read, previews:read, webhooks:manage).
curl https://aq.dev/v1/workspaces \
-H "Authorization: Bearer aq_your_key"
Idempotent writes
Every mutation requires an Idempotency-Key header. Retries with the same key replay the original response instead of re-executing, so a timed-out request can be retried safely:
curl -X POST https://aq.dev/v1/workspaces \
-H "Authorization: Bearer aq_your_key" \
-H "Idempotency-Key: create-fix-auth-bug-1" \
-H "Content-Type: application/json" \
-d '{"title": "Fix the auth bug", "repo_id": "your-repo-id"}'
Webhooks
Register an https endpoint and AQ notifies it when things happen: workspace.created, workspace.closed, workspace.pr_opened, workspace.pr_merged, workspace.agent_error, and more. Deliveries retry with backoff and are signed so you can verify them:
// aq-signature: t=1700000000,v1=<hex>
const [t, v1] = header.split(",").map((p) => p.split("=")[1]);
const expected = crypto.createHmac("sha256", secret)
.update(t + "." + rawBody)
.digest("hex");
// timing-safe compare v1 against expected, and reject stale timestamps
The signing secret is returned once when you create the endpoint. Endpoints that fail continuously are disabled automatically and can be re-created.
MCP
The same surface is available as an MCP server at https://aq.dev/mcp (streamable HTTP), so Claude, Cursor, or any MCP client can list your workspaces, create new ones, read event logs, and fetch preview URLs. Authenticate with the same API key as a Bearer token:
{
"mcpServers": {
"aq": {
"url": "https://aq.dev/mcp",
"headers": { "Authorization": "Bearer aq_your_key" }
}
}
}
Errors and limits
Errors use machine-readable snake_case codes in a stable envelope ({"error": "rate_limited"}), with HTTP status conventions you expect: 401 for a bad key, 403 for a missing scope, 404 for anything not visible to you, 409 while a first attempt is still running, 422 for an idempotency key reused with a different body, and 429 with a Retry-After header when you are rate limited (240 requests per minute per key by default).
Reference
The complete machine-readable reference lives at /v1/openapi.json (OpenAPI 3.1). Endpoints today: workspaces (list, get, create, close), workspace events, pull requests, previews, repos, webhooks, and key introspection at /v1/me.