Qase REST API v1
Workflow
Config preamble: read sparq.config.json, resolve outputs.tms.qase.projectCode as QASE_PROJECT_CODE for all API calls. If not configured, check $QASE_DEFAULT_PROJECT env variable.
- Identify the operation from the Endpoint Index below
- Read the matching reference file for curl examples and body schemas:
- Cases, Suites, Projects → Read references/cases-suites.md
- Runs, Results, Plans → Read references/runs-results.md
- All other entities → Read references/other-endpoints.md
- Use enum values from Enum Field Mapping (integers, not strings)
- On 404/422 errors → apply Web Docs Fallback
Do not load all reference files at once — load only the one needed for the current operation.
Quick Reference
- Base URL:
https://api.qase.io/v1
- Auth header:
Token: $QASE_API_TOKEN
- Content-Type:
application/json
- Project code:
${QASE_PROJECT_CODE} — resolved from outputs.tms.qase.projectCode in sparq.config.json. Env override: QASE_DEFAULT_PROJECT
- Rate limit: 600 req/min — 429 returns
Retry-After: 60
- Pagination:
limit (1-100, default 10), offset (0-100000)
- Response envelope:
{ "status": true, "result": { "total": N, "filtered": N, "count": N, "entities": [...] } }
Enum Field Mapping
CRITICAL: Text labels ("high", "smoke") FAIL. Use integer values.
REST API uses plain integers. MCP tools use numeric strings ("1"). Both map identically.
Priority
- P1 (high) →
1
- P2 (medium) →
2
- P3 (low) →
3
- P4 (not set) →
0
Type
- Functional →
1
- Smoke →
2
- Regression →
3
- Security →
4
- Usability →
5
- Performance →
6
- Acceptance →
7
Behavior
- Positive →
1
- Negative →
2
- Destructive →
3
Result Status
- passed →
"passed"
- failed →
"failed"
- blocked →
"blocked"
- skipped →
"skipped"
- invalid →
"invalid"
Error Handling
429 Rate Limit Pattern
response=$(curl -s -w "\n%{http_code}" -X GET "$URL" -H "Token: $QASE_API_TOKEN")
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" = "429" ]; then
sleep 60
response=$(curl -s -w "\n%{http_code}" -X GET "$URL" -H "Token: $QASE_API_TOKEN")
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')
fi
Common Errors
- 401 — token missing/invalid
- 403 — insufficient permissions
- 404 — resource not found (check project code, IDs; if path seems correct → web fallback)
- 422 — validation error (check enum IDs, required fields; if fields seem correct → web fallback)
- 429 — rate limit (wait 60s, retry once)
- 500 — server error (retry once)
Web Docs Fallback
If REST call returns 404 or 422 and the request looks correct, the endpoint may have changed.
- Search:
WebSearch "qase api {endpoint-name} site:developers.qase.io"
- Fetch:
WebFetch "https://developers.qase.io/reference/{endpoint-slug}" with prompt to extract path, method, body fields
- Use extracted info to retry the operation
- Log:
[sparq] REST endpoint changed — resolved from Qase developer docs
- If web lookup fails → stop, report error with
https://developers.qase.io/reference/ for manual check
Parse Response
body=$(curl -s -H "Token: $QASE_API_TOKEN" "$URL")
# Extract with python3 (universally available)
status=$(echo "$body" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
Destructive Operations
All DELETE endpoints require explicit user confirmation before execution.
Before calling any DELETE endpoint, present:
[sparq] About to DELETE {entity type}:
- {entity description (title/ID/code)}
- Endpoint: DELETE {path}
This action is irreversible. Proceed? (yes / cancel)
Never execute a DELETE call without user approval. This applies to both direct /qase-api usage and when invoked as a fallback from other skills.
Endpoint Index
Projects
- GET /project — list all projects
- POST /project — create project
- GET /project/{code} — get by code
- DELETE /project/{code} — delete
- POST /project/{code}/access — grant access
- DELETE /project/{code}/access — revoke access
Suites
- GET /suite/{code} — list suites
- POST /suite/{code} — create suite
- GET /suite/{code}/{id} — get suite
- PATCH /suite/{code}/{id} — update suite
- DELETE /suite/{code}/{id} — delete suite
Cases
- GET /case/{code} — list cases (filter:
suite_id, search, priority, type, behavior)
- POST /case/{code} — create case
- POST /case/{code}/bulk — bulk create cases
- GET /case/{code}/{id} — get case
- PATCH /case/{code}/{id} — update case
- DELETE /case/{code}/{id} — delete case
- POST /case/{code}/external-issue/attach — attach external issue
- POST /case/{code}/external-issue/detach — detach external issue
Runs
- GET /run/{code} — list runs
- POST /run/{code} — create run
- GET /run/{code}/{id} — get run
- DELETE /run/{code}/{id} — delete run
- POST /run/{code}/{id}/complete — complete run
- PATCH /run/{code}/{id}/publicity — update publicity
- POST /run/{code}/{id}/external-issues — update external issues
Results
- GET /result/{code} — list results
- POST /result/{code}/{run_id} — create result
- POST /result/{code}/{run_id}/bulk — bulk create results
- GET /result/{code}/{run_id}/{hash} — get result
- PATCH /result/{code}/{run_id}/{hash} — update result
- DELETE /result/{code}/{run_id}/{hash} — delete result
Plans
- GET /plan/{code} — list plans
- POST /plan/{code} — create plan
- GET /plan/{code}/{id} — get plan
- PATCH /plan/{code}/{id} — update plan
- DELETE /plan/{code}/{id} — delete plan
Milestones
- GET /milestone/{code} — list milestones
- POST /milestone/{code} — create milestone
- GET /milestone/{code}/{id} — get milestone
- PATCH /milestone/{code}/{id} — update milestone
- DELETE /milestone/{code}/{id} — delete milestone
Environments
- GET /environment/{code} — list environments
- POST /environment/{code} — create environment
- GET /environment/{code}/{id} — get environment
- PATCH /environment/{code}/{id} — update environment
- DELETE /environment/{code}/{id} — delete environment
Defects
- GET /defect/{code} — list defects
- POST /defect/{code} — create defect
- GET /defect/{code}/{id} — get defect
- PATCH /defect/{code}/{id} — update defect
- DELETE /defect/{code}/{id} — delete defect
- PATCH /defect/{code}/resolve/{id} — resolve defect
- PATCH /defect/{code}/status/{id} — update status
Shared Steps
- GET /shared_step/{code} — list shared steps
- POST /shared_step/{code} — create shared step
- GET /shared_step/{code}/{hash} — get shared step
- PATCH /shared_step/{code}/{hash} — update shared step
- DELETE /shared_step/{code}/{hash} — delete shared step
Shared Parameters (workspace-wide, no project code)
- GET /shared_parameter — list parameters
- POST /shared_parameter — create parameter
- GET /shared_parameter/{id} — get parameter
- PATCH /shared_parameter/{id} — update parameter
- DELETE /shared_parameter/{id} — delete parameter
Configurations
- GET /configuration/{code} — list config groups
- POST /configuration/{code} — create configuration
- POST /configuration/{code}/group — create config group
- DELETE /configuration/{code}/group/{id} — delete config group
Custom Fields (workspace-wide, no project code)
- GET /custom_field — list custom fields
- POST /custom_field — create custom field
- GET /custom_field/{id} — get custom field
- PATCH /custom_field/{id} — update custom field
- DELETE /custom_field/{id} — delete custom field
System Fields
- GET /system_field — list all system fields (read-only)
Attachments
- GET /attachment — list attachments (workspace-wide)
- POST /attachment/{code} — upload attachment (multipart, max 32MB/file, 20 files/req)
- GET /attachment/{hash} — get attachment
- DELETE /attachment/{hash} — delete attachment
Authors / Users
- GET /author — list authors
- GET /author/{id} — get author
- GET /user — list users
- GET /user/{id} — get user
Search (QQL)
- GET /search — search entities (
type + QQL query params)
References
claude/skills/sparq-shared/references/qase-formats.md
claude/skills/sparq-shared/references/tms-abstraction.md
claude/skills/sparq-shared/references/degradation-strategy.md
claude/skills/sparq-shared/references/mcp-tool-inventory.md
claude/skills/sparq-shared/references/config-schema.md
Cross-References
Examples
/sparq:qase-api
-> "Create a test suite called 'Authentication' in Qase"
-> reads sparq.config.json: outputs.tms.qase.projectCode = "PROJ"
-> curl -s -X POST "https://api.qase.io/v1/suite/PROJ" ...
-> Suite created: id=10
/sparq:qase-api
-> "List all test cases in suite 42"
-> curl -s "https://api.qase.io/v1/case/PROJ?suite_id=42&limit=100"
-> 15 cases found
1---2name: sparq-qase-api3description: Direct Qase REST API v1 reference for HTTP calls via curl/Bash. Use when Qase MCP server is unavailable, broken, or returning errors and direct API interaction is needed. Covers all endpoint groups (cases, suites, runs, results, projects, milestones, environments, defects, shared steps/parameters, configs, custom fields, attachments, users, search) with curl examples. Project code: from outputs.tms.qase.projectCode in sparq.config.json (env: QASE_DEFAULT_PROJECT). Triggered by: MCP broken, use Qase API directly, curl Qase, bypass MCP, or when mcp__qase__ tools fail and Qase operations are needed.4---56# Qase REST API v178## Workflow910Config preamble: read `sparq.config.json`, resolve `outputs.tms.qase.projectCode` as `QASE_PROJECT_CODE` for all API calls. If not configured, check `$QASE_DEFAULT_PROJECT` env variable.11121. Identify the operation from the [Endpoint Index](#endpoint-index) below132. **Read the matching reference file** for curl examples and body schemas:14 - Cases, Suites, Projects → Read [references/cases-suites.md](references/cases-suites.md)15 - Runs, Results, Plans → Read [references/runs-results.md](references/runs-results.md)16 - All other entities → Read [references/other-endpoints.md](references/other-endpoints.md)173. Use enum values from [Enum Field Mapping](#enum-field-mapping) (integers, not strings)184. On 404/422 errors → apply [Web Docs Fallback](#web-docs-fallback)1920**Do not load all reference files at once — load only the one needed for the current operation.**2122## Quick Reference2324- Base URL: `https://api.qase.io/v1`25- Auth header: `Token: $QASE_API_TOKEN`26- Content-Type: `application/json`27- Project code: `${QASE_PROJECT_CODE}` — resolved from `outputs.tms.qase.projectCode` in `sparq.config.json`. Env override: `QASE_DEFAULT_PROJECT`28- Rate limit: 600 req/min — 429 returns `Retry-After: 60`29- Pagination: `limit` (1-100, default 10), `offset` (0-100000)30- Response envelope:31 ```json32 { "status": true, "result": { "total": N, "filtered": N, "count": N, "entities": [...] } }33 ```3435## Enum Field Mapping3637**CRITICAL: Text labels ("high", "smoke") FAIL. Use integer values.**3839REST API uses plain integers. MCP tools use numeric strings (`"1"`). Both map identically.4041### Priority42- P1 (high) → `1`43- P2 (medium) → `2`44- P3 (low) → `3`45- P4 (not set) → `0`4647### Type48- Functional → `1`49- Smoke → `2`50- Regression → `3`51- Security → `4`52- Usability → `5`53- Performance → `6`54- Acceptance → `7`5556### Behavior57- Positive → `1`58- Negative → `2`59- Destructive → `3`6061### Result Status62- passed → `"passed"`63- failed → `"failed"`64- blocked → `"blocked"`65- skipped → `"skipped"`66- invalid → `"invalid"`6768## Error Handling6970### 429 Rate Limit Pattern7172```bash73response=$(curl -s -w "\n%{http_code}" -X GET "$URL" -H "Token: $QASE_API_TOKEN")74http_code=$(echo "$response" | tail -1)75body=$(echo "$response" | sed '$d')76if [ "$http_code" = "429" ]; then77 sleep 6078 response=$(curl -s -w "\n%{http_code}" -X GET "$URL" -H "Token: $QASE_API_TOKEN")79 http_code=$(echo "$response" | tail -1)80 body=$(echo "$response" | sed '$d')81fi82```8384### Common Errors85- 401 — token missing/invalid86- 403 — insufficient permissions87- 404 — resource not found (check project code, IDs; if path seems correct → web fallback)88- 422 — validation error (check enum IDs, required fields; if fields seem correct → web fallback)89- 429 — rate limit (wait 60s, retry once)90- 500 — server error (retry once)9192### Web Docs Fallback9394If REST call returns 404 or 422 and the request looks correct, the endpoint may have changed.95961. Search: `WebSearch "qase api {endpoint-name} site:developers.qase.io"`972. Fetch: `WebFetch "https://developers.qase.io/reference/{endpoint-slug}"` with prompt to extract path, method, body fields983. Use extracted info to retry the operation994. Log: `[sparq] REST endpoint changed — resolved from Qase developer docs`1005. If web lookup fails → stop, report error with `https://developers.qase.io/reference/` for manual check101102### Parse Response103104```bash105body=$(curl -s -H "Token: $QASE_API_TOKEN" "$URL")106# Extract with python3 (universally available)107status=$(echo "$body" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")108```109110## Destructive Operations111112**All DELETE endpoints require explicit user confirmation before execution.**113114Before calling any DELETE endpoint, present:115116```117[sparq] About to DELETE {entity type}:118 - {entity description (title/ID/code)}119 - Endpoint: DELETE {path}120121This action is irreversible. Proceed? (yes / cancel)122```123124Never execute a DELETE call without user approval. This applies to both direct `/qase-api` usage and when invoked as a fallback from other skills.125126## Endpoint Index127128### Projects129- GET /project — list all projects130- POST /project — create project131- GET /project/{code} — get by code132- DELETE /project/{code} — delete133- POST /project/{code}/access — grant access134- DELETE /project/{code}/access — revoke access135136### Suites137- GET /suite/{code} — list suites138- POST /suite/{code} — create suite139- GET /suite/{code}/{id} — get suite140- PATCH /suite/{code}/{id} — update suite141- DELETE /suite/{code}/{id} — delete suite142143### Cases144- GET /case/{code} — list cases (filter: `suite_id`, `search`, `priority`, `type`, `behavior`)145- POST /case/{code} — create case146- POST /case/{code}/bulk — bulk create cases147- GET /case/{code}/{id} — get case148- PATCH /case/{code}/{id} — update case149- DELETE /case/{code}/{id} — delete case150- POST /case/{code}/external-issue/attach — attach external issue151- POST /case/{code}/external-issue/detach — detach external issue152153### Runs154- GET /run/{code} — list runs155- POST /run/{code} — create run156- GET /run/{code}/{id} — get run157- DELETE /run/{code}/{id} — delete run158- POST /run/{code}/{id}/complete — complete run159- PATCH /run/{code}/{id}/publicity — update publicity160- POST /run/{code}/{id}/external-issues — update external issues161162### Results163- GET /result/{code} — list results164- POST /result/{code}/{run_id} — create result165- POST /result/{code}/{run_id}/bulk — bulk create results166- GET /result/{code}/{run_id}/{hash} — get result167- PATCH /result/{code}/{run_id}/{hash} — update result168- DELETE /result/{code}/{run_id}/{hash} — delete result169170### Plans171- GET /plan/{code} — list plans172- POST /plan/{code} — create plan173- GET /plan/{code}/{id} — get plan174- PATCH /plan/{code}/{id} — update plan175- DELETE /plan/{code}/{id} — delete plan176177### Milestones178- GET /milestone/{code} — list milestones179- POST /milestone/{code} — create milestone180- GET /milestone/{code}/{id} — get milestone181- PATCH /milestone/{code}/{id} — update milestone182- DELETE /milestone/{code}/{id} — delete milestone183184### Environments185- GET /environment/{code} — list environments186- POST /environment/{code} — create environment187- GET /environment/{code}/{id} — get environment188- PATCH /environment/{code}/{id} — update environment189- DELETE /environment/{code}/{id} — delete environment190191### Defects192- GET /defect/{code} — list defects193- POST /defect/{code} — create defect194- GET /defect/{code}/{id} — get defect195- PATCH /defect/{code}/{id} — update defect196- DELETE /defect/{code}/{id} — delete defect197- PATCH /defect/{code}/resolve/{id} — resolve defect198- PATCH /defect/{code}/status/{id} — update status199200### Shared Steps201- GET /shared_step/{code} — list shared steps202- POST /shared_step/{code} — create shared step203- GET /shared_step/{code}/{hash} — get shared step204- PATCH /shared_step/{code}/{hash} — update shared step205- DELETE /shared_step/{code}/{hash} — delete shared step206207### Shared Parameters (workspace-wide, no project code)208- GET /shared_parameter — list parameters209- POST /shared_parameter — create parameter210- GET /shared_parameter/{id} — get parameter211- PATCH /shared_parameter/{id} — update parameter212- DELETE /shared_parameter/{id} — delete parameter213214### Configurations215- GET /configuration/{code} — list config groups216- POST /configuration/{code} — create configuration217- POST /configuration/{code}/group — create config group218- DELETE /configuration/{code}/group/{id} — delete config group219220### Custom Fields (workspace-wide, no project code)221- GET /custom_field — list custom fields222- POST /custom_field — create custom field223- GET /custom_field/{id} — get custom field224- PATCH /custom_field/{id} — update custom field225- DELETE /custom_field/{id} — delete custom field226227### System Fields228- GET /system_field — list all system fields (read-only)229230### Attachments231- GET /attachment — list attachments (workspace-wide)232- POST /attachment/{code} — upload attachment (multipart, max 32MB/file, 20 files/req)233- GET /attachment/{hash} — get attachment234- DELETE /attachment/{hash} — delete attachment235236### Authors / Users237- GET /author — list authors238- GET /author/{id} — get author239- GET /user — list users240- GET /user/{id} — get user241242### Search (QQL)243- GET /search — search entities (`type` + QQL `query` params)244245## References246247- `claude/skills/sparq-shared/references/qase-formats.md`248- `claude/skills/sparq-shared/references/tms-abstraction.md`249- `claude/skills/sparq-shared/references/degradation-strategy.md`250- `claude/skills/sparq-shared/references/mcp-tool-inventory.md`251- `claude/skills/sparq-shared/references/config-schema.md`252253## Cross-References254255- Qase MCP tool inventory: [mcp-tool-inventory.md](../sparq-shared/references/mcp-tool-inventory.md) (Qase section)256- Qase export format: [qase-formats.md](../sparq-shared/references/qase-formats.md)257- TMS abstraction: [tms-abstraction.md](../sparq-shared/references/tms-abstraction.md)258- Degradation strategy: [degradation-strategy.md](../sparq-shared/references/degradation-strategy.md)259260## Examples261262```263/sparq:qase-api264-> "Create a test suite called 'Authentication' in Qase"265-> reads sparq.config.json: outputs.tms.qase.projectCode = "PROJ"266-> curl -s -X POST "https://api.qase.io/v1/suite/PROJ" ...267-> Suite created: id=10268269/sparq:qase-api270-> "List all test cases in suite 42"271-> curl -s "https://api.qase.io/v1/case/PROJ?suite_id=42&limit=100"272-> 15 cases found273```