REST API reference

Custom fields

Read-only definitions of the custom fields your Space uses. The values themselves live on each record, in its customFields attribute, keyed by field.

List custom fields

GET/api/v1/gqlith_custom_field

Lists custom field 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.
scopeRef = "00000000-0000-0000-0000-000000000000"
filter[relation]object
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.
filter[validation]object
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.
filter[visibility]object
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.
sortstring
Comma-separated sort fields; prefix a field with "-" for descending order (e.g. "-createdAt,title"). Permitted fields: id, organizationId, scopeRef, scopeLevel, entity, key.
-scopeRef
includestring
Comma-separated relation names to include; dot-notation for nested includes (up to 3 levels deep). Permitted top-level relations: organization, project.
fields[gqlith_custom_field]string[]
Sparse fieldset for resource type "gqlith_custom_field" - comma-separated subset of its exposed fields: id, organizationId, scopeRef, scopeLevel, entity, key, kind, label, createdAt, updatedAt, createdBy, updatedBy, version, nullable, required, description, options, relation, validation, visibility, metadata, readOnly, filterable, sortable, position, archivedAt, filterFieldKind, organization, project.
scopeRef,scopeLevel,entity
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 fields27

Show fields and operators
FieldTypeOperators
iduuid= != in (…) not in (…) is null is not null
organizationIduuid= != in (…) not in (…) is null is not null
scopeRefuuid= != in (…) not in (…) is null is not null
scopeLevelstring= != in (…) not in (…) is null is not null
entitystring= != in (…) not in (…) is null is not null
keystring= != in (…) not in (…) is null is not null
kindstring= != in (…) not in (…) is null is not null
labelstring= != in (…) not in (…) is null is not null
createdAtdatetime= != < <= > >= is null is not null
updatedAtdatetime= != < <= > >= is null is not null
createdBystring= != in (…) not in (…) is null is not null
updatedBystring= != in (…) not in (…) is null is not null
versionint= != < <= > >= in (…) not in (…) is null is not null
nullablebool= != is null is not null
requiredbool= != is null is not null
descriptionstring= != in (…) not in (…) is null is not null
optionsjsonb= != is null is not null
metadatajsonb= != is null is not null
readOnlybool= != is null is not null
filterablebool= != is null is not null
sortablebool= != is null is not null
positionint= != < <= > >= in (…) not in (…) is null is not null
archivedAtdatetime= != < <= > >= is null is not null
filterFieldKindstring= != in (…) not in (…) is null is not null
relationtypedJson
validationtypedJson
visibilitytypedJson

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

Returns the same attributes as Get a custom field.

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/gqlith_custom_field?page%5Bsize%5D=25" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": [
    {
      "type": "gqlith_custom_field",
      "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
      "attributes": {
        "updatedAt": "2026-10-05T09:30:00Z"
      },
      "links": {
        "self": "/gqlith_custom_field/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33"
      }
    }
  ],
  "links": {
    "self": "/gqlith_custom_field?page[size]=25",
    "first": "/gqlith_custom_field?page[size]=25&page[number]=1",
    "prev": null,
    "next": "/gqlith_custom_field?page[size]=25&page[number]=2",
    "last": "/gqlith_custom_field?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 custom fields

GET/api/v1/gqlith_custom_field/aggregate

Aggregates custom field 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, position.
aggregations[avg][]string[]
Column(s) to average - repeat the bracketed key per column (aggregations[avg][]=a&aggregations[avg][]=b). Permitted columns: version, position.
aggregations[min][]string[]
Column(s) to take the minimum of - repeat the bracketed key per column (aggregations[min][]=a&aggregations[min][]=b). Permitted columns: scopeLevel, entity, key, kind, label, createdAt, updatedAt, createdBy, updatedBy, version, description, position, archivedAt, filterFieldKind.
aggregations[max][]string[]
Column(s) to take the maximum of - repeat the bracketed key per column (aggregations[max][]=a&aggregations[max][]=b). Permitted columns: scopeLevel, entity, key, kind, label, createdAt, updatedAt, createdBy, updatedBy, version, description, position, archivedAt, filterFieldKind.
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, scopeRef, scopeLevel, entity, key.
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.
scopeRef = "00000000-0000-0000-0000-000000000000"

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 fields27

Show fields and operators
FieldTypeOperators
iduuid= != in (…) not in (…) is null is not null
organizationIduuid= != in (…) not in (…) is null is not null
scopeRefuuid= != in (…) not in (…) is null is not null
scopeLevelstring= != in (…) not in (…) is null is not null
entitystring= != in (…) not in (…) is null is not null
keystring= != in (…) not in (…) is null is not null
kindstring= != in (…) not in (…) is null is not null
labelstring= != in (…) not in (…) is null is not null
createdAtdatetime= != < <= > >= is null is not null
updatedAtdatetime= != < <= > >= is null is not null
createdBystring= != in (…) not in (…) is null is not null
updatedBystring= != in (…) not in (…) is null is not null
versionint= != < <= > >= in (…) not in (…) is null is not null
nullablebool= != is null is not null
requiredbool= != is null is not null
descriptionstring= != in (…) not in (…) is null is not null
optionsjsonb= != is null is not null
metadatajsonb= != is null is not null
readOnlybool= != is null is not null
filterablebool= != is null is not null
sortablebool= != is null is not null
positionint= != < <= > >= in (…) not in (…) is null is not null
archivedAtdatetime= != < <= > >= is null is not null
filterFieldKindstring= != in (…) not in (…) is null is not null
relationtypedJson
validationtypedJson
visibilitytypedJson

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

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/gqlith_custom_field/aggregate?aggregations%5Bcount%5D=true" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": {
    "type": "gqlithCustomField_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 custom field

GET/api/v1/gqlith_custom_field/{id}

Returns the custom field 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: organization, project.
fields[gqlith_custom_field]string[]
Sparse fieldset for resource type "gqlith_custom_field" - comma-separated subset of its exposed fields: id, organizationId, scopeRef, scopeLevel, entity, key, kind, label, createdAt, updatedAt, createdBy, updatedBy, version, nullable, required, description, options, relation, validation, visibility, metadata, readOnly, filterable, sortable, position, archivedAt, filterFieldKind, organization, project.
scopeRef,scopeLevel,entity

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 returned27

archivedAtdate-time | nullread-only
createdAtdate-timeread-only
createdBystring | nullread-only
descriptionstring | null
entitystring
requirementstest_casestest_cyclestest_campaignstest_collections
filterablebooleandefault true
filterFieldKindstring | null
iduuidread-only
Show the remaining 19
keystring
kindstring
labelstring
metadataany
nullablebooleandefault true
optionsany
organizationIduuidread-only
positioninteger | null
readOnlybooleandefault false
relationobject | null
requiredbooleandefault false
scopeLevelstringdefault tenant
scopeRefuuid | null
sortablebooleandefault false
updatedAtdate-timeread-only
updatedBystring | nullread-only
validationobject | null
versionintegerread-onlydefault 1
visibilityobject | null

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/gqlith_custom_field/3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33" \
  -H "Authorization: Bearer $BESTEST_TOKEN" \
  -H "Accept: application/vnd.api+json"
Response

application/vnd.api+json

{
  "data": {
    "type": "gqlith_custom_field",
    "id": "3f2b9c14-8d5e-4a71-9f60-2c1e7b4a8d33",
    "attributes": {
      "updatedAt": "2026-10-05T09:30:00Z"
    },
    "links": {
      "self": "/gqlith_custom_field/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]"
      }
    }
  ]
}