Skip to content
The docs are now organized by product area. Old links still work. Report a broken link

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
ReadsAny token. Token creator: Viewer+ · project (requires the Viewer role or higher in the project)
WritesCreating and updating cases and steps: a token created with Allow writes. Token creator: Editor+ · project (requires the Editor role or higher in the project)
PagesNone: a suite's cases and a case's steps come back whole
LimitsRate limits and request sizes
ErrorsErrors and status codes
CLIqf <identifier> cases list --suite <seq>, qf <identifier> case get <seq>, qf <identifier> case steps <seq> (Cases commands)
MCPlist_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:

EndpointWhat it does
GET /api/v1/suite/{suiteSeq}/casesList a suite's cases
GET /api/v1/case/{caseSeq}Get a case
POST /api/v1/suite/{suiteSeq}/casesCreate a case
PUT /api/v1/case/{caseSeq}Update a case
POST /api/v1/suite/{suiteSeq}/cases/bulkCreate cases in bulk
GET /api/v1/case/{caseSeq}/stepsList a case's steps
POST /api/v1/case/{caseSeq}/stepsAdd 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.

NameTypeDefaultRequiredDescription
suiteSeqpath, integerYesThe suite number
qquery, stringNoText to look for in case names, up to 255 characters
statequery, stringNoA state: active, review, outdated or draft. Repeat it for more, up to 20
priorityquery, stringNoA priority: low, medium, high or critical. Repeat it for more, up to 10
testTypequery, stringNoA 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
sortByquery, stringseqNoseq, name, createdAt, updatedAt, flakyScore or position (the order in the suite)
sortDirquery, booleanfalseNotrue 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 items and total, every matching case in the suite, with no pages.
  • suiteName is 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.

NameTypeDefaultRequiredDescription
caseSeqpath, integerYesThe 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 404 with case 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.

NameTypeDefaultRequiredDescription
suiteSeqpath, integerYesThe suite number
namebody, stringYesThe 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 name is 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 402 with Test 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.

NameTypeDefaultRequiredDescription
caseSeqpath, integerYesThe case number
namebody, stringNoUp to 255 characters
descriptionbody, stringNoUp to 1,024 characters; longer text fails to save
statebody, stringNoactive, review, outdated or draft
prioritybody, stringNolow, 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.

NameTypeDefaultRequiredDescription
suiteSeqpath, integerYesThe suite number
casesbody, arrayYes1 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 title of 5 to 255 characters, an optional description (up to 1,024 characters; longer text fails to save) and an optional priority (default medium). 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, count and caseSeqs.

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.

NameTypeDefaultRequiredDescription
caseSeqpath, integerYesThe 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.

NameTypeDefaultRequiredDescription
caseSeqpath, integerYesThe case number
instructionbody, stringYesThe step text, up to 500 characters
stepTypebody, stringactionNoprecondition, action, expected_result, verification, navigation, api_request, data_input or cleanup
parentIdbody, integerNoThe id of a step to nest this one under
databody, JSONNoAny 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.

  • instruction is required, up to 500 characters; stepType defaults to action; parentId nests the step under another; data is 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.

NameTypeDefaultRequiredDescription
caseSeqpath, integerYesThe case number
idpath, integerYesThe step id
instructionbody, stringNoUp to 500 characters
stepTypebody, stringNoprecondition, action, expected_result, verification, navigation, api_request, data_input or cleanup
databody, JSONNoAny 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 id that isn't on the case answers 404 with step 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:

FieldTypeNotes
seqintegerThe case number in the project
positionintegerThe case's place in its suite
uidstringThe case's identifier: Create a case sets it to the name, and Create cases in bulk to a random UUID
namestringThe case name
descriptionstringUp to 1,024 characters, or null
statestringactive, review, outdated or draft (Case states)
prioritystringlow, medium, high or critical
testTypestringThe kind of test, or the framework that reported it: a value of testType in List a suite's cases
automationstringmanual or automated
isFavoritebooleantrue for a favorite case
isFlaky, flakyScoreboolean, numberWhether Qualflare flags the case as flaky, and its flaky score
markstringnone, redundant or low_value
isArchivedbooleantrue for an archived case
archivedAtstringWhen it was archived; left out unless archived
suiteSeq, suiteNameinteger, stringThe case's suite
createdAt, updatedAtstringRFC 3339 timestamps

Step fields

Every step in List a case's steps, and the step a write returns, has these fields:

FieldTypeNotes
idintegerThe step id, which Update a step takes
instructionstringThe step text; left out when empty, as a shared step's can be
dataJSONThe data kept with the step; left out when there is none
stepTypestringprecondition, action, expected_result, verification, navigation, api_request, data_input or cleanup; left out when empty
positionintegerThe step's place in the case
originstringWho last wrote the step: manual, ai_generated or automated
sharedStepobjectFor a shared step: its seq, name and items, each item with id, instruction, data, stepType and position. Left out for other steps
createdAt, updatedAtstringRFC 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:

RESTqf command and MCP tool
GET /api/v1/suite/{suiteSeq}/casesqf <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}/casesNo qf command; create_test_case
PUT /api/v1/case/{caseSeq}No qf command; update_test_case
POST /api/v1/suite/{suiteSeq}/cases/bulkNo qf command; bulk_create_cases
GET /api/v1/case/{caseSeq}/stepsqf <identifier> case steps <seq>; list_case_steps
POST /api/v1/case/{caseSeq}/stepsNo qf command; create_case_step
PUT /api/v1/case/{caseSeq}/step/{id}No qf command; update_case_step