curl --request GET \
--url https://app.testorim.com/api/runs \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.testorim.com/api/runs"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.testorim.com/api/runs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.testorim.com/api/runs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.testorim.com/api/runs"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.testorim.com/api/runs")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.testorim.com/api/runs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"runs": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"instruction": "<string>",
"status": "pending",
"passedCount": 123,
"failedCount": 123,
"skippedCount": 123,
"totalDurationMs": 123,
"hasVideo": true,
"hasTrace": true,
"createdAt": "2023-11-07T05:31:56Z",
"procedureId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"userExpectation": "pass",
"overallStatus": "passed",
"initialUrl": "<string>",
"finalUrl": "<string>",
"reportMarkdown": "<string>",
"confidenceScore": 123,
"finalScreenshotR2Key": "<string>",
"finalScreenshotUrl": "<string>",
"videoR2Key": "<string>",
"traceR2Key": "<string>",
"videoUrl": null,
"traceUrl": null,
"viewportPreset": "<string>",
"batchId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"browser": "<string>",
"attemptIndex": 123,
"parentRunId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"runKind": "<string>",
"startedAt": "2023-11-07T05:31:56Z",
"completedAt": "2023-11-07T05:31:56Z"
}
]
}{
"error": "Invalid or revoked API key"
}{
"error": "<string>",
"retryAfter": 123
}List runs across the organization
Every run in the key’s organization, newest first, in the slim summary shape. Heavy JSONB columns (stepsJson, network/console events, screenshot refs) are omitted. Fetch a single run for those.
curl --request GET \
--url https://app.testorim.com/api/runs \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.testorim.com/api/runs"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.testorim.com/api/runs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.testorim.com/api/runs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.testorim.com/api/runs"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.testorim.com/api/runs")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.testorim.com/api/runs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"runs": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"instruction": "<string>",
"status": "pending",
"passedCount": 123,
"failedCount": 123,
"skippedCount": 123,
"totalDurationMs": 123,
"hasVideo": true,
"hasTrace": true,
"createdAt": "2023-11-07T05:31:56Z",
"procedureId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"userExpectation": "pass",
"overallStatus": "passed",
"initialUrl": "<string>",
"finalUrl": "<string>",
"reportMarkdown": "<string>",
"confidenceScore": 123,
"finalScreenshotR2Key": "<string>",
"finalScreenshotUrl": "<string>",
"videoR2Key": "<string>",
"traceR2Key": "<string>",
"videoUrl": null,
"traceUrl": null,
"viewportPreset": "<string>",
"batchId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"browser": "<string>",
"attemptIndex": 123,
"parentRunId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"runKind": "<string>",
"startedAt": "2023-11-07T05:31:56Z",
"completedAt": "2023-11-07T05:31:56Z"
}
]
}{
"error": "Invalid or revoked API key"
}{
"error": "<string>",
"retryAfter": 123
}Authorizations
Send Authorization: Bearer tst_live_….
Format (services/api-keys.ts): the literal prefix tst_live_
followed by 24 random bytes rendered as 32 base64url characters.
Only the SHA-256 hash is stored server-side. The shape check that
routes a token down the API-key path rather than the Clerk JWT path
requires the tst_live_ prefix and a total length of at least 25
characters.
Keys are minted in the dashboard at /settings/team. The same header
also accepts a Clerk session JWT, which is how the web app
authenticates, but the JWT path is out of scope for this document.
Query Parameters
Maximum rows. Default 100, clamped to 1..500. Parsed with parseInt; a non-numeric value silently falls back to 100 rather than erroring.
1 <= x <= 500Response
OK
Show child attributes
Show child attributes

