Cases and steps API
Read, create and update test cases and their steps over the Qualflare REST API, including a bulk create of up to 20 cases, with every parameter and field.
Last updated
The Cases and steps API lets you read, create and update test cases and their steps in a Qualflare project over REST at https://api.qualflare.com/api/v1, authenticated with a project access token.
| Base path | /api/v1/suite/{suiteSeq}/cases, /api/v1/case/{caseSeq} and /api/v1/case/{caseSeq}/steps |
| Reads | Any token. Token creator: Viewer+ · project (requires the Viewer role or higher in the project) |
| Writes | Creating and updating cases and steps: a token created with Allow writes. Token creator: Editor+ · project (requires the Editor role or higher in the project) |
| Pages | None: a suite's cases and a case's steps come back whole |
| Limits | Rate limits and request sizes |
| Errors | Errors and status codes |
| CLI | qf <identifier> cases list --suite <seq>, qf <identifier> case get <seq>, qf <identifier> case steps <seq> (Cases commands) |
| MCP | list_suite_cases, get_test_case, list_case_steps, create_test_case, update_test_case, bulk_create_cases, create_case_step, update_case_step (MCP server reference) |
The eight endpoints, each with its own section below:
| Endpoint | What it does |
|---|---|
GET /api/v1/suite/{suiteSeq}/cases | List a suite's cases |
GET /api/v1/case/{caseSeq} | Get a case |
POST /api/v1/suite/{suiteSeq}/cases | Create a case |
PUT /api/v1/case/{caseSeq} | Update a case |
POST /api/v1/suite/{suiteSeq}/cases/bulk | Create cases in bulk |
GET /api/v1/case/{caseSeq}/steps | List a case's steps |
POST /api/v1/case/{caseSeq}/steps | Add a step |
PUT /api/v1/case/{caseSeq}/step/{id} | Update a step |
List a suite's cases
List a suite's cases returns every case of one suite that matches your filters.
GET /api/v1/suite/{suiteSeq}/cases
Needs a project access token whose creator has the Viewer role or higher in the project.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
suiteSeq | path, integer | Yes | The suite number | |
q | query, string | No | Text to look for in case names, up to 255 characters | |
state | query, string | No | A state: active, review, outdated or draft. Repeat it for more, up to 20 | |
priority | query, string | No | A priority: low, medium, high or critical. Repeat it for more, up to 10 | |
testType | query, string | No | A test type: unit, regression, integration, feature, e2e, component, contract, api, performance, ui, snapshot, accessibility, smoke, resilience, vulnerability, penetration, bdd, security, generic, junit, python, golang, jest, mocha, vitest, rspec, phpunit, testng, cucumber, karate, playwright, cypress, selenium, testcafe, maestro, xctest, espresso, webdriverio, appium, flutter, newman, k6, zap, trivy, snyk or sonarqube. Repeat it for more, up to 10 | |
sortBy | query, string | seq | No | seq, name, createdAt, updatedAt, flakyScore or position (the order in the suite) |
sortDir | query, boolean | false | No | true sorts in descending order |
curl -sS "https://api.qualflare.com/api/v1/suite/12/cases?state=active&state=draft" \
-H "Authorization: Bearer $QF_TOKEN"Returns 200: items and total: every matching case of the suite, with no pages.
- The answer is
itemsandtotal, every matching case in the suite, with no pages. suiteNameis empty in this list; Get a case fills it in.
Get a case
Get a case returns one test case by its number.
GET /api/v1/case/{caseSeq}
Needs a project access token whose creator has the Viewer role or higher in the project.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
caseSeq | path, integer | Yes | The case number |
curl -sS "https://api.qualflare.com/api/v1/case/101" \
-H "Authorization: Bearer $QF_TOKEN"Returns 200: The case.
{
"seq": 101,
"position": 4,
"uid": "User can apply a coupon at checkout",
"name": "User can apply a coupon at checkout",
"description": "A 10% coupon lowers the order total before tax.",
"state": "active",
"priority": "high",
"testType": "e2e",
"automation": "manual",
"isFavorite": false,
"isFlaky": false,
"flakyScore": 0,
"mark": "none",
"isArchived": false,
"suiteSeq": 12,
"suiteName": "Checkout",
"createdAt": "2026-09-14T08:40:12Z",
"updatedAt": "2026-10-21T16:05:57Z"
}- A number that isn't a case of the project answers
404withcase not found.
Create a case
Create a case adds a test case to a suite and sets only its name.
POST /api/v1/suite/{suiteSeq}/cases
Needs a project access token created with Allow writes, whose creator has the Editor role or higher in the project.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
suiteSeq | path, integer | Yes | The suite number | |
name | body, string | Yes | The case name, 1 to 255 characters, that no other case in the suite has |
curl -sS -X POST "https://api.qualflare.com/api/v1/suite/12/cases" \
-H "Authorization: Bearer $QF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "User can reset a forgotten password"}'Returns 201: The new case.
- Only
nameis set (1 to 255 characters); the case starts as a Draft, Low-priority, E2E, manual case. Set the rest with Update a case. - A name already in the suite answers
409. - Each case counts toward your plan's test cases; at the limit the API answers
402withTest Cases quota exceeded (<used>/<limit>).
Update a case
Update a case changes the name, description, state or priority of a test case.
PUT /api/v1/case/{caseSeq}
Needs a project access token created with Allow writes, whose creator has the Editor role or higher in the project.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
caseSeq | path, integer | Yes | The case number | |
name | body, string | No | Up to 255 characters | |
description | body, string | No | Up to 1,024 characters; longer text fails to save | |
state | body, string | No | active, review, outdated or draft | |
priority | body, string | No | low, medium, high or critical |
curl -sS -X PUT "https://api.qualflare.com/api/v1/case/101" \
-H "Authorization: Bearer $QF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"state": "active", "priority": "high"}'Returns 200: The updated case.
- Send only the fields to change:
name,description(up to 1,024 characters; longer text fails to save),state,priority. - A body with none of them changes nothing and returns the case.
Create cases in bulk
Create cases in bulk adds up to 20 test cases to one suite in one request.
POST /api/v1/suite/{suiteSeq}/cases/bulk
Needs a project access token created with Allow writes, whose creator has the Editor role or higher in the project.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
suiteSeq | path, integer | Yes | The suite number | |
cases | body, array | Yes | 1 to 20 cases, each a title of 5 to 255 characters, an optional description of up to 1,024 characters and an optional priority (default medium) |
curl -sS -X POST "https://api.qualflare.com/api/v1/suite/12/cases/bulk" \
-H "Authorization: Bearer $QF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"cases": [{"title": "Reset link expires after one hour", "priority": "high"}, {"title": "Reset link works only once"}]}'Returns 201: suiteSeq, count and caseSeqs, the numbers of the new cases.
- 1 to 20 cases, each with a
titleof 5 to 255 characters, an optionaldescription(up to 1,024 characters; longer text fails to save) and an optionalpriority(defaultmedium). They start as Draft, Unit, manual cases. - All or none: if the batch would pass your plan's test-case limit, nothing is created.
- The answer is
suiteSeq,countandcaseSeqs.
List a case's steps
List a case's steps returns an array of every step of the case, in order; a shared step carries sharedStep with its own items.
GET /api/v1/case/{caseSeq}/steps
Needs a project access token whose creator has the Viewer role or higher in the project.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
caseSeq | path, integer | Yes | The case number |
curl -sS "https://api.qualflare.com/api/v1/case/101/steps" \
-H "Authorization: Bearer $QF_TOKEN"Returns 200: An array of every step of the case, in order.
Add a step
Add a step appends a step to a test case.
POST /api/v1/case/{caseSeq}/steps
Needs a project access token created with Allow writes, whose creator has the Editor role or higher in the project.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
caseSeq | path, integer | Yes | The case number | |
instruction | body, string | Yes | The step text, up to 500 characters | |
stepType | body, string | action | No | precondition, action, expected_result, verification, navigation, api_request, data_input or cleanup |
parentId | body, integer | No | The id of a step to nest this one under | |
data | body, JSON | No | Any JSON value to keep with the step |
curl -sS -X POST "https://api.qualflare.com/api/v1/case/101/steps" \
-H "Authorization: Bearer $QF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"instruction": "Open the sign-in page", "stepType": "navigation"}'Returns 201: The new step.
instructionis required, up to 500 characters;stepTypedefaults toaction;parentIdnests the step under another;datais any JSON.
Update a step
Update a step changes the instruction, stepType or data you send.
PUT /api/v1/case/{caseSeq}/step/{id}
Needs a project access token created with Allow writes, whose creator has the Editor role or higher in the project.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
caseSeq | path, integer | Yes | The case number | |
id | path, integer | Yes | The step id | |
instruction | body, string | No | Up to 500 characters | |
stepType | body, string | No | precondition, action, expected_result, verification, navigation, api_request, data_input or cleanup | |
data | body, JSON | No | Any JSON value to keep with the step |
curl -sS -X PUT "https://api.qualflare.com/api/v1/case/101/step/7" \
-H "Authorization: Bearer $QF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"instruction": "Open /login"}'Returns 200: The updated step.
- A step
idthat isn't on the case answers404withstep not found.
A create can't be retried safely: if a POST succeeded but you didn't get the answer, a retry creates a second case or step.
Case fields
Every case the Cases and steps API returns has these fields:
| Field | Type | Notes |
|---|---|---|
seq | integer | The case number in the project |
position | integer | The case's place in its suite |
uid | string | The case's identifier: Create a case sets it to the name, and Create cases in bulk to a random UUID |
name | string | The case name |
description | string | Up to 1,024 characters, or null |
state | string | active, review, outdated or draft (Case states) |
priority | string | low, medium, high or critical |
testType | string | The kind of test, or the framework that reported it: a value of testType in List a suite's cases |
automation | string | manual or automated |
isFavorite | boolean | true for a favorite case |
isFlaky, flakyScore | boolean, number | Whether Qualflare flags the case as flaky, and its flaky score |
mark | string | none, redundant or low_value |
isArchived | boolean | true for an archived case |
archivedAt | string | When it was archived; left out unless archived |
suiteSeq, suiteName | integer, string | The case's suite |
createdAt, updatedAt | string | RFC 3339 timestamps |
Step fields
Every step in List a case's steps, and the step a write returns, has these fields:
| Field | Type | Notes |
|---|---|---|
id | integer | The step id, which Update a step takes |
instruction | string | The step text; left out when empty, as a shared step's can be |
data | JSON | The data kept with the step; left out when there is none |
stepType | string | precondition, action, expected_result, verification, navigation, api_request, data_input or cleanup; left out when empty |
position | integer | The step's place in the case |
origin | string | Who last wrote the step: manual, ai_generated or automated |
sharedStep | object | For a shared step: its seq, name and items, each item with id, instruction, data, stepType and position. Left out for other steps |
createdAt, updatedAt | string | RFC 3339 timestamps |
CLI and MCP equivalents
The qf CLI and the MCP server run the same reads, and the MCP server the same writes, so they return the same JSON:
| REST | qf command and MCP tool |
|---|---|
GET /api/v1/suite/{suiteSeq}/cases | qf <identifier> cases list --suite <seq>; list_suite_cases |
GET /api/v1/case/{caseSeq} | qf <identifier> case get <seq>; get_test_case |
POST /api/v1/suite/{suiteSeq}/cases | No qf command; create_test_case |
PUT /api/v1/case/{caseSeq} | No qf command; update_test_case |
POST /api/v1/suite/{suiteSeq}/cases/bulk | No qf command; bulk_create_cases |
GET /api/v1/case/{caseSeq}/steps | qf <identifier> case steps <seq>; list_case_steps |
POST /api/v1/case/{caseSeq}/steps | No qf command; create_case_step |
PUT /api/v1/case/{caseSeq}/step/{id} | No qf command; update_case_step |
Related
- Guides: Create and edit test cases
- Reference: Test cases: fields, states and steps · Suites API
- CLI/API: Qualflare API · Errors and status codes
Suites API
List and read the test suites of a Qualflare project over the REST API, analyze a suite's coverage and save its score, with every parameter and field.
Launches API
List and read the launches of a Qualflare project over the REST API and export a launch as a CTRF report, with filters, sorting and every launch field.