REST API for integration partners. Test automation, security scanning, gap analysis, and artifact downloads.
All requests require the X-QualityMax-API-Key header with a valid API token.
# Example request curl -H "X-QualityMax-API-Key: qm-your-api-token" \ https://app.qualitymax.io/api/v1/partner/jobs/{job_id}/report
| Format | Type | How to get |
|---|---|---|
| qm-... | API Token | Settings → API Keys in QualityMax dashboard |
| qm_... | GitHub Actions Key | Generated via CI/CD integration setup |
| Endpoint type | Limit |
|---|---|
| Free endpoints | 60 requests/minute |
| LLM-powered endpoints | 10 requests/minute |
https://app.qualitymax.io/api/v1/partner
The primary integration point. Send a webhook with a URL, and QualityMax crawls the page, generates Playwright tests, executes them, and POSTs results back to your callback URL.
Triggers the full pipeline: AI crawl with browser, element discovery, Playwright test generation, execution with screenshots/video, quality scoring, and callback delivery.
Requires both headers:
| Header | Description |
|---|---|
| X-QualityMax-API-Key | Your API token (qm-... or qm_...) |
| X-Partner-Signature | sha256=<hmac_hex> -- HMAC-SHA256 of the raw request body using your webhook secret |
{
"url": "https://preview-abc.env.yourapp.com",
"feature_description": "Test that users can login and see their dashboard with 4 task sections",
"auth": {
"type": "user_login",
"username": "test@example.com",
"password": "testpass123"
},
"callback_url": "https://your-api.com/qualitymax-results",
"custom_data": {
"deploy_id": "abc-123",
"branch": "feat/new-feature",
"pr_number": 42
},
"options": {
"browser": "chromium",
"headless": true,
"skip_cookie_consent": false,
"quality_threshold": 45,
"auto_execute": true
}
}
| Field | Type | Description |
|---|---|---|
| url | string required | Target URL to crawl and test (max 2048 chars) |
| feature_description | string required | What to test -- natural language instructions (max 8000 chars) |
| callback_url | string required | URL where results will be POSTed (max 2048 chars) |
| auth | object | Login credentials for authenticated pages |
| auth.type | string | user_login (username/password authentication) |
| auth.username | string | Login email or username |
| auth.password | string | Login password |
| custom_data | object | Any JSON object -- echoed back in the callback (max 4KB) |
| options.browser | string | chromium (default), firefox, or webkit |
| options.headless | boolean | Run browser headless (default: true) |
| options.skip_cookie_consent | boolean | Skip cookie consent dismissal (default: false) |
| options.quality_threshold | integer | Minimum quality score 0-100 (default: 45) |
| options.auto_execute | boolean | Execute generated tests automatically (default: true) |
{
"accepted": true,
"job_id": "pwj_abc123def456...",
"message": "Webhook accepted, processing started"
}
When processing completes (typically 30-120 seconds), QualityMax POSTs results to your callback_url with an X-QualityMax-Signature header for verification.
{
"event": "test_results",
"custom_data": { "deploy_id": "abc-123", "branch": "feat/new-feature" },
"workflow_summary": "AI crawl completed, 1 test generated and executed",
"results": {
"status": "passed",
"total_tests": 1,
"passed": 1,
"failed": 0,
"duration_ms": 54600,
"report_app_url": "https://app.qualitymax.io/#/projects/137",
"tests": [
{
"test": "Login and Dashboard Verification",
"status": "passed",
"duration_ms": 4200,
"screenshot_url": "https://app.qualitymax.io/static/test-executions/...",
"video_url": "https://app.qualitymax.io/static/test-executions/...",
"execution_id": "exec_abc123"
}
],
"failures": []
}
}
Compute HMAC-SHA256 of the raw callback body using your webhook secret:
# Python import hmac, hashlib def verify(body: bytes, secret: str, signature: str) -> bool: expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest() return hmac.compare_digest(f"sha256={expected}", signature) # Node.js const crypto = require('crypto'); function verify(body, secret, signature) { const expected = 'sha256=' + crypto .createHmac('sha256', secret).update(body).digest('hex'); return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signature)); }
# Compute HMAC signature BODY='{"url":"https://preview.app.com","feature_description":"Test login","callback_url":"https://api.you.com/results"}' SIG=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "your-webhook-secret" | cut -d' ' -f2) curl -X POST https://app.qualitymax.io/api/webhooks/veilstream \ -H "Content-Type: application/json" \ -H "X-QualityMax-API-Key: qm-your-token" \ -H "X-Partner-Signature: sha256=$SIG" \ -d "$BODY"
Download screenshots, videos, and logs from test executions. All free, no LLM cost.
Returns a 302 redirect to the screenshot image file.
| Name | In | Type | Description |
|---|---|---|---|
| execution_id | path | string required | Test execution result ID |
curl -L -H "X-QualityMax-API-Key: qm-..." \
-o screenshot.png \
https://app.qualitymax.io/api/v1/partner/artifacts/{execution_id}/screenshot
Returns a 302 redirect to the video recording file (WebM/MP4).
curl -L -H "X-QualityMax-API-Key: qm-..." \
-o recording.webm \
https://app.qualitymax.io/api/v1/partner/artifacts/{execution_id}/video
Returns structured execution logs: console output, test output, and errors.
{
"console_logs": [
{ "message": "Navigation to https://...", "type": "info" }
],
"test_output": "Running 1 test...\n PASS login-flow.spec.ts",
"error_message": null
}
Full structured report for a partner webhook job. Includes job metadata, crawl results, generated scripts, execution results, and quality scores.
{
"job": {
"id": "pwj_abc123...",
"status": "callback_sent",
"url": "https://preview.yourapp.com",
"tests_generated": 1,
"duration_seconds": 54.6,
"quality_score": 96
},
"crawl": { "status": "completed", "pages_crawled": 1 },
"scripts": [{ "id": 123, "name": "login-flow", "framework": "playwright" }],
"executions": [{ "status": "passed", "duration": 4200 }]
}
Import a GitHub or GitLab repository for scanning and analysis. Creates a project automatically.
{
"url": "https://github.com/your-org/your-repo",
"branch": "main",
"name": "My Project",
"base_url": "https://app.yoursite.com"
}
| Field | Type | Description |
|---|---|---|
| url | string required | GitHub or GitLab HTTPS URL |
| branch | string | Branch to import (default: main) |
| name | string | Project name (auto-generated from repo if omitted) |
| base_url | string | Application URL for E2E testing |
{
"success": true,
"repository_id": 42,
"project_id": 15,
"name": "your-repo",
"already_exists": false
}
Static Application Security Testing. No LLM cost -- uses Semgrep and Bandit engines.
Trigger a SAST scan on an imported repository. Returns a job_id for polling.
{
"repository_id": 42,
"branch": "main",
"engines": ["semgrep", "bandit"]
}
{
"job_id": "scan_abc123",
"status": "pending",
"status_url": "/api/v1/partner/sast/scan/scan_abc123"
}
Get SAST scan results with findings, severity counts, and CWE classifications.
{
"scan_id": "scan_abc123",
"status": "completed",
"verdict": "pass",
"findings_count": 3,
"critical_count": 0,
"high_count": 1,
"medium_count": 2,
"findings": [
{
"rule_id": "sql-injection",
"severity": "high",
"file": "src/db.py",
"line_start": 42,
"message": "Possible SQL injection",
"cwe_id": "CWE-89"
}
]
}
Parse an OpenAPI/Swagger specification and generate API test cases. Provide either inline spec content or a URL to fetch it.
{
"openapi_url": "https://api.yourapp.com/openapi.json",
"project_id": 15,
"instructions": "Focus on authentication and payment endpoints"
}
| Field | Type | Description |
|---|---|---|
| openapi_spec | string | Inline OpenAPI JSON or YAML content |
| openapi_url | string | URL to fetch spec from |
| project_id | integer | Project to associate tests with |
| instructions | string | Additional context for generation |
Create a test case in a project.
{
"project_id": 15,
"title": "Login with valid credentials",
"description": "Verify user can log in",
"steps": "1. Go to /login\n2. Enter email\n3. Enter password\n4. Click Submit",
"expected_results": "User is redirected to dashboard",
"category": "e2e",
"priority": 1,
"tags": ["auth", "critical-path"]
}
AI-generate test cases from a natural language description. Uses BYOLLM keys if configured.
{
"project_id": 15,
"description": "Generate tests for user authentication flow including login, logout, password reset, and session expiry",
"count": 5
}
Analyze a repository for missing test coverage. Identifies gaps and generates test cases for specified categories. Async -- returns a job_id for polling.
{
"repository_id": 42,
"categories": ["e2e", "security", "integration"],
"max_tests_per_category": 10
}
{
"job_id": "gap_analysis_abc123",
"status": "queued",
"status_url": "/api/v1/partner/gap-analysis/gap_analysis_abc123"
}
Poll gap analysis job status. Returns results when complete.
{
"job_id": "gap_analysis_abc123",
"status": "completed",
"progress": 1.0,
"result": {
"tests_generated": 15,
"categories": { "e2e": 5, "security": 5, "integration": 5 }
}
}
All errors return a JSON object with a detail field.
| Status | Meaning |
|---|---|
| 400 | Bad request -- invalid parameters or missing fields |
| 401 | Unauthorized -- missing or invalid API key |
| 403 | Forbidden -- no access to this resource |
| 404 | Not found -- resource does not exist |
| 429 | Rate limit exceeded -- wait and retry |
| 503 | Service unavailable -- try again later |
{
"detail": "Repository not found. Import it first via POST /api/v1/partner/repositories/import"
}