{
  "openapi": "3.0.3",
  "info": {
    "title": "CasePilot API",
    "description": "AI-powered test case generation for Azure DevOps. Uses a two-pass Worker + Judge pipeline to produce structured, categorized, automation-ready test cases from user story descriptions.",
    "version": "1.0.0",
    "contact": {
      "name": "CasePilot Support",
      "email": "support@casepilot.dev"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.iklab.dev",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/api/v1/generate": {
      "post": {
        "operationId": "generateTestCases",
        "summary": "Generate test cases",
        "description": "Generate structured test cases from a user story description using the two-pass Worker + Judge AI pipeline. Each generated test case counts against your monthly usage quota.",
        "tags": [
          "Generation"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Test cases generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "AI service temporarily unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Get usage and credits",
        "description": "Returns current credit usage for your organization in the current billing period.",
        "tags": [
          "Usage"
        ],
        "responses": {
          "200": {
            "description": "Usage information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/keys/create": {
      "post": {
        "operationId": "createApiKey",
        "summary": "Create an API key",
        "description": "Create a new API key for your organization. The full key value is returned only once — store it securely.",
        "tags": [
          "API Keys"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateKeyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateKeyResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/keys/list": {
      "get": {
        "operationId": "listApiKeys",
        "summary": "List API keys",
        "description": "List all active API keys for your organization. Key values are masked — only the last 4 characters are shown.",
        "tags": [
          "API Keys"
        ],
        "responses": {
          "200": {
            "description": "List of API keys",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKeyInfo"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/keys/revoke": {
      "post": {
        "operationId": "revokeApiKey",
        "summary": "Revoke an API key",
        "description": "Revoke an API key. The key will immediately stop working for all requests.",
        "tags": [
          "API Keys"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Key revoked successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "example": "Key revoked successfully"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Key not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key prefixed with cp_live_ (production) or cp_test_ (testing). Created from the CasePilot extension settings."
      }
    },
    "schemas": {
      "GenerateRequest": {
        "type": "object",
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 500,
            "description": "User story title",
            "example": "User can reset password via email"
          },
          "description": {
            "type": "string",
            "maxLength": 5000,
            "description": "User story description",
            "example": "As a user, I want to reset my password so I can regain access to my account."
          },
          "acceptanceCriteria": {
            "type": "string",
            "maxLength": 5000,
            "description": "Acceptance criteria text",
            "example": "- User receives reset email within 2 minutes\n- Reset link expires after 24 hours"
          },
          "comments": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string",
              "maxLength": 2000
            },
            "description": "Discussion comments for additional context"
          },
          "projectKnowledge": {
            "$ref": "#/components/schemas/ProjectKnowledge"
          },
          "settings": {
            "$ref": "#/components/schemas/GenerationSettings"
          }
        }
      },
      "ProjectKnowledge": {
        "type": "object",
        "description": "Project-specific context to improve generation quality",
        "properties": {
          "techStack": {
            "type": "string",
            "maxLength": 2000,
            "description": "Technology stack description",
            "example": "React + Node.js + PostgreSQL"
          },
          "uiComponents": {
            "type": "string",
            "maxLength": 2000,
            "description": "UI component library or patterns used",
            "example": "Material UI v5 with custom theme"
          },
          "businessRules": {
            "type": "string",
            "maxLength": 2000,
            "description": "Domain-specific business rules or constraints",
            "example": "Passwords require 8+ chars, 1 uppercase, 1 number, 1 special"
          },
          "testingConventions": {
            "type": "string",
            "maxLength": 2000,
            "description": "Testing conventions, naming patterns, or frameworks",
            "example": "Playwright + NUnit, Page Object Model pattern"
          }
        }
      },
      "GenerationSettings": {
        "type": "object",
        "description": "Generation configuration",
        "properties": {
          "maxTestCases": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 5,
            "description": "Number of test cases to generate"
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "positive",
                "negative",
                "edge"
              ]
            },
            "default": [
              "positive",
              "negative",
              "edge"
            ],
            "description": "Test case categories to include"
          },
          "includeAutomationHints": {
            "type": "boolean",
            "default": true,
            "description": "Include automation hints (selectors, API calls) in output"
          }
        }
      },
      "GenerationResponse": {
        "type": "object",
        "properties": {
          "testCases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TestCase"
            }
          },
          "metadata": {
            "$ref": "#/components/schemas/GenerationMetadata"
          },
          "usage": {
            "$ref": "#/components/schemas/UsageInfo"
          }
        }
      },
      "TestCase": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "Test case title"
          },
          "description": {
            "type": "string",
            "description": "Brief test case description"
          },
          "category": {
            "type": "string",
            "enum": [
              "positive",
              "negative",
              "edge"
            ],
            "description": "Test case category"
          },
          "priority": {
            "type": "integer",
            "minimum": 1,
            "maximum": 4,
            "description": "Priority level: 1 (critical) to 4 (low)"
          },
          "preconditions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Required preconditions before executing"
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TestStep"
            },
            "description": "Ordered test steps"
          },
          "automationHints": {
            "type": "string",
            "nullable": true,
            "description": "Automation guidance (selectors, API calls). Null if includeAutomationHints is false."
          }
        }
      },
      "TestStep": {
        "type": "object",
        "properties": {
          "stepNumber": {
            "type": "integer",
            "description": "Step sequence number"
          },
          "action": {
            "type": "string",
            "description": "Action to perform"
          },
          "expectedResult": {
            "type": "string",
            "description": "Expected outcome of the action"
          },
          "testData": {
            "type": "string",
            "nullable": true,
            "description": "Test data to use for this step"
          }
        }
      },
      "GenerationMetadata": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "AI model used for generation",
            "example": "gpt-4o-mini"
          },
          "tokensUsed": {
            "type": "integer",
            "description": "Total tokens consumed (Worker + Judge passes)"
          },
          "generationTimeMs": {
            "type": "integer",
            "description": "Total generation time in milliseconds"
          },
          "qualityScore": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "description": "Judge-assigned quality score"
          },
          "coverageGaps": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Any identified coverage gaps"
          },
          "judgeNotes": {
            "type": "string",
            "description": "Judge review commentary"
          }
        }
      },
      "UsageInfo": {
        "type": "object",
        "properties": {
          "used": {
            "type": "integer",
            "description": "Test cases generated this period"
          },
          "limit": {
            "type": "integer",
            "description": "Monthly test case limit for your plan"
          },
          "remaining": {
            "type": "integer",
            "description": "Credits remaining this period"
          },
          "planId": {
            "type": "string",
            "description": "Current plan identifier",
            "example": "starter"
          }
        }
      },
      "UsageResponse": {
        "type": "object",
        "properties": {
          "used": {
            "type": "integer",
            "description": "Test cases generated this period",
            "example": 42
          },
          "limit": {
            "type": "integer",
            "description": "Monthly test case limit for your plan",
            "example": 200
          },
          "remaining": {
            "type": "integer",
            "description": "Credits remaining this period",
            "example": 158
          },
          "planId": {
            "type": "string",
            "description": "Current plan identifier",
            "example": "starter"
          },
          "periodStart": {
            "type": "string",
            "format": "date-time",
            "description": "Start of the current billing period",
            "example": "2026-04-01T00:00:00Z"
          },
          "periodEnd": {
            "type": "string",
            "format": "date-time",
            "description": "End of the current billing period",
            "example": "2026-04-30T23:59:59Z"
          }
        }
      },
      "CreateKeyRequest": {
        "type": "object",
        "required": [
          "name",
          "orgId"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Descriptive name for the API key",
            "example": "CI Pipeline Key"
          },
          "orgId": {
            "type": "string",
            "description": "Azure DevOps organization ID",
            "example": "my-organization"
          }
        }
      },
      "CreateKeyResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique key identifier",
            "example": "key_abc123"
          },
          "name": {
            "type": "string",
            "description": "Key name",
            "example": "CI Pipeline Key"
          },
          "key": {
            "type": "string",
            "description": "Full API key value. Only returned once at creation time — store securely.",
            "example": "cp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Key creation timestamp",
            "example": "2026-04-03T10:00:00Z"
          }
        }
      },
      "ApiKeyInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique key identifier",
            "example": "key_abc123"
          },
          "name": {
            "type": "string",
            "description": "Key name",
            "example": "CI Pipeline Key"
          },
          "maskedKey": {
            "type": "string",
            "description": "Masked key showing only last 4 characters",
            "example": "cp_live_****************************3def"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Key creation timestamp"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Last time this key was used"
          }
        }
      },
      "RevokeKeyRequest": {
        "type": "object",
        "required": [
          "keyId"
        ],
        "properties": {
          "keyId": {
            "type": "string",
            "description": "ID of the key to revoke",
            "example": "key_abc123"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "Machine-readable error code",
                "example": "VALIDATION_ERROR"
              },
              "message": {
                "type": "string",
                "description": "Human-readable error message",
                "example": "Field 'title' is required and must not be empty."
              }
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Generation",
      "description": "AI test case generation endpoints"
    },
    {
      "name": "Usage",
      "description": "Credit usage and billing information"
    },
    {
      "name": "API Keys",
      "description": "API key management"
    }
  ]
}