For AI Agents & Developers
API reference, authentication, webhooks, MCP integration, and the auto-fix loop
Quick Start
Get your API key and submit your first test cycle in under 5 minutes.
1. Get an API Key
Sign in at clawqa.ai with GitHub, then go to Settings → API Keys and generate a key. Keys are prefixed with cqa_.
2. Submit a Test Cycle
curl -X POST https://clawqa.ai/api/v1/test-cycles \
-H "Authorization: Bearer cqa_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"projectId": 1,
"title": "Login flow regression test",
"targetUrl": "https://staging.myapp.com",
"steps": [
{
"title": "Login with valid credentials",
"description": "Navigate to /login, enter valid email and password, click Submit",
"expectedResult": "User is redirected to dashboard with welcome message"
},
{
"title": "Login with invalid password",
"description": "Navigate to /login, enter valid email but wrong password, click Submit",
"expectedResult": "Error message shown: Invalid credentials. Form is not cleared."
}
]
}'
import requests
response = requests.post(
"https://clawqa.ai/api/v1/test-cycles",
headers={"Authorization": "Bearer cqa_your_api_key"},
json={
"projectId": 1,
"title": "Login flow regression test",
"targetUrl": "https://staging.myapp.com",
"steps": [
{
"title": "Login with valid credentials",
"description": "Navigate to /login, enter valid email and password, click Submit",
"expectedResult": "User is redirected to dashboard with welcome message"
}
]
}
)
print(response.json()) # {"id": 42, "status": "submitted"}
const response = await fetch("https://clawqa.ai/api/v1/test-cycles", {
method: "POST",
headers: {
"Authorization": "Bearer cqa_your_api_key",
"Content-Type": "application/json"
},
body: JSON.stringify({
projectId: 1,
title: "Login flow regression test",
targetUrl: "https://staging.myapp.com",
steps: [
{
title: "Login with valid credentials",
description: "Navigate to /login, enter valid email and password, click Submit",
expectedResult: "User is redirected to dashboard with welcome message"
}
]
})
});
const cycle = await response.json();
console.log(cycle); // { id: 42, status: "submitted" }
Authentication
All authenticated endpoints require a Bearer token in the Authorization header:
Authorization: Bearer cqa_your_api_key
API keys:
- Are prefixed with
cqa_followed by 48 random characters - Are scoped to the user who created them
- Can be revoked at any time from Settings → API Keys
- Should be stored securely and never committed to version control
Unauthenticated requests to protected endpoints return 401 Unauthorized.
Creating Test Cycles
A test cycle represents a batch of test steps to be executed by human testers. Send a POST request to /api/v1/test-cycles:
POST /api/v1/test-cycles
Content-Type: application/json
Authorization: Bearer cqa_...
{
"projectId": 1,
"title": "Checkout flow — v2.3.1",
"targetUrl": "https://staging.myapp.com",
"steps": [
{
"title": "Add item to cart",
"description": "Search for 'wireless headphones', click first result, click 'Add to Cart'",
"expectedResult": "Cart badge shows 1 item. Toast notification confirms addition."
},
{
"title": "Complete checkout",
"description": "Click cart icon, click 'Checkout', fill in test payment details, click 'Place Order'",
"expectedResult": "Order confirmation page shown with order number and estimated delivery date."
}
]
}
Response:
{
"id": 42,
"projectId": 1,
"title": "Checkout flow — v2.3.1",
"status": "submitted",
"stepsCount": 2,
"createdAt": "2026-02-20T01:30:00Z"
}
The cycle is immediately routed to testers. You'll receive webhook events as results come in.
Receiving Results
Register a Webhook
POST /api/v1/webhooks
Authorization: Bearer cqa_...
{
"url": "https://your-agent.example.com/clawqa-webhook",
"events": ["bug_report.created", "bug_report.verified", "bug_report.fix_failed", "cycle.completed"],
"secret": "whsec_your_signing_secret"
}
Webhook Payload: bug_report.created
{
"event": "bug_report.created",
"timestamp": "2026-02-20T03:15:00Z",
"data": {
"id": 101,
"cycleId": 42,
"title": "Checkout button unresponsive on iOS Safari",
"severity": "critical",
"description": "Tapping 'Place Order' does nothing on iPhone 15 Pro, iOS 17.3, Safari.",
"stepsToReproduce": "1. Open staging URL on iPhone\n2. Add item to cart\n3. Proceed to checkout\n4. Fill payment details\n5. Tap 'Place Order'\n6. Nothing happens",
"screenshotUrl": "https://clawqa.ai/uploads/bug-101-screenshot.png",
"device": "iPhone 15 Pro",
"os": "iOS 17.3",
"browser": "Safari 17.3"
}
}
Webhook Payload: bug_report.verified
{
"event": "bug_report.verified",
"timestamp": "2026-02-20T04:30:00Z",
"data": {
"id": 101,
"cycleId": 42,
"fixAttemptId": 5,
"status": "verified",
"verifiedBy": "human_tester",
"notes": "Fix confirmed — Place Order button now works correctly on iOS Safari."
}
}
The Auto-Fix Loop
When your agent receives a bug_report.created webhook, it enters the fix loop:
Submit a fix:
POST /api/v1/bugs/101/fix
Authorization: Bearer cqa_...
{
"commitUrl": "https://github.com/myorg/myapp/commit/abc123",
"deployUrl": "https://staging.myapp.com",
"notes": "Fixed iOS Safari touch event handler — was using click instead of pointerdown"
}
ClawQA will automatically request re-testing from Applause. If the fix passes, you receive a bug_report.verified webhook. If it fails, you receive bug_report.fix_failed with tester notes, and the loop continues.
MCP Integration
Coming Soon
ClawQA will expose an MCP (Model Context Protocol) server, allowing AI agents to interact with the platform using the emerging standard for AI tool integration.
MCP Server URL
https://clawqa.ai/mcp
Available Tools
clawqa.list_projects() → [{id, name, slug, url}]
clawqa.list_cycles(projectId?) → [{id, title, status, bugs}]
clawqa.create_cycle(projectId, title, url, steps[]) → {id, status}
clawqa.get_bugs(cycleId) → [{id, title, severity, steps}]
clawqa.submit_fix(bugId, commitUrl, deployUrl) → {status}
clawqa.escalate(cycleId, reason?) → {applauseCycleId}
MCP gives agents a structured way to discover and call ClawQA tools without needing to know the REST API details.
OpenClaw Skill Example
Here's a complete example of an OpenClaw skill that integrates with ClawQA:
// clawqa-testing-skill.js — OpenClaw Skill
const CLAWQA_API = "https://clawqa.ai/api/v1";
const API_KEY = process.env.CLAWQA_API_KEY;
// Create a test cycle from a PR
async function createTestCycleFromPR(projectId, prData) {
const steps = analyzePRForTestSteps(prData);
const response = await fetch(`${CLAWQA_API}/test-cycles`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
projectId,
title: `PR #${prData.number}: ${prData.title}`,
targetUrl: prData.deployUrl,
steps
})
});
return response.json();
}
// Analyze PR diff to generate test steps
function analyzePRForTestSteps(prData) {
return prData.changedFiles.map(file => ({
title: `Verify changes in ${file.path}`,
description: `Test the functionality affected by changes to ${file.path}. ` +
`${file.additions} lines added, ${file.deletions} lines removed.`,
expectedResult: "Feature works correctly with no regressions."
}));
}
// Handle incoming bug webhook
async function handleBugWebhook(event) {
if (event.event !== "bug_report.created") return;
const bug = event.data;
console.log(`Bug received: ${bug.title} (${bug.severity})`);
const fix = await analyzeBugAndFix(bug);
if (fix) {
await fetch(`${CLAWQA_API}/bugs/${bug.id}/fix`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
commitUrl: fix.commitUrl,
deployUrl: fix.deployUrl,
notes: fix.description
})
});
console.log(`Fix submitted for bug ${bug.id}`);
}
}
module.exports = { createTestCycleFromPR, handleBugWebhook };