API Reference
TestPlanIt provides a comprehensive RESTful API for programmatic access to all test management functionality. The API uses ZenStack-generated endpoints with built-in type safety, authentication, and row-level security.
Interactive API Documentation
TestPlanIt includes interactive Swagger UI documentation for exploring and testing the API:
Access the API documentation at: /docs/api in your TestPlanIt instance
The interactive documentation is organized into categories:
| Category | Description |
|---|---|
| Custom API Endpoints | Authentication, file uploads, JUnit imports, search, and admin endpoints |
| Projects & Folders | Project and folder management |
| Test Cases & Repository | Test case management, steps, templates, and custom fields |
| Test Runs & Execution | Test run management, sessions, and execution tracking |
| Planning & Organization | Milestones, configurations, tags, workflows, and statuses |
| Users & Accounts | User management, roles, groups, and account settings |
| Integrations & SSO | External integrations, SSO, and AI/LLM features |
| Attachments & Other | File attachments, comments, and imports |
Overview
The API provides:
- RESTful endpoints for all entities and operations
- Type-safe requests with automatic validation
- Row-level security based on user permissions
- Authentication via NextAuth.js sessions
- Rate limiting and security measures
- OpenAPI 3.0 specification for documentation and client generation
OpenAPI Specification
The OpenAPI specification is available programmatically:
# Get list of API categories
curl https://your-domain.com/api/docs
# Get OpenAPI spec for a specific category
curl https://your-domain.com/api/docs?category=custom
curl https://your-domain.com/api/docs?category=projects
curl https://your-domain.com/api/docs?category=testCases
curl https://your-domain.com/api/docs?category=testRuns
curl https://your-domain.com/api/docs?category=planning
curl https://your-domain.com/api/docs?category=users
curl https://your-domain.com/api/docs?category=integrations
curl https://your-domain.com/api/docs?category=other
You can use these specifications to:
- Generate API clients in any language
- Import into tools like Postman or Insomnia
- Build custom integrations
Authentication
TestPlanIt supports two authentication methods:
- API Tokens - For programmatic access (CLI, CI/CD, scripts)
- Session-Based - For browser-based requests
API Token Authentication (Recommended for Integrations)
API tokens provide persistent authentication for server-to-server integrations, CLI tools, and automated workflows.
curl -X POST "https://your-domain.com/api/model/project/findMany" \
-H "Authorization: Bearer tpi_your_token_here" \
-H "Content-Type: application/json" \
-d '{"where": {"isDeleted": false}}'
const response = await fetch('/api/model/project/findMany', {
method: 'POST',
headers: {
'Authorization': 'Bearer tpi_your_token_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({ where: { isDeleted: false } })
});
To create and manage API tokens, see the API Tokens documentation.
Session-Based Authentication
For browser-based requests, TestPlanIt uses NextAuth.js session cookies. Authentication is handled automatically:
// Fetch with automatic session handling
const response = await fetch('/api/model/project/findMany', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include', // Include session cookies
body: JSON.stringify({ where: { isDeleted: false } })
});
Base URL and Endpoints
Base URL: https://your-domain.com/api
ZenStack Model Endpoints
ZenStack generates RESTful endpoints for all data models:
/api/model/{entity}/findMany - List entities with filtering
/api/model/{entity}/findUnique - Get single entity by ID
/api/model/{entity}/create - Create new entity
/api/model/{entity}/update - Update existing entity
/api/model/{entity}/delete - Delete entity
/api/model/{entity}/count - Count entities
/api/model/{entity}/aggregate - Aggregate operations
Custom Endpoints
Additional endpoints for specialized operations:
/api/junit/import - Import JUnit XML test results
/api/search - Full-text search
/api/files/upload - File uploads
/api/admin/* - Administrative operations
Common Operations
Querying Data
All ZenStack endpoints support Prisma-style query parameters:
// Find all projects with filtering and includes
const response = await fetch('/api/model/project/findMany', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
where: {
name: { contains: 'Test' }
},
include: {
folders: true,
assignments: {
include: { user: true }
}
},
orderBy: { createdAt: 'desc' },
take: 10,
skip: 0
})
});
Creating Records
// Create a new test case
const response = await fetch('/api/model/repositoryCase/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
data: {
title: 'Login Test',
description: 'Verify user can log in',
project: { connect: { id: projectId } },
folder: { connect: { id: folderId } }
}
})
});
Updating Records
// Update a test case
const response = await fetch('/api/model/repositoryCase/update', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
where: { id: caseId },
data: {
title: 'Updated Title',
description: 'Updated description'
}
})
});
Deleting Records
// Delete a test case
const response = await fetch('/api/model/repositoryCase/delete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
where: { id: caseId }
})
});
JUnit Import API
Import JUnit XML test results to create test runs with test cases:
curl -X POST "https://your-domain.com/api/junit/import" \
-H "Authorization: Bearer tpi_your_token_here" \
-F "name=My Test Run" \
-F "projectId=1" \
-F "files=@/path/to/junit-results.xml" \
-F "stateId=5" \
-F "parentFolderId=10" \
-F "configId=2" \
-F "milestoneId=3" \
-F "tagIds=1" \
-F "tagIds=2"
Parameters:
| Parameter | Required | Description |
|---|---|---|
name | Yes | Name for the test run |
projectId | Yes | Project ID |
files | Yes | One or more JUnit XML files |
stateId | No | Workflow state ID for the test run |
parentFolderId | No | Folder ID for storing test cases |
testRunId | No | Existing test run ID to append results to |
configId | No | Configuration ID |
milestoneId | No | Milestone ID |
tagIds | No | Tag IDs (repeat for multiple) |
Response:
The API returns a Server-Sent Events (SSE) stream with progress updates:
data: {"progress": 10, "status": "Validating input..."}
data: {"progress": 50, "status": "Processing test case 25 of 50..."}
data: {"progress": 100, "status": "Import completed!"}
data: {"complete": true, "testRunId": 456}
Error Handling
All API endpoints return consistent error responses:
{
"error": "Error message",
"code": "ERROR_CODE",
"details": {}
}
Common HTTP Status Codes
| Status | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Not authenticated |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found |
| 500 | Internal Server Error |
Rate Limiting
TestPlanIt enforces a global hourly rate limit on all authenticated API requests. The limit applies per instance (not per token or per user) and resets on the hour.
Tier Limits
The TIER environment variable selects the hourly limit:
| Tier | Hourly Limit | Typical Use |
|---|---|---|
essentials | 1,000 requests/hour | Small teams, light CI/CD integration |
team | 5,000 requests/hour | Mid-size teams with moderate automation |
professional (default) | 10,000 requests/hour | Most production deployments |
dedicated | 25,000 requests/hour | Heavy CI/CD workloads, large organizations |
When the limit is exceeded, requests return HTTP 429 with a Retry-After header indicating seconds until the window resets.
Response Headers
Every API response includes the following headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current hour |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets |
Implementation
Rate limiting uses a Valkey-backed fixed-window counter aligned to hourly boundaries. If Valkey is unavailable, TestPlanIt falls back to in-memory counting (per-instance).
Disabling Rate Limiting (Load Testing Only)
For isolated load-testing or development environments, you can disable rate limiting entirely by setting:
DISABLE_API_RATE_LIMIT=true
Never enable DISABLE_API_RATE_LIMIT in production. This bypasses a key protection against abuse and accidental resource exhaustion. It is intended only for isolated test environments where you're intentionally probing throughput limits.
When set, all authenticated requests are allowed through regardless of request volume. The X-RateLimit-* headers still report the configured tier's limit, but the counter never increments and 429 responses are never returned.
Further Resources
- Interactive Documentation: Access
/docs/apiin your TestPlanIt instance - OpenAPI Spec: Available at
/api/docs?category={category} - CLI Tool: See the CLI documentation for importing test results from CI/CD pipelines
- API Tokens: See the API Tokens documentation for managing programmatic access
- ZenStack Documentation (v2): zenstack.dev