The results namespace provides API methods to retrieve and record test results for a run. The following endpoints are available:
- GET
runs/{run_id}/results - POST
runs/{run_id}/tests/{run_test_id}/results - POST
runs/{run_id}/tests/results/bulk - PATCH
runs/{run_id}/results/{run_result_id} - GET
projects/{project_id}/statuses
GET /runs/{run_id}/results
Returns all test results for a run.
This method uses pagination so you might need to request additional pages to retrieve all results.
run_id id required
ID of the run.
Request
page integer
Number of page to return (default: first page).
per_page integer
Maximum number of results to return (supported: 15, 25, 50, 100; default: 100).
sort string
Sort field (supported: run_results:created_at; default: run_results:created_at).
order string
Sort order (supported: asc, desc; default: desc).
status_id string
Comma-separated list of status IDs to filter by. Use GET /projects/{project_id}/statuses to retrieve available statuses.
assignee_id string
Comma-separated list of assignee user IDs to filter by. Use 0 to return unassigned results.
test_id string
Comma-separated list of run test IDs to filter by.
case_id string
Comma-separated list of repository case IDs to filter by.
created_after string
Limit results to those created after this date/time (ISO 8601, UTC).
created_before string
Limit results to those created before this date/time (ISO 8601, UTC).
created_by string
Comma-separated list of user IDs to filter by creator.
get_latest_result boolean
When true, returns only the most recent result per test. Default returns all results.
expands string
Comma-separated list of expands to return.
{
"page": {
"type": "integer",
"format": "int64",
"description": "Number of page to return (default: first page)."
},
"per_page": {
"type": "integer",
"format": "int64",
"enum": [15, 25, 50, 100],
"description": "Maximum number of items to return per page (default: 100)."
},
"sort": {
"type": "string",
"enum": ["run_results:created_at"],
"default": "run_results:created_at",
"description": "Sort field for the list of results."
},
"order": {
"type": "string",
"enum": ["asc", "desc"],
"default": "desc",
"description": "Sort order (ascending or descending)."
},
"status_id": {
"type": "string",
"description": "Comma-separated list of status IDs to filter by."
},
"assignee_id": {
"type": "string",
"description": "Comma-separated list of assignee user IDs to filter by. Use 0 for unassigned."
},
"test_id": {
"type": "string",
"description": "Comma-separated list of run test IDs to filter by."
},
"case_id": {
"type": "string",
"description": "Comma-separated list of repository case IDs to filter by."
},
"created_after": {
"type": "string",
"format": "date-time",
"description": "Limit results to those created after this date/time (ISO 8601, UTC)."
},
"created_before": {
"type": "string",
"format": "date-time",
"description": "Limit results to those created before this date/time (ISO 8601, UTC)."
},
"created_by": {
"type": "string",
"description": "Comma-separated list of user IDs to filter by creator."
},
"get_latest_result": {
"type": "boolean",
"description": "When true, returns only the most recent result per test."
},
"expands": {
"type": "string",
"description": "Comma-separated list of expands to return (issues, statuses, users)."
}
}
This method supports the following expands so you can automatically include additional information for referenced objects:
issuesstatusesusers
Each result includes the values of any custom result fields configured for the project (for example custom_defect_id). Multi-value custom fields (such as steps or multi-select fields) are returned as arrays.
Response
GET /api/v1/runs/1/results
200 OK
{
"page": 1,
"prev_page": null,
"next_page": 2,
"last_page": 16,
"per_page": 25,
"total": 392,
"result": [
{
"id": 538,
"project_id": 1,
"run_id": 1,
"test_id": 64,
"case_id": 1078,
"status_id": 2,
"note": "<p>All assertions passed.</p>",
"elapsed": 45,
"assignee_id": 3,
"is_latest": true,
"issues": [],
"created_at": "2025-09-24T09:39:21.211Z",
"created_by": 1,
"updated_at": null,
"updated_by": null,
"deleted_at": null,
"deleted_by": null,
"custom_defect_id": null
},
..
],
"expands": {}
}
Examples
// Get all results for a run
GET /api/v1/runs/1/results
// Get only failed results
GET /api/v1/runs/1/results?status_id=3
// Get the latest result per test
GET /api/v1/runs/1/results?get_latest_result=true
// Filter by case ID
GET /api/v1/runs/1/results?case_id=1078
// Include issues and user expands
GET /api/v1/runs/1/results?expands=issues,users
Status codes
200 401 403 404 422 429 (details)
POST /runs/{run_id}/tests/{run_test_id}/results
Records a new result for a single test in a run. Results are additive — each call adds a new result to the test's history and becomes the test's latest result.
Validation matches the Testmo app: a disabled status is rejected, and a result cannot be assigned to an inactive user.
run_id id required
ID of the run.
run_test_id id required
ID of the test within the run (the run_tests.id value, returned as test_id by GET /runs/{run_id}/results). The test must belong to the specified run.
Request
status_id integer required
ID of the status to assign to the result. Use GET /projects/{project_id}/statuses to retrieve available statuses. The status must be active.
comment string
Optional comment for the result (rich text). Returned as the note field in responses.
elapsed integer
Elapsed time for the test, in seconds.
assignee_id integer
ID of the user to assign the result to. The user must be active.
custom_* mixed
Any custom result fields defined for the project, specified with the custom_ prefix (for example custom_defect_id). Field names are template-specific. Submitted values are returned in the response. Restricted custom fields require the appropriate user permissions.
{
"status_id": {
"type": "integer",
"format": "int32",
"description": "ID of the status to assign to the result (required, must be active)."
},
"comment": {
"type": "string",
"nullable": true,
"description": "Optional comment for the result. Returned as the note field."
},
"elapsed": {
"type": "integer",
"format": "int64",
"nullable": true,
"description": "Elapsed time in seconds."
},
"assignee_id": {
"type": "integer",
"format": "int64",
"nullable": true,
"description": "ID of the user to assign the result to (must be active)."
},
"custom_*": {
"type": "mixed",
"description": "Template-specific custom result fields, prefixed with custom_ (e.g. custom_defect_id)."
}
}
Response
POST /api/v1/runs/1/tests/64/results
201 Created
{
"result": {
"id": 613,
"project_id": 1,
"run_id": 1,
"test_id": 64,
"case_id": 1078,
"status_id": 3,
"note": "<p>Login button unresponsive on submit.</p>",
"elapsed": 45,
"assignee_id": 3,
"is_latest": true,
"issues": [],
"created_at": "2025-09-24T11:02:14.880Z",
"created_by": 1,
"updated_at": null,
"updated_by": null,
"deleted_at": null,
"deleted_by": null,
"custom_defect_id": "JIRA-1234"
}
}
Examples
// Record a simple passed result
POST /api/v1/runs/1/tests/64/results
{
"status_id": 2
}
// Record a failed result with a comment, elapsed time and assignee
POST /api/v1/runs/1/tests/64/results
{
"status_id": 3,
"comment": "<p>Login button unresponsive on submit.</p>",
"elapsed": 45,
"assignee_id": 3
}
// Record a result with a custom field value
POST /api/v1/runs/1/tests/64/results
{
"status_id": 3,
"custom_defect_id": "JIRA-1234"
}
Status codes
201 400 401 403 404 415 422 429 (details)
POST /runs/{run_id}/tests/results/bulk
Records results for multiple tests in a run in a single request. Provide a results array with between 1 and 100 items, each targeting a test by its test_id.
All items are validated up front, before any result is recorded. If any item fails validation (for example an unknown test, a disabled status, or an inactive assignee), the whole request is rejected and no results are written — so the batch never leaves a partial state.
run_id id required
ID of the run.
Request
results array required
Array of result objects to record (minimum 1, maximum 100). Each item accepts the fields below.
results[].test_id integer required
ID of the test within the run (the run_tests.id value, returned as test_id by GET /runs/{run_id}/results). Must belong to the run.
results[].status_id integer required
ID of the status to assign. Must be active.
results[].comment string
Optional comment for the result. Returned as the note field.
results[].elapsed integer
Elapsed time for the test, in seconds.
results[].assignee_id integer
ID of the user to assign the result to. Must be active.
results[].custom_* mixed
Any template-specific custom result fields, prefixed with custom_.
{
"results": {
"type": "array",
"minItems": 1,
"maxItems": 100,
"description": "Array of results to record.",
"items": {
"type": "object",
"required": ["test_id", "status_id"],
"properties": {
"test_id": {
"type": "integer",
"format": "int64",
"description": "ID of the test (run_tests.id) to create a result for."
},
"status_id": {
"type": "integer",
"format": "int32",
"description": "ID of the status to assign (must be active)."
},
"comment": {
"type": "string",
"nullable": true,
"description": "Optional comment. Returned as the note field."
},
"elapsed": {
"type": "integer",
"format": "int64",
"nullable": true,
"description": "Elapsed time in seconds."
},
"assignee_id": {
"type": "integer",
"format": "int64",
"nullable": true,
"description": "ID of the user to assign the result to (must be active)."
},
"custom_*": {
"type": "mixed",
"description": "Template-specific custom result fields, prefixed with custom_."
}
}
}
}
}
Response
POST /api/v1/runs/1/tests/results/bulk
Returns the array of created results, each with the same shape as a single result.
201 Created
[
{
"id": 614,
"project_id": 1,
"run_id": 1,
"test_id": 64,
"case_id": 1078,
"status_id": 2,
"note": null,
"elapsed": 45,
"assignee_id": null,
"is_latest": true,
"issues": [],
"created_at": "2025-09-24T11:05:00.000Z",
"created_by": 1,
"updated_at": null,
"updated_by": null,
"deleted_at": null,
"deleted_by": null,
"custom_defect_id": null
},
{
"id": 615,
"project_id": 1,
"run_id": 1,
"test_id": 65,
"case_id": 1079,
"status_id": 3,
"note": "<p>Timeout waiting for dashboard.</p>",
"elapsed": 120,
"assignee_id": 3,
"is_latest": true,
"issues": [],
"created_at": "2025-09-24T11:05:00.000Z",
"created_by": 1,
"updated_at": null,
"updated_by": null,
"deleted_at": null,
"deleted_by": null,
"custom_defect_id": "JIRA-1250"
}
]
Examples
// Record results for multiple tests at once
POST /api/v1/runs/1/tests/results/bulk
{
"results": [
{ "test_id": 64, "status_id": 2 },
{ "test_id": 65, "status_id": 3, "comment": "<p>Timeout waiting for dashboard.</p>", "elapsed": 120, "assignee_id": 3 }
]
}
Status codes
201 400 401 403 404 415 422 429 (details)
PATCH /runs/{run_id}/results/{run_result_id}
Updates an existing result. Only the fields provided in the request body are changed. As with recording results, a disabled status is rejected and a result cannot be assigned to an inactive user.
run_id id required
ID of the run.
run_result_id id required
ID of the result to update (the id of the result). The result must belong to the specified run.
Request
status_id integer
ID of the status to assign to the result. Must be active.
comment string
Comment for the result. Returned as the note field.
elapsed integer
Elapsed time for the test, in seconds.
assignee_id integer
ID of the user to assign the result to. Must be active.
custom_* mixed
Any template-specific custom result fields, prefixed with custom_.
{
"status_id": {
"type": "integer",
"format": "int32",
"nullable": true,
"description": "ID of the status to assign to the result (must be active)."
},
"comment": {
"type": "string",
"nullable": true,
"description": "Comment for the result. Returned as the note field."
},
"elapsed": {
"type": "integer",
"format": "int64",
"nullable": true,
"description": "Elapsed time in seconds."
},
"assignee_id": {
"type": "integer",
"format": "int64",
"nullable": true,
"description": "ID of the user to assign the result to (must be active)."
},
"custom_*": {
"type": "mixed",
"description": "Template-specific custom result fields, prefixed with custom_."
}
}
Response
PATCH /api/v1/runs/1/results/613
200 OK
{
"result": {
"id": 613,
"project_id": 1,
"run_id": 1,
"test_id": 64,
"case_id": 1078,
"status_id": 2,
"note": "<p>Passed after fix verified.</p>",
"elapsed": 45,
"assignee_id": 3,
"is_latest": true,
"issues": [],
"created_at": "2025-09-24T11:02:14.880Z",
"created_by": 1,
"updated_at": "2025-09-24T14:20:00.000Z",
"updated_by": 1,
"deleted_at": null,
"deleted_by": null,
"custom_defect_id": "JIRA-1234"
}
}
Examples
// Change a result's status and comment
PATCH /api/v1/runs/1/results/613
{
"status_id": 2,
"comment": "<p>Passed after fix verified.</p>"
}
// Reassign a result
PATCH /api/v1/runs/1/results/613
{
"assignee_id": 3
}
Status codes
200 400 401 403 404 415 422 429 (details)
GET /projects/{project_id}/statuses
Returns the list of test result statuses assigned to the specified project, across all entity types (runs, sessions, and automation). Statuses are used when recording results for run tests. Each status indicates whether it is currently active — inactive statuses are retained for historical results but cannot be assigned to new results.
project_id id required
ID of the project.
Response
Each status includes an is_active flag (whether it can be assigned to new results) and an aliases array (alternative names accepted for the status, for example when submitting automation results).
GET /api/v1/projects/1/statuses
200 OK
{
"result": [
{
"id": 1,
"name": "Untested",
"system_name": "untested",
"color": "#aaaaaa",
"is_active": true,
"is_final": false,
"is_untested": true,
"is_passed": false,
"is_failed": false,
"aliases": []
},
{
"id": 2,
"name": "Passed",
"system_name": "passed",
"color": "#69aa1f",
"is_active": true,
"is_final": true,
"is_untested": false,
"is_passed": true,
"is_failed": false,
"aliases": ["pass", "ok"]
},
{
"id": 3,
"name": "Failed",
"system_name": "failed",
"color": "#c00000",
"is_active": true,
"is_final": true,
"is_untested": false,
"is_passed": false,
"is_failed": true,
"aliases": ["fail"]
},
{
"id": 4,
"name": "Retest",
"system_name": "retest",
"color": "#f0ad00",
"is_active": true,
"is_final": false,
"is_untested": false,
"is_passed": false,
"is_failed": false,
"aliases": []
},
..
]
}
Status codes
200 401 403 404 429 (details)