CasePilot API Documentation
Integrate AI-powered test case generation into your CI/CD pipeline, CLI tools, or custom workflows.
Overview
CasePilot generates structured, categorized, automation-ready test cases from user story descriptions using a two-pass AI pipeline (Worker + Judge). The Worker generates initial test cases and the Judge reviews them for coverage gaps, duplicates, and quality — producing significantly higher quality than single-pass approaches.
The REST API lets any tool integrate with CasePilot — CI/CD systems, CLI scripts, test management platforms, or custom dashboards. You get the same two-pass AI quality available in the Azure DevOps extension.
https://api.iklab.dev
Authentication
All API endpoints require authentication via an API key. Pass your key using one of these methods:
| Method | Header | Example |
|---|---|---|
| API Key Header | X-API-Key | X-API-Key: cp_live_abc123... |
| Bearer Token | Authorization | Authorization: Bearer cp_live_abc123... |
API keys are created from the CasePilot extension settings panel in Azure DevOps. All keys are prefixed with cp_live_ for production or cp_test_ for testing.
Generate Test Cases
Generate test cases from a user story description. Uses the three-pass Worker + Judge + Optimizer AI pipeline. Each generated test case counts against your monthly usage quota.
Enrich Story (StoryPilot)
Enrich a User Story title into a fully detailed story with description, acceptance criteria, priority, story points, risks, and definition of done. Uses the two-pass Worker + Judge AI pipeline. Consumes 1 CasePilot credit per enrichment.
Request body:
{
"orgId": "my-organization",
"title": "User can reset password via email",
"context": "Mobile app, React Native",
"existingDescription": "",
"existingAcceptanceCriteria": ""
}
| Field | Type | Required | Description |
|---|---|---|---|
orgId | string | required | Organization identifier |
title | string | required | Story title — the seed for enrichment. Max 1,000 chars. |
context | string | optional | Brief context or notes. Max 10,000 chars. |
existingDescription | string | optional | Existing description to improve (AI enhances rather than generates). Max 50,000 chars. |
existingAcceptanceCriteria | string | optional | Existing AC to improve. Max 30,000 chars. |
Response:
{
"enrichedStory": {
"description": "As a user, I want to reset my password...",
"acceptanceCriteria": [
{ "text": "Reset email arrives within 2 minutes", "category": "functional" },
{ "text": "Link expires after 24 hours", "category": "functional" }
],
"priority": { "level": 2, "justification": "Core auth flow" },
"storyPoints": 5,
"suggestedTags": ["auth", "email"],
"risks": ["Email delivery delay"],
"definitionOfDone": ["Unit tests pass", "E2E test for reset flow"]
},
"metadata": {
"model": "gpt-4o-mini",
"tokensUsed": 1800,
"generationTimeMs": 2500,
"qualityScore": 8,
"judgeNotes": "Well-structured with testable AC."
}
}
Cross-Story Coverage Matrix
Build a 4-dimension coverage heatmap across multiple stories. Detects gap clusters, cross-story dependencies, and risk areas. Free — does not consume credits.
Request body: { orgId, stories: [{ id, title, state, testCaseCount, testCaseIds, description?, acceptanceCriteria?, priority?, storyPoints? }] }
Max 500 stories per request.
Response: Coverage percentages (test, AC, overall), gap clusters (high-priority, large, well-defined, done-without-tests), cross-story dependencies (shared keywords), per-story heatmap cells.
Sprint Test Coverage
Analyze sprint stories for test coverage gaps and risks. Provide stories with their test case counts and get a risk-scored coverage report. Free — does not consume credits.
Request body: { orgId, sprintName, stories: [{ id, title, state, testCaseCount, testCaseIds, ... }] }
Response: Coverage percentage, risk summary (critical/high/medium/low), per-story risk analysis with factors.
Incident-to-Test Bridge
Convert an incident/postmortem report into targeted regression test cases. Uses two-pass AI pipeline. Consumes CasePilot credits.
Request body: { orgId, incident: { title, description, rootCause?, impact?, resolution? }, maxTestCases? }
Response: Regression test cases with steps, incident coverage mapping, prevention insights, and quality score.
Test Health Score
Compute a project-level test health score (A–F). Evaluates pass rate, flakiness, duration, and coverage factors. Requires API key.
Request body:
{
"projectId": "my-project",
"tests": [
{
"name": "Login flow e2e",
"category": "e2e",
"passed": true,
"duration": 4500,
"flaky": false,
"lastRun": "2026-04-14T10:00:00Z"
}
]
}
| Field | Type | Required | Description |
|---|---|---|---|
projectId | string | required | Project identifier. Max 100 characters. |
tests | array | required | Array of test result objects. |
tests[].name | string | required | Test name. |
tests[].category | string | required | "unit", "integration", "e2e", or "unknown". |
tests[].passed | boolean | required | Whether the test passed. |
tests[].duration | number | required | Duration in milliseconds. |
tests[].errorMessage | string | optional | Error message if the test failed. |
tests[].flaky | boolean | required | Whether the test is known to be flaky. |
tests[].lastRun | string | required | ISO 8601 date of last run. |
Response:
{
"projectId": "my-project",
"score": 82,
"grade": "B",
"factors": [
{ "name": "passRate", "score": 95, "weight": 0.4, "detail": "95% of tests passing" },
{ "name": "flakiness", "score": 70, "weight": 0.25, "detail": "3 flaky tests detected" }
],
"summary": "Good overall health with some flaky tests to address.",
"recommendations": [
"Fix 3 flaky tests to improve reliability",
"Add more integration tests for payment module"
]
}
Failure Triage
Group test failures by root cause category (timeout, assertion, connection, permission, resource, flaky, unknown). Provides per-group suggestions and an overall summary. Requires API key.
Request body:
{
"projectId": "my-project",
"failures": [
{
"name": "Checkout timeout test",
"errorMessage": "TimeoutError: waiting for selector",
"stackTrace": "at Object.waitForSelector ...",
"category": "e2e",
"duration": 30000,
"occurrences": 5,
"totalRuns": 20
}
]
}
| Field | Type | Required | Description |
|---|---|---|---|
projectId | string | required | Project identifier. |
failures | array | required | Array of failure objects. |
failures[].name | string | required | Test name. |
failures[].errorMessage | string | required | Error message from the failure. |
failures[].stackTrace | string | optional | Stack trace. |
failures[].category | string | optional | Test category. |
failures[].duration | number | required | Duration in milliseconds. |
failures[].occurrences | number | required | Number of times the failure occurred. |
failures[].totalRuns | number | optional | Total runs of this test. |
Response:
{
"projectId": "my-project",
"groups": [
{
"category": "timeout",
"count": 3,
"failures": [ ... ],
"rootCause": "Slow API responses under load",
"suggestion": "Add explicit wait timeouts and retry logic"
}
],
"summary": {
"totalFailures": 12,
"groupCount": 4,
"topCategory": "timeout",
"estimatedFlakyCount": 2
}
}
Usage & Credits
Returns current credit usage for your organization in the current billing period.
Response:
{
"used": 42,
"limit": 200,
"remaining": 158,
"planId": "starter",
"periodStart": "2026-04-01T00:00:00Z",
"periodEnd": "2026-04-30T23:59:59Z"
}
API Key Management
Create a new API key for your organization. Returns the full key value only once — store it securely.
Request body:
{
"name": "CI Pipeline Key",
"orgId": "my-organization"
}
Response:
{
"id": "key_abc123",
"name": "CI Pipeline Key",
"key": "cp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"createdAt": "2026-04-03T10:00:00Z"
}
List all active API keys for your organization. Key values are masked — only the last 4 characters are shown.
Revoke an API key. The key will immediately stop working for all requests.
Request body:
{
"keyId": "key_abc123"
}
Request Schema
Request body for POST /api/v1/generate:
| Field | Type | Required | Description |
|---|---|---|---|
title | string | required | User story title. Max 500 characters. |
description | string | optional | User story description. Max 5,000 characters. |
acceptanceCriteria | string | optional | Acceptance criteria text. Max 5,000 characters. |
comments | string[] | optional | Discussion comments for additional context. Max 20 items, 2,000 characters each. |
projectKnowledge | object | optional | Project-specific context to improve generation quality. See sub-fields below. |
settings | object | optional | Generation settings. See sub-fields below. |
projectKnowledge sub-fields
| Field | Type | Description |
|---|---|---|
techStack | string | Technology stack description (e.g., "React + Node.js + PostgreSQL"). Max 2,000 characters. |
uiComponents | string | UI component library or patterns used. Max 2,000 characters. |
businessRules | string | Domain-specific business rules or constraints. Max 2,000 characters. |
testingConventions | string | Testing conventions, naming patterns, or frameworks in use. Max 2,000 characters. |
settings sub-fields
| Field | Type | Default | Description |
|---|---|---|---|
maxTestCases | number | 5 | Number of test cases to generate. Range: 1–20. |
categories | string[] | ["positive", "negative", "edge"] | Test case categories to include. Values: "positive", "negative", "edge". |
includeAutomationHints | boolean | true | Include automation hints (selectors, API calls) in output. |
automationFramework | string | — | Target framework: "playwright", "selenium", "cypress", or "other". Produces framework-specific hints. |
Response Schema
Successful response from POST /api/v1/generate:
{
"testCases": [
{
"title": "Verify successful login with valid credentials",
"description": "Test that a user can log in with correct email and password",
"category": "positive",
"priority": 1,
"preconditions": [
"User account exists with verified email",
"User is on the login page"
],
"steps": [
{
"stepNumber": 1,
"action": "Enter valid email in the email field",
"expectedResult": "Email is displayed in the field",
"testData": "[email protected]"
},
{
"stepNumber": 2,
"action": "Enter valid password in the password field",
"expectedResult": "Password is masked in the field",
"testData": "SecurePass123!"
},
{
"stepNumber": 3,
"action": "Click the Login button",
"expectedResult": "User is redirected to the dashboard",
"testData": null
}
],
"automationHints": "Locate email input: [data-testid='email-input']"
}
],
"metadata": {
"model": "gpt-4o-mini",
"tokensUsed": 2450,
"generationTimeMs": 3200,
"qualityScore": 8,
"coverageGaps": [],
"judgeNotes": "Good coverage of positive and negative scenarios."
},
"usage": {
"used": 47,
"limit": 200,
"remaining": 153,
"planId": "starter"
}
}
testCases[] fields
| Field | Type | Description |
|---|---|---|
title | string | Test case title |
description | string | Brief test case description |
category | string | "positive", "negative", or "edge" |
priority | number | Priority level: 1 (critical) to 4 (low) |
preconditions | string[] | Required preconditions before executing |
steps | object[] | Ordered test steps with stepNumber, action, expectedResult, and optional testData |
automationHints | string | null | Automation guidance (selectors, API calls). Null if includeAutomationHints is false. |
metadata fields
| Field | Type | Description |
|---|---|---|
model | string | AI model used for generation |
tokensUsed | number | Total tokens consumed (Worker + Judge passes) |
generationTimeMs | number | Total generation time in milliseconds |
qualityScore | number | Judge-assigned quality score (1–10) |
coverageGaps | string[] | Any identified coverage gaps |
judgeNotes | string | Judge review commentary |
Code Examples
curl -X POST https://api.iklab.dev/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: cp_live_your_api_key_here" \
-d '{
"title": "User can reset password via email",
"description": "As a user, I want to reset my password so I can regain access to my account.",
"acceptanceCriteria": "- User receives reset email within 2 minutes\n- Reset link expires after 24 hours\n- Password must meet complexity requirements",
"settings": {
"maxTestCases": 5,
"categories": ["positive", "negative", "edge"],
"includeAutomationHints": true
}
}'
import requests
API_KEY = "cp_live_your_api_key_here"
BASE_URL = "https://api.iklab.dev"
response = requests.post(
f"{BASE_URL}/api/v1/generate",
headers={
"Content-Type": "application/json",
"X-API-Key": API_KEY,
},
json={
"title": "User can reset password via email",
"description": "As a user, I want to reset my password so I can regain access.",
"acceptanceCriteria": (
"- User receives reset email within 2 minutes\n"
"- Reset link expires after 24 hours\n"
"- Password must meet complexity requirements"
),
"settings": {
"maxTestCases": 5,
"categories": ["positive", "negative", "edge"],
"includeAutomationHints": True,
},
},
)
data = response.json()
for tc in data["testCases"]:
print(f"[{tc['category']}] {tc['title']}")
const API_KEY = "cp_live_your_api_key_here";
const BASE_URL = "https://api.iklab.dev";
const response = await fetch(`${BASE_URL}/api/v1/generate`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": API_KEY,
},
body: JSON.stringify({
title: "User can reset password via email",
description: "As a user, I want to reset my password so I can regain access.",
acceptanceCriteria: [
"- User receives reset email within 2 minutes",
"- Reset link expires after 24 hours",
"- Password must meet complexity requirements",
].join("\n"),
settings: {
maxTestCases: 5,
categories: ["positive", "negative", "edge"],
includeAutomationHints: true,
},
}),
});
const data = await response.json();
for (const tc of data.testCases) {
console.log(`[${tc.category}] ${tc.title}`);
}
using var client = new HttpClient();
client.BaseAddress = new Uri("https://api.iklab.dev");
client.DefaultRequestHeaders.Add("X-API-Key", "cp_live_your_api_key_here");
var request = new
{
title = "User can reset password via email",
description = "As a user, I want to reset my password so I can regain access.",
acceptanceCriteria = string.Join("\n", new[]
{
"- User receives reset email within 2 minutes",
"- Reset link expires after 24 hours",
"- Password must meet complexity requirements"
}),
settings = new
{
maxTestCases = 5,
categories = new[] { "positive", "negative", "edge" },
includeAutomationHints = true
}
};
var json = JsonSerializer.Serialize(request);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("/api/v1/generate", content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
Error Codes
| Status | Code | Description |
|---|---|---|
400 | VALIDATION_ERROR | Invalid request body. Check required fields, field lengths, and value constraints. The response body includes a message field describing the specific validation failure. |
401 | UNAUTHORIZED | Missing or invalid API key. Verify your X-API-Key header or Authorization: Bearer token. |
429 | RATE_LIMITED | Too many requests. You have exceeded 30 requests per minute. Back off and retry with exponential backoff. |
429 | USAGE_LIMIT_EXCEEDED | Monthly test case quota exhausted. Upgrade your plan or wait for the next billing period. |
500 | INTERNAL_ERROR | Unexpected server error. Retry the request. If the issue persists, contact support. |
503 | SERVICE_UNAVAILABLE | The AI service is temporarily unavailable. Retry after a brief delay. |
All error responses follow this format:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Field 'title' is required and must not be empty."
}
}
Rate Limits
API requests are rate-limited using a sliding window per API key:
| Limit | Window | Scope |
|---|---|---|
| 30 requests | 1 minute | Per API key |
Rate limit headers are included in every response:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
429 response, use the X-RateLimit-Reset header to determine when to retry. Implement exponential backoff for best results.
Usage & Billing
API usage shares the same credit pool as the Azure DevOps extension. Credits are metered per test case generated (not per API request). A single request generating 5 test cases consumes 5 credits.
| Plan | Monthly Credits | API Access |
|---|---|---|
| Free | 20 | No |
| Starter ($35/mo) | 200 | Yes |
| Pro ($79/mo) | 1,000 | Yes |
| Team ($149/mo) | 3,000 | Yes |
| Enterprise | Unlimited | Yes |
Monitor your usage by calling GET /api/v1/usage or checking the usage field in generation responses.