REST API reference

Test cases

A test case holds either traditional steps or a BDD (Gherkin) body. Steps are separate resources that carry their test case id, so you create the case first and its steps after. Test cases and steps are soft-deleted and can be restored.

List test cases

GET/api/v1/test_cases

Lists test case resources as a JSON:API collection document. Narrow the set with filter, order it with sort, embed related resources with include, select attributes with fields[<type>], and page with page[size] plus page[number] (offset) or page[after] (cursor, taken from the previous response's links.next).

Query parameters

filterstring
A FiltrQL expression, url-encoded. Combine conditions with AND / OR and parentheses. The fields you can filter on, and the operators each accepts, are listed under Filterable fields.
testCaseKey = "A-TC-1"
sortstring
Comma-separated sort fields; prefix a field with "-" for descending order (e.g. "-createdAt,title"). Permitted fields: id, organizationId, projectId, testCaseKey, status, name, rank, createdAt, updatedAt, folderId, priority, type, automationStatus, automationKey, formatMode, createdBy, ownerId, deletedAt, testCaseKeyNumeric.
-testCaseKey
includestring
Comma-separated relation names to include; dot-notation for nested includes (up to 3 levels deep). Permitted top-level relations: createdByUser, testCaseFolder, formatModeChangedByUser, organization, ownerUser, project, updatedByUser.
createdByUser
fields[test_cases]string[]
Sparse fieldset for resource type "test_cases" - comma-separated subset of its exposed fields: id, organizationId, projectId, testCaseKey, status, name, description, version, rank, preconditions, expectedResults, plannedTime, createdAt, updatedAt, folderId, priority, objective, type, automationStatus, automationKey, formatMode, formatModeChangedAt, formatModeChangedBy, createdBy, updatedBy, ownerId, deletedAt, testCaseKeyNumeric, createdByUser, formatModeChangedByUser, ownerUser, updatedByUser, testCaseFolder, organization, project, customFields.
testCaseKey,status,name
page[size]integer
Number of resources per page (applies to both offset and cursor pagination). Minimum 1, maximum 100, default 25 when omitted.
25
page[number]integer
1-indexed page number for offset-based pagination. Mutually exclusive with "page[after]" - supplying both is rejected with a 400 (CONFLICTING_PAGINATION).
2
page[after]string
Opaque cursor for cursor-based pagination - always taken verbatim from a previous response's "links.next" value, never client-constructed or decoded. Mutually exclusive with "page[number]" - supplying both is rejected with a 400 (CONFLICTING_PAGINATION).
withDeletedboolean
Include soft-deleted rows in the collection. Only present on soft-delete-enabled entities. Default false (soft-deleted rows excluded) when omitted.

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json

Filterable fields28

Show fields and operators
FieldTypeOperators
iduuid= != in (…) not in (…) is null is not null
organizationIduuid= != in (…) not in (…) is null is not null
projectIduuid= != in (…) not in (…) is null is not null
testCaseKeystring= != in (…) not in (…) ~ is null is not null
statusenum= != in (…) not in (…) is null is not nullDRAFT, IN_REVIEW, CHANGE_NEEDED, ACTIVE, ARCHIVED
namestring~ is null is not null is empty is not empty
descriptionstring~ is null is not null is empty is not empty
versionint= != < <= > >= in (…) not in (…) is null is not null
rankint= != < <= > >= in (…) not in (…) is null is not null
preconditionsstring~ is null is not null is empty is not empty
expectedResultsstring~ is null is not null is empty is not empty
plannedTimeint= != < <= > >= in (…) not in (…) is null is not null
createdAtdatetime= != < <= > >= is null is not null
updatedAtdatetime= != < <= > >= is null is not null
folderIduuid= != in (…) not in (…) is null is not null
priorityenum= != < <= > >= in (…) not in (…) is null is not nullCRITICAL, HIGH, MEDIUM, LOW
objectivestring~ is null is not null is empty is not empty
typeenum= != in (…) not in (…) is null is not nullFUNCTIONAL, INTEGRATION, REGRESSION, SMOKE, PERFORMANCE, SECURITY, USABILITY, EXPLORATORY
automationStatusenum= != in (…) not in (…) is null is not nullMANUAL, AUTOMATED, TO_BE_AUTOMATED, NOT_AUTOMATABLE
automationKeystring= != in (…) not in (…) is null is not null
formatModeenum= != in (…) not in (…) is null is not nullTRADITIONAL, BDD
formatModeChangedAtdatetime= != < <= > >= is null is not null
formatModeChangedByuuid= != in (…) not in (…) is null is not null
createdByuuid= != in (…) not in (…) is null is not null
updatedByuuid= != in (…) not in (…) is null is not null
ownerIduuid= != in (…) not in (…) is null is not null
deletedAtdatetime= != < <= > >= is null is not null
testCaseKeyNumericint= != < <= > >= in (…) not in (…) is null is not null

Filter through a relation with ANY, ALL or NONE, for example testCaseExecutions ANY (id = "…"). Relations: testCaseExecutions, createdByUser, testCaseFolder, formatModeChangedByUser, organization, ownerUser, project, updatedByUser, testCollectionTestCases, testSteps.

Returns the same attributes as Get a test case.

Responses

  • 200Success.
11 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INVALID_TYPED_JSON_FILTERUNKNOWN_SORT_FIELDINCLUDE_DEPTH_EXCEEDEDUNKNOWN_RELATIONINCLUDE_RESOURCES_EXCEEDEDUNKNOWN_TYPEUNKNOWN_FIELDCONFLICTING_PAGINATIONINVALID_PAGE_SIZEPAGE_SIZE_EXCEEDEDINVALID_PAGE_NUMBERINPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_cases?page%5Bsize%5D=25" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": [
    {
      "type": "test_cases",
      "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
      "attributes": {
        "name": "Checkout rejects an expired card",
        "testCaseKey": "KAN-TC-42",
        "status": "ACTIVE",
        "priority": "HIGH",
        "automationKey": "checkout.spec.ts:expired-card",
        "updatedAt": "2026-10-05T09:30:00Z"
      },
      "links": {
        "self": "/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
      }
    }
  ],
  "links": {
    "self": "/test_cases?page[size]=25",
    "first": "/test_cases?page[size]=25&page[number]=1",
    "prev": null,
    "next": "/test_cases?page[size]=25&page[number]=2",
    "last": "/test_cases?page[size]=25&page[number]=6"
  },
  "meta": {
    "totalCount": 128
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Create a test case

POST/api/v1/test_cases

Creates a test case from a JSON:API resource object - data.type names the resource type and data.attributes carries the writable attributes - and returns the created resource.

Needs a read-and-write token. A read-only token gets 403.

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
Content-Typestringrequired
Must be application/vnd.api+json on any request with a body. Anything else returns 415 Unsupported Media Type.
application/vnd.api+json

Attributes you can send17

namestringrequired
projectIduuidrequired
rankintegerrequired
automationKeystring | null
automationStatusstring | nulldefault MANUAL
MANUALAUTOMATEDTO_BE_AUTOMATEDNOT_AUTOMATABLE
customFieldsobject
descriptionstring | nullmax 5000 chars
expectedResultsstring | null
Show the remaining 9
folderIduuid | null
formatModestringdefault TRADITIONAL
TRADITIONALBDD
objectivestring | nullmax 2000 chars
ownerIduuid | null
plannedTimeinteger | null
preconditionsstring | nullmax 2000 chars
prioritystring | nulldefault MEDIUM
CRITICALHIGHMEDIUMLOW
statusstringdefault DRAFT
DRAFTIN_REVIEWCHANGE_NEEDEDACTIVEARCHIVED
typestring | nulldefault FUNCTIONAL
FUNCTIONALINTEGRATIONREGRESSIONSMOKEPERFORMANCESECURITYUSABILITYEXPLORATORY

Returns the same attributes as Get a test case.

Responses

  • 201Created.
11 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 415The Content-Type was not application/vnd.api+json.MISSING_CONTENT_TYPEINVALID_CONTENT_TYPEINVALID_CONTENT_TYPE_PARAMSPARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.INVALID_INPUTVALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_cases" \
  -X POST \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
  "data": {
    "type": "test_cases",
    "attributes": {
      "name": "Checkout rejects an expired card",
      "projectId": "03ff802c-4fcb-4718-8eb8-12ecc999f758",
      "rank": 1,
      "status": "ACTIVE"
    }
  }
}'
Response

application/vnd.api+json

{
  "data": [
    {
      "type": "test_cases",
      "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
      "attributes": {
        "name": "Checkout rejects an expired card",
        "testCaseKey": "KAN-TC-42",
        "status": "ACTIVE",
        "priority": "HIGH",
        "automationKey": "checkout.spec.ts:expired-card",
        "updatedAt": "2026-10-05T09:30:00Z"
      },
      "links": {
        "self": "/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
      }
    }
  ],
  "links": {
    "self": "/test_cases?page[size]=25",
    "first": "/test_cases?page[size]=25&page[number]=1",
    "prev": null,
    "next": "/test_cases?page[size]=25&page[number]=2",
    "last": "/test_cases?page[size]=25&page[number]=6"
  },
  "meta": {
    "totalCount": 128
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Count and aggregate test cases

GET/api/v1/test_cases/aggregate

Aggregates test case resources - a count and per-column aggregations, optionally grouped - over the same filter the collection route accepts.

Query parameters

aggregations[count]boolean
Include the row count in the aggregate result. When no aggregation is requested at all, the runtime defaults to count.
aggregations[sum][]string[]
Column(s) to sum - repeat the bracketed key per column (aggregations[sum][]=a&aggregations[sum][]=b). Permitted columns: version, rank, plannedTime, testCaseKeyNumeric.
aggregations[avg][]string[]
Column(s) to average - repeat the bracketed key per column (aggregations[avg][]=a&aggregations[avg][]=b). Permitted columns: version, rank, plannedTime, testCaseKeyNumeric.
aggregations[min][]string[]
Column(s) to take the minimum of - repeat the bracketed key per column (aggregations[min][]=a&aggregations[min][]=b). Permitted columns: testCaseKey, name, description, version, rank, preconditions, expectedResults, plannedTime, createdAt, updatedAt, objective, automationKey, formatModeChangedAt, deletedAt, testCaseKeyNumeric.
aggregations[max][]string[]
Column(s) to take the maximum of - repeat the bracketed key per column (aggregations[max][]=a&aggregations[max][]=b). Permitted columns: testCaseKey, name, description, version, rank, preconditions, expectedResults, plannedTime, createdAt, updatedAt, objective, automationKey, formatModeChangedAt, deletedAt, testCaseKeyNumeric.
aggregations[groupBy][]string[]
Column(s) to group by - repeating the bracketed key switches the response to the grouped shape (aggregations[groupBy][]=a&aggregations[groupBy][]=b). Permitted columns: id, organizationId, projectId, testCaseKey, status, name, rank, createdAt, updatedAt, folderId, priority, type, automationStatus, automationKey, formatMode, createdBy, ownerId, deletedAt, testCaseKeyNumeric.
filterstring
A FiltrQL expression, url-encoded. Combine conditions with AND / OR and parentheses. The fields you can filter on, and the operators each accepts, are listed under Filterable fields.
testCaseKey = "A-TC-1"

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json

Filterable fields28

Show fields and operators
FieldTypeOperators
iduuid= != in (…) not in (…) is null is not null
organizationIduuid= != in (…) not in (…) is null is not null
projectIduuid= != in (…) not in (…) is null is not null
testCaseKeystring= != in (…) not in (…) ~ is null is not null
statusenum= != in (…) not in (…) is null is not nullDRAFT, IN_REVIEW, CHANGE_NEEDED, ACTIVE, ARCHIVED
namestring~ is null is not null is empty is not empty
descriptionstring~ is null is not null is empty is not empty
versionint= != < <= > >= in (…) not in (…) is null is not null
rankint= != < <= > >= in (…) not in (…) is null is not null
preconditionsstring~ is null is not null is empty is not empty
expectedResultsstring~ is null is not null is empty is not empty
plannedTimeint= != < <= > >= in (…) not in (…) is null is not null
createdAtdatetime= != < <= > >= is null is not null
updatedAtdatetime= != < <= > >= is null is not null
folderIduuid= != in (…) not in (…) is null is not null
priorityenum= != < <= > >= in (…) not in (…) is null is not nullCRITICAL, HIGH, MEDIUM, LOW
objectivestring~ is null is not null is empty is not empty
typeenum= != in (…) not in (…) is null is not nullFUNCTIONAL, INTEGRATION, REGRESSION, SMOKE, PERFORMANCE, SECURITY, USABILITY, EXPLORATORY
automationStatusenum= != in (…) not in (…) is null is not nullMANUAL, AUTOMATED, TO_BE_AUTOMATED, NOT_AUTOMATABLE
automationKeystring= != in (…) not in (…) is null is not null
formatModeenum= != in (…) not in (…) is null is not nullTRADITIONAL, BDD
formatModeChangedAtdatetime= != < <= > >= is null is not null
formatModeChangedByuuid= != in (…) not in (…) is null is not null
createdByuuid= != in (…) not in (…) is null is not null
updatedByuuid= != in (…) not in (…) is null is not null
ownerIduuid= != in (…) not in (…) is null is not null
deletedAtdatetime= != < <= > >= is null is not null
testCaseKeyNumericint= != < <= > >= in (…) not in (…) is null is not null

Filter through a relation with ANY, ALL or NONE, for example testCaseExecutions ANY (id = "…"). Relations: testCaseExecutions, createdByUser, testCaseFolder, formatModeChangedByUser, organization, ownerUser, project, updatedByUser, testCollectionTestCases, testSteps.

Responses

  • 200Success.
11 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_cases/aggregate?aggregations%5Bcount%5D=true" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": {
    "type": "testCases_aggregate",
    "id": "(aggregate)",
    "attributes": {
      "count": 128
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Get a test case

GET/api/v1/test_cases/{id}

Returns the test case with this id as a JSON:API resource document; include embeds related resources and fields[<type>] selects the attributes returned.

Path parameters

iduuidrequired
The resource id (a UUID).

Query parameters

includestring
Comma-separated relation names to include; dot-notation for nested includes (up to 3 levels deep). Permitted top-level relations: createdByUser, testCaseFolder, formatModeChangedByUser, organization, ownerUser, project, updatedByUser.
createdByUser
fields[test_cases]string[]
Sparse fieldset for resource type "test_cases" - comma-separated subset of its exposed fields: id, organizationId, projectId, testCaseKey, status, name, description, version, rank, preconditions, expectedResults, plannedTime, createdAt, updatedAt, folderId, priority, objective, type, automationStatus, automationKey, formatMode, formatModeChangedAt, formatModeChangedBy, createdBy, updatedBy, ownerId, deletedAt, testCaseKeyNumeric, createdByUser, formatModeChangedByUser, ownerUser, updatedByUser, testCaseFolder, organization, project, customFields.
testCaseKey,status,name

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json

Attributes returned29

automationKeystring | null
automationStatusstring | nulldefault MANUAL
MANUALAUTOMATEDTO_BE_AUTOMATEDNOT_AUTOMATABLE
createdAtdate-timeread-only
createdByuuid | nullread-only
customFieldsobject
deletedAtdate-time | nullread-only
descriptionstring | nullmax 5000 chars
expectedResultsstring | null
Show the remaining 21
folderIduuid | null
formatModestringread-onlydefault TRADITIONAL
TRADITIONALBDD
formatModeChangedAtdate-time | nullread-only
formatModeChangedByuuid | nullread-only
iduuidread-only
namestring
objectivestring | nullmax 2000 chars
organizationIduuidread-only
ownerIduuid | null
plannedTimeinteger | null
preconditionsstring | nullmax 2000 chars
prioritystring | nulldefault MEDIUM
CRITICALHIGHMEDIUMLOW
projectIduuid
rankinteger
statusstringdefault DRAFT
DRAFTIN_REVIEWCHANGE_NEEDEDACTIVEARCHIVED
testCaseKeystringread-only
testCaseKeyNumericinteger | nullread-only
typestring | nulldefault FUNCTIONAL
FUNCTIONALINTEGRATIONREGRESSIONSMOKEPERFORMANCESECURITYUSABILITYEXPLORATORY
updatedAtdate-timeread-only
updatedByuuid | nullread-only
versionintegerread-onlydefault 1

Responses

  • 200Success.
12 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.UNKNOWN_TYPEUNKNOWN_FIELDINCLUDE_DEPTH_EXCEEDEDUNKNOWN_RELATIONINCLUDE_RESOURCES_EXCEEDEDINPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 410Gone.GONE
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": {
    "type": "test_cases",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "name": "Checkout rejects an expired card",
      "testCaseKey": "KAN-TC-42",
      "status": "ACTIVE",
      "priority": "HIGH",
      "automationKey": "checkout.spec.ts:expired-card",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Update a test case

PATCH/api/v1/test_cases/{id}

Updates the test case with this id from a JSON:API resource object carrying only the attributes to change, and returns the updated resource. A resource that carries an ETag requires it back as If-Match.

Needs a read-and-write token. A read-only token gets 403.

Version-locked: send the ETag from your last read as If-Match.

Path parameters

iduuidrequired
The resource id (a UUID).

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
Content-Typestringrequired
Must be application/vnd.api+json on any request with a body. Anything else returns 415 Unsupported Media Type.
application/vnd.api+json
If-Matchstringrequired
The ETag from your last read of this resource, sent back verbatim. Missing returns 428 Precondition Required; stale (someone changed it since you read it) returns 412 Precondition Failed. Read it again and retry.
W/"3"

Attributes you can send16

automationKeystring | null
automationStatusstring | nulldefault MANUAL
MANUALAUTOMATEDTO_BE_AUTOMATEDNOT_AUTOMATABLE
customFieldsobject
descriptionstring | nullmax 5000 chars
expectedResultsstring | null
folderIduuid | null
namestring
objectivestring | nullmax 2000 chars
Show the remaining 8
ownerIduuid | null
plannedTimeinteger | null
preconditionsstring | nullmax 2000 chars
prioritystring | nulldefault MEDIUM
CRITICALHIGHMEDIUMLOW
projectIduuid
rankinteger
statusstringdefault DRAFT
DRAFTIN_REVIEWCHANGE_NEEDEDACTIVEARCHIVED
typestring | nulldefault FUNCTIONAL
FUNCTIONALINTEGRATIONREGRESSIONSMOKEPERFORMANCESECURITYUSABILITYEXPLORATORY

Returns the same attributes as Get a test case.

Responses

  • 200Success.
13 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 412The If-Match ETag is stale: the resource changed since you read it. Read it again and retry.STALE_OBJECT
  • 415The Content-Type was not application/vnd.api+json.MISSING_CONTENT_TYPEINVALID_CONTENT_TYPEINVALID_CONTENT_TYPE_PARAMSPARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_ERRORVALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 428This resource is version-locked: send its ETag in an If-Match header.MISSING_IF_MATCH
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33" \
  -X PATCH \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H 'If-Match: W/"3"' \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
  "data": {
    "type": "test_cases",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "status": "ACTIVE"
    }
  }
}'
Response

application/vnd.api+json

{
  "data": {
    "type": "test_cases",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "name": "Checkout rejects an expired card",
      "testCaseKey": "KAN-TC-42",
      "status": "ACTIVE",
      "priority": "HIGH",
      "automationKey": "checkout.spec.ts:expired-card",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Delete a test case

DEL/api/v1/test_cases/{id}

Deletes the test case with this id.

Needs a read-and-write token. A read-only token gets 403.

Version-locked: send the ETag from your last read as If-Match.

Path parameters

iduuidrequired
The resource id (a UUID).

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
If-Matchstringrequired
The ETag from your last read of this resource, sent back verbatim. Missing returns 428 Precondition Required; stale (someone changed it since you read it) returns 412 Precondition Failed. Read it again and retry.
W/"3"

Returns the same attributes as Get a test case.

Responses

  • 200Success.
13 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 412The If-Match ETag is stale: the resource changed since you read it. Read it again and retry.STALE_OBJECT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 428This resource is version-locked: send its ETag in an If-Match header.MISSING_IF_MATCH
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33" \
  -X DELETE \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H 'If-Match: W/"3"'
Response

application/vnd.api+json

{
  "data": {
    "type": "test_cases",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "name": "Checkout rejects an expired card",
      "testCaseKey": "KAN-TC-42",
      "status": "ACTIVE",
      "priority": "HIGH",
      "automationKey": "checkout.spec.ts:expired-card",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Restore a test case

POST/api/v1/test_cases/{id}/actions/restore

Restores the soft-deleted test case with this id and returns it.

Needs a read-and-write token. A read-only token gets 403.

Version-locked: send the ETag from your last read as If-Match.

Path parameters

iduuidrequired
The resource id (a UUID).

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
If-Matchstringrequired
The ETag from your last read of this resource, sent back verbatim. Missing returns 428 Precondition Required; stale (someone changed it since you read it) returns 412 Precondition Failed. Read it again and retry.
W/"3"

Returns the same attributes as Get a test case.

Responses

  • 200Success.
13 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 412The If-Match ETag is stale: the resource changed since you read it. Read it again and retry.STALE_OBJECT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 428This resource is version-locked: send its ETag in an If-Match header.MISSING_IF_MATCH
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33/actions/restore" \
  -X POST \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H 'If-Match: W/"3"'
Response

application/vnd.api+json

{
  "data": {
    "type": "test_cases",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "name": "Checkout rejects an expired card",
      "testCaseKey": "KAN-TC-42",
      "status": "ACTIVE",
      "priority": "HIGH",
      "automationKey": "checkout.spec.ts:expired-card",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_cases/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

List test steps

GET/api/v1/test_steps

Lists test step resources as a JSON:API collection document. Narrow the set with filter, order it with sort, embed related resources with include, select attributes with fields[<type>], and page with page[size] plus page[number] (offset) or page[after] (cursor, taken from the previous response's links.next).

Query parameters

filterstring
A FiltrQL expression, url-encoded. Combine conditions with AND / OR and parentheses. The fields you can filter on, and the operators each accepts, are listed under Filterable fields.
sequenceNumber = 1
sortstring
Comma-separated sort fields; prefix a field with "-" for descending order (e.g. "-createdAt,title"). Permitted fields: id, organizationId, testCaseId, sequenceNumber, version, deletedAt.
-sequenceNumber
includestring
Comma-separated relation names to include; dot-notation for nested includes (up to 3 levels deep). Permitted top-level relations: createdByUser, organization, project, testCase, updatedByUser.
createdByUser
fields[test_steps]string[]
Sparse fieldset for resource type "test_steps" - comma-separated subset of its exposed fields: id, organizationId, projectId, testCaseId, sequenceNumber, action, testData, expectedResult, bddContent, version, createdAt, updatedAt, createdBy, updatedBy, deletedAt, createdByUser, updatedByUser, organization, project, testCase.
sequenceNumber,action,testData
page[size]integer
Number of resources per page (applies to both offset and cursor pagination). Minimum 1, maximum 100, default 25 when omitted.
25
page[number]integer
1-indexed page number for offset-based pagination. Mutually exclusive with "page[after]" - supplying both is rejected with a 400 (CONFLICTING_PAGINATION).
2
page[after]string
Opaque cursor for cursor-based pagination - always taken verbatim from a previous response's "links.next" value, never client-constructed or decoded. Mutually exclusive with "page[number]" - supplying both is rejected with a 400 (CONFLICTING_PAGINATION).
withDeletedboolean
Include soft-deleted rows in the collection. Only present on soft-delete-enabled entities. Default false (soft-deleted rows excluded) when omitted.

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json

Filterable fields15

Show fields and operators
FieldTypeOperators
iduuid= != in (…) not in (…) is null is not null
organizationIduuid= != in (…) not in (…) is null is not null
projectIduuid= != in (…) not in (…) is null is not null
testCaseIduuid= != in (…) not in (…) is null is not null
sequenceNumberint= != < <= > >= in (…) not in (…) is null is not null
actionstring~ is null is not null is empty is not empty
testDatastring~ is null is not null is empty is not empty
expectedResultstring~ is null is not null is empty is not empty
bddContentstring~ is null is not null is empty is not empty
versionint= != < <= > >= in (…) not in (…) is null is not null
createdAtdatetime= != < <= > >= is null is not null
updatedAtdatetime= != < <= > >= is null is not null
createdByuuid= != in (…) not in (…) is null is not null
updatedByuuid= != in (…) not in (…) is null is not null
deletedAtdatetime= != < <= > >= is null is not null

Filter through a relation with ANY, ALL or NONE, for example testStepExecutions ANY (id = "…"). Relations: testStepExecutions, createdByUser, organization, project, testCase, updatedByUser.

Returns the same attributes as Get a test step.

Responses

  • 200Success.
11 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INVALID_TYPED_JSON_FILTERUNKNOWN_SORT_FIELDINCLUDE_DEPTH_EXCEEDEDUNKNOWN_RELATIONINCLUDE_RESOURCES_EXCEEDEDUNKNOWN_TYPEUNKNOWN_FIELDCONFLICTING_PAGINATIONINVALID_PAGE_SIZEPAGE_SIZE_EXCEEDEDINVALID_PAGE_NUMBERINPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_steps?page%5Bsize%5D=25" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": [
    {
      "type": "test_steps",
      "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
      "attributes": {
        "action": "Pay with a card that expired last month",
        "expectedResult": "Payment is refused with a clear message",
        "updatedAt": "2026-10-05T09:30:00Z"
      },
      "links": {
        "self": "/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
      }
    }
  ],
  "links": {
    "self": "/test_steps?page[size]=25",
    "first": "/test_steps?page[size]=25&page[number]=1",
    "prev": null,
    "next": "/test_steps?page[size]=25&page[number]=2",
    "last": "/test_steps?page[size]=25&page[number]=6"
  },
  "meta": {
    "totalCount": 128
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Create a test step

POST/api/v1/test_steps

Creates a test step from a JSON:API resource object - data.type names the resource type and data.attributes carries the writable attributes - and returns the created resource.

Needs a read-and-write token. A read-only token gets 403.

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
Content-Typestringrequired
Must be application/vnd.api+json on any request with a body. Anything else returns 415 Unsupported Media Type.
application/vnd.api+json

Attributes you can send7

projectIduuidrequired
sequenceNumberintegerrequired
testCaseIduuidrequired
actionstring | nullmax 5000 chars
bddContentstring | nullmax 10000 chars
expectedResultstring | nullmax 5000 chars
testDatastring | nullmax 5000 chars

Returns the same attributes as Get a test step.

Responses

  • 201Created.
11 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 415The Content-Type was not application/vnd.api+json.MISSING_CONTENT_TYPEINVALID_CONTENT_TYPEINVALID_CONTENT_TYPE_PARAMSPARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.INVALID_INPUTVALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_steps" \
  -X POST \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
  "data": {
    "type": "test_steps",
    "attributes": {
      "projectId": "03ff802c-4fcb-4718-8eb8-12ecc999f758",
      "sequenceNumber": 1,
      "testCaseId": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
      "action": "Pay with a card that expired last month"
    }
  }
}'
Response

application/vnd.api+json

{
  "data": [
    {
      "type": "test_steps",
      "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
      "attributes": {
        "action": "Pay with a card that expired last month",
        "expectedResult": "Payment is refused with a clear message",
        "updatedAt": "2026-10-05T09:30:00Z"
      },
      "links": {
        "self": "/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
      }
    }
  ],
  "links": {
    "self": "/test_steps?page[size]=25",
    "first": "/test_steps?page[size]=25&page[number]=1",
    "prev": null,
    "next": "/test_steps?page[size]=25&page[number]=2",
    "last": "/test_steps?page[size]=25&page[number]=6"
  },
  "meta": {
    "totalCount": 128
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Count and aggregate test steps

GET/api/v1/test_steps/aggregate

Aggregates test step resources - a count and per-column aggregations, optionally grouped - over the same filter the collection route accepts.

Query parameters

aggregations[count]boolean
Include the row count in the aggregate result. When no aggregation is requested at all, the runtime defaults to count.
aggregations[sum][]string[]
Column(s) to sum - repeat the bracketed key per column (aggregations[sum][]=a&aggregations[sum][]=b). Permitted columns: sequenceNumber, version.
aggregations[avg][]string[]
Column(s) to average - repeat the bracketed key per column (aggregations[avg][]=a&aggregations[avg][]=b). Permitted columns: sequenceNumber, version.
aggregations[min][]string[]
Column(s) to take the minimum of - repeat the bracketed key per column (aggregations[min][]=a&aggregations[min][]=b). Permitted columns: sequenceNumber, action, testData, expectedResult, bddContent, version, createdAt, updatedAt, deletedAt.
aggregations[max][]string[]
Column(s) to take the maximum of - repeat the bracketed key per column (aggregations[max][]=a&aggregations[max][]=b). Permitted columns: sequenceNumber, action, testData, expectedResult, bddContent, version, createdAt, updatedAt, deletedAt.
aggregations[groupBy][]string[]
Column(s) to group by - repeating the bracketed key switches the response to the grouped shape (aggregations[groupBy][]=a&aggregations[groupBy][]=b). Permitted columns: id, organizationId, testCaseId, sequenceNumber, version, deletedAt.
filterstring
A FiltrQL expression, url-encoded. Combine conditions with AND / OR and parentheses. The fields you can filter on, and the operators each accepts, are listed under Filterable fields.
sequenceNumber = 1

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json

Filterable fields15

Show fields and operators
FieldTypeOperators
iduuid= != in (…) not in (…) is null is not null
organizationIduuid= != in (…) not in (…) is null is not null
projectIduuid= != in (…) not in (…) is null is not null
testCaseIduuid= != in (…) not in (…) is null is not null
sequenceNumberint= != < <= > >= in (…) not in (…) is null is not null
actionstring~ is null is not null is empty is not empty
testDatastring~ is null is not null is empty is not empty
expectedResultstring~ is null is not null is empty is not empty
bddContentstring~ is null is not null is empty is not empty
versionint= != < <= > >= in (…) not in (…) is null is not null
createdAtdatetime= != < <= > >= is null is not null
updatedAtdatetime= != < <= > >= is null is not null
createdByuuid= != in (…) not in (…) is null is not null
updatedByuuid= != in (…) not in (…) is null is not null
deletedAtdatetime= != < <= > >= is null is not null

Filter through a relation with ANY, ALL or NONE, for example testStepExecutions ANY (id = "…"). Relations: testStepExecutions, createdByUser, organization, project, testCase, updatedByUser.

Responses

  • 200Success.
11 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_steps/aggregate?aggregations%5Bcount%5D=true" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": {
    "type": "testSteps_aggregate",
    "id": "(aggregate)",
    "attributes": {
      "count": 128
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Get a test step

GET/api/v1/test_steps/{id}

Returns the test step with this id as a JSON:API resource document; include embeds related resources and fields[<type>] selects the attributes returned.

Path parameters

iduuidrequired
The resource id (a UUID).

Query parameters

includestring
Comma-separated relation names to include; dot-notation for nested includes (up to 3 levels deep). Permitted top-level relations: createdByUser, organization, project, testCase, updatedByUser.
createdByUser
fields[test_steps]string[]
Sparse fieldset for resource type "test_steps" - comma-separated subset of its exposed fields: id, organizationId, projectId, testCaseId, sequenceNumber, action, testData, expectedResult, bddContent, version, createdAt, updatedAt, createdBy, updatedBy, deletedAt, createdByUser, updatedByUser, organization, project, testCase.
sequenceNumber,action,testData

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json

Attributes returned15

actionstring | nullmax 5000 chars
bddContentstring | nullmax 10000 chars
createdAtdate-timeread-only
createdByuuid | nullread-only
deletedAtdate-time | nullread-only
expectedResultstring | nullmax 5000 chars
iduuidread-only
organizationIduuidread-only
Show the remaining 7
projectIduuid
sequenceNumberinteger
testCaseIduuidread-only
testDatastring | nullmax 5000 chars
updatedAtdate-timeread-only
updatedByuuid | nullread-only
versionintegerread-onlydefault 1

Responses

  • 200Success.
12 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.UNKNOWN_TYPEUNKNOWN_FIELDINCLUDE_DEPTH_EXCEEDEDUNKNOWN_RELATIONINCLUDE_RESOURCES_EXCEEDEDINPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 410Gone.GONE
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": {
    "type": "test_steps",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "action": "Pay with a card that expired last month",
      "expectedResult": "Payment is refused with a clear message",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Update a test step

PATCH/api/v1/test_steps/{id}

Updates the test step with this id from a JSON:API resource object carrying only the attributes to change, and returns the updated resource. A resource that carries an ETag requires it back as If-Match.

Needs a read-and-write token. A read-only token gets 403.

Version-locked: send the ETag from your last read as If-Match.

Path parameters

iduuidrequired
The resource id (a UUID).

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
Content-Typestringrequired
Must be application/vnd.api+json on any request with a body. Anything else returns 415 Unsupported Media Type.
application/vnd.api+json
If-Matchstringrequired
The ETag from your last read of this resource, sent back verbatim. Missing returns 428 Precondition Required; stale (someone changed it since you read it) returns 412 Precondition Failed. Read it again and retry.
W/"3"

Attributes you can send6

actionstring | nullmax 5000 chars
bddContentstring | nullmax 10000 chars
expectedResultstring | nullmax 5000 chars
projectIduuid
sequenceNumberinteger
testDatastring | nullmax 5000 chars

Returns the same attributes as Get a test step.

Responses

  • 200Success.
13 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 412The If-Match ETag is stale: the resource changed since you read it. Read it again and retry.STALE_OBJECT
  • 415The Content-Type was not application/vnd.api+json.MISSING_CONTENT_TYPEINVALID_CONTENT_TYPEINVALID_CONTENT_TYPE_PARAMSPARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_ERRORVALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 428This resource is version-locked: send its ETag in an If-Match header.MISSING_IF_MATCH
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33" \
  -X PATCH \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H 'If-Match: W/"3"' \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
  "data": {
    "type": "test_steps",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "action": "Pay with a card that expired last month"
    }
  }
}'
Response

application/vnd.api+json

{
  "data": {
    "type": "test_steps",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "action": "Pay with a card that expired last month",
      "expectedResult": "Payment is refused with a clear message",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Delete a test step

DEL/api/v1/test_steps/{id}

Deletes the test step with this id.

Needs a read-and-write token. A read-only token gets 403.

Version-locked: send the ETag from your last read as If-Match.

Path parameters

iduuidrequired
The resource id (a UUID).

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
If-Matchstringrequired
The ETag from your last read of this resource, sent back verbatim. Missing returns 428 Precondition Required; stale (someone changed it since you read it) returns 412 Precondition Failed. Read it again and retry.
W/"3"

Returns the same attributes as Get a test step.

Responses

  • 200Success.
13 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 412The If-Match ETag is stale: the resource changed since you read it. Read it again and retry.STALE_OBJECT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 428This resource is version-locked: send its ETag in an If-Match header.MISSING_IF_MATCH
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33" \
  -X DELETE \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H 'If-Match: W/"3"'
Response

application/vnd.api+json

{
  "data": {
    "type": "test_steps",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "action": "Pay with a card that expired last month",
      "expectedResult": "Payment is refused with a clear message",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Restore a test step

POST/api/v1/test_steps/{id}/actions/restore

Restores the soft-deleted test step with this id and returns it.

Needs a read-and-write token. A read-only token gets 403.

Version-locked: send the ETag from your last read as If-Match.

Path parameters

iduuidrequired
The resource id (a UUID).

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
If-Matchstringrequired
The ETag from your last read of this resource, sent back verbatim. Missing returns 428 Precondition Required; stale (someone changed it since you read it) returns 412 Precondition Failed. Read it again and retry.
W/"3"

Returns the same attributes as Get a test step.

Responses

  • 200Success.
13 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 412The If-Match ETag is stale: the resource changed since you read it. Read it again and retry.STALE_OBJECT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 428This resource is version-locked: send its ETag in an If-Match header.MISSING_IF_MATCH
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33/actions/restore" \
  -X POST \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H 'If-Match: W/"3"'
Response

application/vnd.api+json

{
  "data": {
    "type": "test_steps",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "action": "Pay with a card that expired last month",
      "expectedResult": "Payment is refused with a clear message",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_steps/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

List test case folders

GET/api/v1/test_case_folders

Lists test case folder resources as a JSON:API collection document. Narrow the set with filter, order it with sort, embed related resources with include, select attributes with fields[<type>], and page with page[size] plus page[number] (offset) or page[after] (cursor, taken from the previous response's links.next).

Query parameters

filterstring
A FiltrQL expression, url-encoded. Combine conditions with AND / OR and parentheses. The fields you can filter on, and the operators each accepts, are listed under Filterable fields.
name = "example"
sortstring
Comma-separated sort fields; prefix a field with "-" for descending order (e.g. "-createdAt,title"). Permitted fields: id, organizationId, projectId, name, parentFolderId, rank.
-name
includestring
Comma-separated relation names to include; dot-notation for nested includes (up to 3 levels deep). Permitted top-level relations: createdByUser, organization, testCaseFolder, project, updatedByUser.
createdByUser
fields[test_case_folders]string[]
Sparse fieldset for resource type "test_case_folders" - comma-separated subset of its exposed fields: id, organizationId, projectId, name, description, parentFolderId, rank, createdAt, updatedAt, createdBy, updatedBy, createdByUser, updatedByUser, organization, testCaseFolder, project.
name,description,rank
page[size]integer
Number of resources per page (applies to both offset and cursor pagination). Minimum 1, maximum 100, default 25 when omitted.
25
page[number]integer
1-indexed page number for offset-based pagination. Mutually exclusive with "page[after]" - supplying both is rejected with a 400 (CONFLICTING_PAGINATION).
2
page[after]string
Opaque cursor for cursor-based pagination - always taken verbatim from a previous response's "links.next" value, never client-constructed or decoded. Mutually exclusive with "page[number]" - supplying both is rejected with a 400 (CONFLICTING_PAGINATION).

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json

Filterable fields11

Show fields and operators
FieldTypeOperators
iduuid= != in (…) not in (…) is null is not null
organizationIduuid= != in (…) not in (…) is null is not null
projectIduuid= != in (…) not in (…) is null is not null
namestring= != in (…) not in (…) is null is not null
descriptionstring~ is null is not null is empty is not empty
parentFolderIduuid= != in (…) not in (…) is null is not null
rankint= != < <= > >= in (…) not in (…) is null is not null
createdAtdatetime= != < <= > >= is null is not null
updatedAtdatetime= != < <= > >= is null is not null
createdByuuid= != in (…) not in (…) is null is not null
updatedByuuid= != in (…) not in (…) is null is not null

Filter through a relation with ANY, ALL or NONE, for example createdByUser ANY (id = "…"). Relations: createdByUser, organization, testCaseFolder, testCaseFolders, project, updatedByUser, testCases.

Returns the same attributes as Get a test case folder.

Responses

  • 200Success.
11 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INVALID_TYPED_JSON_FILTERUNKNOWN_SORT_FIELDINCLUDE_DEPTH_EXCEEDEDUNKNOWN_RELATIONINCLUDE_RESOURCES_EXCEEDEDUNKNOWN_TYPEUNKNOWN_FIELDCONFLICTING_PAGINATIONINVALID_PAGE_SIZEPAGE_SIZE_EXCEEDEDINVALID_PAGE_NUMBERINPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_case_folders?page%5Bsize%5D=25" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": [
    {
      "type": "test_case_folders",
      "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
      "attributes": {
        "name": "Checkout",
        "updatedAt": "2026-10-05T09:30:00Z"
      },
      "links": {
        "self": "/test_case_folders/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
      }
    }
  ],
  "links": {
    "self": "/test_case_folders?page[size]=25",
    "first": "/test_case_folders?page[size]=25&page[number]=1",
    "prev": null,
    "next": "/test_case_folders?page[size]=25&page[number]=2",
    "last": "/test_case_folders?page[size]=25&page[number]=6"
  },
  "meta": {
    "totalCount": 128
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Create a test case folder

POST/api/v1/test_case_folders

Creates a test case folder from a JSON:API resource object - data.type names the resource type and data.attributes carries the writable attributes - and returns the created resource.

Needs a read-and-write token. A read-only token gets 403.

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
Content-Typestringrequired
Must be application/vnd.api+json on any request with a body. Anything else returns 415 Unsupported Media Type.
application/vnd.api+json

Attributes you can send5

namestringrequired
projectIduuidrequired
rankintegerrequired
descriptionstring | null
parentFolderIduuid | null

Returns the same attributes as Get a test case folder.

Responses

  • 201Created.
11 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 415The Content-Type was not application/vnd.api+json.MISSING_CONTENT_TYPEINVALID_CONTENT_TYPEINVALID_CONTENT_TYPE_PARAMSPARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.INVALID_INPUTVALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_case_folders" \
  -X POST \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
  "data": {
    "type": "test_case_folders",
    "attributes": {
      "name": "Checkout",
      "projectId": "03ff802c-4fcb-4718-8eb8-12ecc999f758",
      "rank": 1
    }
  }
}'
Response

application/vnd.api+json

{
  "data": [
    {
      "type": "test_case_folders",
      "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
      "attributes": {
        "name": "Checkout",
        "updatedAt": "2026-10-05T09:30:00Z"
      },
      "links": {
        "self": "/test_case_folders/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
      }
    }
  ],
  "links": {
    "self": "/test_case_folders?page[size]=25",
    "first": "/test_case_folders?page[size]=25&page[number]=1",
    "prev": null,
    "next": "/test_case_folders?page[size]=25&page[number]=2",
    "last": "/test_case_folders?page[size]=25&page[number]=6"
  },
  "meta": {
    "totalCount": 128
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Count and aggregate test case folders

GET/api/v1/test_case_folders/aggregate

Aggregates test case folder resources - a count and per-column aggregations, optionally grouped - over the same filter the collection route accepts.

Query parameters

aggregations[count]boolean
Include the row count in the aggregate result. When no aggregation is requested at all, the runtime defaults to count.
aggregations[sum][]string[]
Column(s) to sum - repeat the bracketed key per column (aggregations[sum][]=a&aggregations[sum][]=b). Permitted columns: rank.
aggregations[avg][]string[]
Column(s) to average - repeat the bracketed key per column (aggregations[avg][]=a&aggregations[avg][]=b). Permitted columns: rank.
aggregations[min][]string[]
Column(s) to take the minimum of - repeat the bracketed key per column (aggregations[min][]=a&aggregations[min][]=b). Permitted columns: name, description, rank, createdAt, updatedAt.
aggregations[max][]string[]
Column(s) to take the maximum of - repeat the bracketed key per column (aggregations[max][]=a&aggregations[max][]=b). Permitted columns: name, description, rank, createdAt, updatedAt.
aggregations[groupBy][]string[]
Column(s) to group by - repeating the bracketed key switches the response to the grouped shape (aggregations[groupBy][]=a&aggregations[groupBy][]=b). Permitted columns: id, organizationId, projectId, name, parentFolderId, rank.
filterstring
A FiltrQL expression, url-encoded. Combine conditions with AND / OR and parentheses. The fields you can filter on, and the operators each accepts, are listed under Filterable fields.
name = "example"

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json

Filterable fields11

Show fields and operators
FieldTypeOperators
iduuid= != in (…) not in (…) is null is not null
organizationIduuid= != in (…) not in (…) is null is not null
projectIduuid= != in (…) not in (…) is null is not null
namestring= != in (…) not in (…) is null is not null
descriptionstring~ is null is not null is empty is not empty
parentFolderIduuid= != in (…) not in (…) is null is not null
rankint= != < <= > >= in (…) not in (…) is null is not null
createdAtdatetime= != < <= > >= is null is not null
updatedAtdatetime= != < <= > >= is null is not null
createdByuuid= != in (…) not in (…) is null is not null
updatedByuuid= != in (…) not in (…) is null is not null

Filter through a relation with ANY, ALL or NONE, for example createdByUser ANY (id = "…"). Relations: createdByUser, organization, testCaseFolder, testCaseFolders, project, updatedByUser, testCases.

Responses

  • 200Success.
11 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_case_folders/aggregate?aggregations%5Bcount%5D=true" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": {
    "type": "testCaseFolders_aggregate",
    "id": "(aggregate)",
    "attributes": {
      "count": 128
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Get a test case folder

GET/api/v1/test_case_folders/{id}

Returns the test case folder with this id as a JSON:API resource document; include embeds related resources and fields[<type>] selects the attributes returned.

Path parameters

iduuidrequired
The resource id (a UUID).

Query parameters

includestring
Comma-separated relation names to include; dot-notation for nested includes (up to 3 levels deep). Permitted top-level relations: createdByUser, organization, testCaseFolder, project, updatedByUser.
createdByUser
fields[test_case_folders]string[]
Sparse fieldset for resource type "test_case_folders" - comma-separated subset of its exposed fields: id, organizationId, projectId, name, description, parentFolderId, rank, createdAt, updatedAt, createdBy, updatedBy, createdByUser, updatedByUser, organization, testCaseFolder, project.
name,description,rank

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json

Attributes returned11

createdAtdate-timeread-only
createdByuuid | nullread-only
descriptionstring | null
iduuidread-only
namestring
organizationIduuidread-only
parentFolderIduuid | null
projectIduuid
Show the remaining 3
rankinteger
updatedAtdate-timeread-only
updatedByuuid | nullread-only

Responses

  • 200Success.
12 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.UNKNOWN_TYPEUNKNOWN_FIELDINCLUDE_DEPTH_EXCEEDEDUNKNOWN_RELATIONINCLUDE_RESOURCES_EXCEEDEDINPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 410Gone.GONE
  • 415The Content-Type was not application/vnd.api+json.PARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_case_folders/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": {
    "type": "test_case_folders",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "name": "Checkout",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_case_folders/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Update a test case folder

PATCH/api/v1/test_case_folders/{id}

Updates the test case folder with this id from a JSON:API resource object carrying only the attributes to change, and returns the updated resource. A resource that carries an ETag requires it back as If-Match.

Needs a read-and-write token. A read-only token gets 403.

Version-locked: send the ETag from your last read as If-Match.

Path parameters

iduuidrequired
The resource id (a UUID).

Headers

Authorizationstringrequired
Your API token as a bearer credential.
Bearer $BESTEST_TOKEN
Acceptstring
Send application/vnd.api+json, or leave it out. Asking for application/json returns 406 Not Acceptable.
application/vnd.api+json
Content-Typestringrequired
Must be application/vnd.api+json on any request with a body. Anything else returns 415 Unsupported Media Type.
application/vnd.api+json
If-Matchstringrequired
The ETag from your last read of this resource, sent back verbatim. Missing returns 428 Precondition Required; stale (someone changed it since you read it) returns 412 Precondition Failed. Read it again and retry.
W/"3"

Attributes you can send5

descriptionstring | null
namestring
parentFolderIduuid | null
projectIduuid
rankinteger

Returns the same attributes as Get a test case folder.

Responses

  • 200Success.
13 error responses
  • 400The request is malformed: an unknown field, a filter that does not parse, or conflicting paging parameters.INPUT_DEPTH_EXCEEDEDGRAPHQL_PARSE_FAILEDGRAPHQL_VALIDATION_FAILEDBAD_USER_INPUT
  • 401The token has expired or could not be authenticated.TOKEN_EXPIREDUNAUTHENTICATED
  • 403The token is missing or not recognised, belongs to another region, or is read-only and this is a write.FORBIDDEN
  • 404No such resource, or it is outside the Space your token reaches.NOT_FOUND
  • 406The Accept header asked for something other than application/vnd.api+json.NOT_ACCEPTABLE
  • 409The write conflicts with existing data, for example a duplicate or a reference to something that does not exist.UNIQUE_VIOLATIONFOREIGN_KEY_VIOLATIONCONFLICT
  • 412The If-Match ETag is stale: the resource changed since you read it. Read it again and retry.STALE_OBJECT
  • 415The Content-Type was not application/vnd.api+json.MISSING_CONTENT_TYPEINVALID_CONTENT_TYPEINVALID_CONTENT_TYPE_PARAMSPARAMETERIZED_ACCEPT
  • 422The body is well-formed but a value is invalid, such as an enum outside its list or a missing required attribute.VALIDATION_ERRORVALIDATION_FAILEDCHECK_VIOLATIONMISSING_REQUIREDATMOST_EXCEEDEDHOOK_ABORT
  • 428This resource is version-locked: send its ETag in an If-Match header.MISSING_IF_MATCH
  • 429Rate limited (RATE_LIMITED). Limits are per person and shared with MCP. Back off a few seconds and retry.RATE_LIMITEDQUOTA_EXCEEDED
  • 500Server error. Safe to retry a read; check before retrying a write.INTERNAL_ERROR
  • 503Temporarily unavailable. Retry with backoff.UNAVAILABLE
Request

curl

curl "https://prod-eu.getbestest.com/api/v1/test_case_folders/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33" \
  -X PATCH \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H 'If-Match: W/"3"' \
  -H "Content-Type: application/vnd.api+json" \
  -d '{
  "data": {
    "type": "test_case_folders",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "name": "Checkout"
    }
  }
}'
Response

application/vnd.api+json

{
  "data": {
    "type": "test_case_folders",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "name": "Checkout",
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/test_case_folders/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
    }
  },
  "jsonapi": {
    "version": "1.1"
  }
}
Show an error response
Error

every 4xx and 5xx has this shape

{
  "errors": [
    {
      "status": "400",
      "title": "Bad Request",
      "code": "UNKNOWN_FIELD",
      "detail": "Unknown field \"displayName\" on resource type \"users\". Valid fields: id, externalId, role, ...",
      "source": {
        "parameter": "fields[users]"
      }
    }
  ]
}

Related-resource endpoints

Each to-many relation has its own URL, such as a test case's steps or a cycle's executions. They return a paginated collection of the related resource and take that resource's own filter, sort, paging and fields parameters, so they are listed rather than documented one by one. For to-one relations, use ?include= on the parent request instead: one round trip instead of two.

Show all 6
  • GET/api/v1/test_cases/{id}/testCaseExecutions
  • GET/api/v1/test_cases/{id}/testCollectionTestCases
  • GET/api/v1/test_cases/{id}/testSteps
  • GET/api/v1/test_steps/{id}/testStepExecutions
  • GET/api/v1/test_case_folders/{id}/testCaseFolders
  • GET/api/v1/test_case_folders/{id}/testCases