All non-archived projects in the key’s organization, ordered by lastUsedAt descending. Returns whole rows. Deleted projects are soft-deleted (archivedAt set) and never appear here.
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/api-keys, in any
workspace, personal included. 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.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Testorim","description":"Documentation for Testorim: plain-English browser QA tests that run in a real browser.","colors":{"primary":"#059669","light":"#10b981","dark":"#047857"},"logo":{"light":"https://mintcdn.com/fulgic/ZOzvtyg298rAaunK/logo/wordmark.png?fit=max\u0026auto=format\u0026n=ZOzvtyg298rAaunK\u0026q=85\u0026s=c49b84c50b62f2ccafcc2660391619e7","dark":"https://mintcdn.com/fulgic/ZOzvtyg298rAaunK/logo/wordmark-dark.png?fit=max\u0026auto=format\u0026n=ZOzvtyg298rAaunK\u0026q=85\u0026s=d74e70ecf0f91872956e46385b5665e1","href":"https://testorim.com"},"favicon":"https://mintcdn.com/fulgic/MOzJBi6Mn9MbYgbw/favicon.png?fit=max\u0026auto=format\u0026n=MOzJBi6Mn9MbYgbw\u0026q=85\u0026s=783a1618974414f0ee72cf911352ab64","appearance":{"default":"system"},"navbar":{"links":[{"href":"https://status.testorim.com","label":"Status"},{"href":"mailto:info@fulgic.com","label":"Support"}],"primary":{"type":"button","label":"Open Testorim","href":"https://app.testorim.com"}},"footer":{"links":[{"header":"Product","items":[{"label":"Testorim","href":"https://testorim.com"},{"label":"Pricing","href":"https://testorim.com/pricing"},{"label":"Open the app","href":"https://app.testorim.com"},{"label":"Status","href":"https://status.testorim.com"}]},{"header":"Documentation","items":[{"label":"Quickstart","href":"https://docs.testorim.com/getting-started/quickstart"},{"label":"Plans and limits","href":"https://docs.testorim.com/resources/plans-and-limits"},{"label":"API reference","href":"https://docs.testorim.com/api-reference/introduction"},{"label":"CLI","href":"https://docs.testorim.com/developers/cli"}]},{"header":"Legal","items":[{"label":"Terms","href":"https://testorim.com/terms"},{"label":"Privacy","href":"https://testorim.com/privacy"}]}]},"search":{"prompt":"Search the Testorim docs"},"icons":{"library":"lucide"},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"Testorim app","icon":"monitor","href":"https://app.testorim.com"},{"anchor":"Website","icon":"globe","href":"https://testorim.com"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"fulgic","hasAudioNarration":false,"actualSubdomain":"fulgic","customDomains":["docs.testorim.com"],"gitSource":{"type":"github","owner":"sallar-ba","repo":"testorim-docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"entitlements":{"AI_CHAT":{"status":"DISABLED"},"WEB_MCP":{"status":"DISABLED"},"NARRATION":{"status":"DISABLED"}},"buildId":"6abb3a2d9ae82eb23a513b7a","clientVersion":"0.0.4094","searchFilterCounts":[{"language":"default","tag":"Documentation","count":29},{"language":"default","tag":"API reference","count":19},{"language":"default","tag":"Endpoints","count":17},{"language":"default","tag":"Runs","count":7},{"language":"default","tag":"Developers","count":6},{"language":"default","tag":"Developer documentation","count":6},{"language":"default","tag":"Getting started","count":4},{"language":"default","tag":"Integrations","count":4},{"language":"default","tag":"Resources","count":4},{"language":"default","tag":"Test creation","count":4}],"searchSettings":{"showContentSnippets":true}},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true,"deflection":{"enabled":true,"email":"support@fulgic.com"}},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"privacy":{"consentBanner":{"enabled":true}},"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"api-reference/projects/list-projects","slug":"/api-reference/projects/list-projects","pageMetadata":{"title":"List projects","description":"All non-archived projects in the key's organization, ordered by `lastUsedAt` descending. Returns whole rows. Deleted projects are soft-deleted (`archivedAt` set) and never appear here.","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/projects","href":"/api-reference/projects/list-projects","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_components.p, {\n children: [\"All non-archived projects in the key’s organization, ordered by \", _jsx(_components.code, {\n children: \"lastUsedAt\"\n }), \" descending. Returns whole rows. Deleted projects are soft-deleted (\", _jsx(_components.code, {\n children: \"archivedAt\"\n }), \" set) and never appear here.\"]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"List projects","description":"All non-archived projects in the key's organization, ordered by `lastUsedAt` descending. Returns whole rows. Deleted projects are soft-deleted (`archivedAt` set) and never appear here.","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/projects","href":"/api-reference/projects/list-projects","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"tags":["Projects"],"operationId":"listProjects","summary":"List projects","description":"All non-archived projects in the key's organization, ordered by `lastUsedAt` descending. Returns whole rows. Deleted projects are soft-deleted (`archivedAt` set) and never appear here.","security":["fae8b6de-d283-4261-b3bd-0ce2f346e6af"],"responses":{"200":"d082b73c-9a24-4486-9386-a0fadad66353","401":"bc7628bf-a313-4e7f-8625-ddf0813b6f88","429":"fc3a309f-bfe1-48e0-88a0-8740335340f0"},"method":"get","type":"path","servers":["d4db3c55-f4bc-46f2-9432-5f123e333c25","7ea51c90-14cf-4c02-9601-e57633a5e03f"],"path":"/api/projects","baseUrlOptions":["https://app.testorim.com","http://localhost:3001"],"title":"List projects","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{},"responses":{"d082b73c-9a24-4486-9386-a0fadad66353":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["projects"],"properties":{"projects":{"type":"array","items":{"type":"object","title":"Project","description":"A website-under-test. Handlers return the DB row less the saved login session, so several internal columns are visible.","required":["id","orgId","name","baseUrl","createdAt","lastUsedAt","hasLoginState"],"properties":{"id":{"type":"string","format":"uuid","isRequired":true,"uniqueKey":"projects.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"orgId":{"type":"string","format":"uuid","description":"The owning organization. Always the key's bound org.","isRequired":true,"uniqueKey":"projects.items.[INDEX].orgId","typeLabel":"string\u003cuuid>"},"name":{"type":"string","isRequired":true,"uniqueKey":"projects.items.[INDEX].name","typeLabel":"string"},"baseUrl":{"type":"string","description":"Normalised so the scheme is present and the path has no trailing slash.","isRequired":true,"uniqueKey":"projects.items.[INDEX].baseUrl","typeLabel":"string"},"createdAt":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"projects.items.[INDEX].createdAt","typeLabel":"string\u003cdate-time>"},"lastUsedAt":{"type":"string","format":"date-time","description":"Bumped on project update and on a duplicate create. Drives the ordering of `GET /api/projects`.","isRequired":true,"uniqueKey":"projects.items.[INDEX].lastUsedAt","typeLabel":"string\u003cdate-time>"},"hasLoginState":{"type":"boolean","description":"Whether a login-setup procedure has saved a browser session for this project. The session itself is never returned.","isRequired":true,"uniqueKey":"projects.items.[INDEX].hasLoginState","typeLabel":"boolean"},"archivedAt":{"oneOf":[{"type":"string","format":"date-time","description":"Soft-delete marker. Always null in responses, because archived projects are filtered out of every read path.","uniqueKey":"projects.items.[INDEX].archivedAt.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Soft-delete marker. Always null in responses, because archived projects are filtered out of every read path.","uniqueKey":"projects.items.[INDEX].archivedAt.oneOf.1","typeLabel":"null"}],"uniqueKey":"projects.items.[INDEX].archivedAt","typeLabel":"string\u003cdate-time> | null"},"storageStateCapturedAt":{"oneOf":[{"type":"string","format":"date-time","description":"When the saved session was captured. Null when none is saved.","uniqueKey":"projects.items.[INDEX].storageStateCapturedAt.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"When the saved session was captured. Null when none is saved.","uniqueKey":"projects.items.[INDEX].storageStateCapturedAt.oneOf.1","typeLabel":"null"}],"uniqueKey":"projects.items.[INDEX].storageStateCapturedAt","typeLabel":"string\u003cdate-time> | null"},"timezone":{"oneOf":[{"type":"string","description":"IANA timezone applied to every browser context. Null = browser default. There is no control for it in the app today.","uniqueKey":"projects.items.[INDEX].timezone.oneOf.0","typeLabel":"string"},{"type":"null","description":"IANA timezone applied to every browser context. Null = browser default. There is no control for it in the app today.","uniqueKey":"projects.items.[INDEX].timezone.oneOf.1","typeLabel":"null"}],"uniqueKey":"projects.items.[INDEX].timezone","typeLabel":"string | null"},"locale":{"oneOf":[{"type":"string","uniqueKey":"projects.items.[INDEX].locale.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"projects.items.[INDEX].locale.oneOf.1","typeLabel":"null"}],"uniqueKey":"projects.items.[INDEX].locale","typeLabel":"string | null"},"geolocationJson":{"oneOf":[{"type":"object","description":"Geolocation override applied to every browser context.","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90,"uniqueKey":"projects.items.[INDEX].geolocationJson.oneOf.0.latitude","typeLabel":"number"},"longitude":{"type":"number","minimum":-180,"maximum":180,"uniqueKey":"projects.items.[INDEX].geolocationJson.oneOf.0.longitude","typeLabel":"number"},"accuracy":{"type":"number","minimum":0,"maximum":10000,"uniqueKey":"projects.items.[INDEX].geolocationJson.oneOf.0.accuracy","typeLabel":"number"}},"additionalProperties":false,"uniqueKey":"projects.items.[INDEX].geolocationJson.oneOf.0","typeLabel":"object"},{"type":"null","description":"Geolocation override applied to every browser context.","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"accuracy":{"type":"number","minimum":0,"maximum":10000}},"additionalProperties":false,"uniqueKey":"projects.items.[INDEX].geolocationJson.oneOf.1","typeLabel":"null"}],"uniqueKey":"projects.items.[INDEX].geolocationJson","typeLabel":"object | null"},"appContextJson":{"oneOf":[{"type":"object","description":"User-provided, non-secret app profile used as planner context. Written by `PATCH /api/projects/{id}` (out of scope here) against a strict schema.","properties":{"appType":{"type":"string","maxLength":80,"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.0.appType","typeLabel":"string"},"summary":{"type":"string","maxLength":1200,"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.0.summary","typeLabel":"string"},"authModel":{"type":"string","maxLength":800,"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.0.authModel","typeLabel":"string"},"keyFlows":{"type":"array","maxItems":12,"items":{"type":"string","maxLength":160,"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.0.keyFlows.items.[INDEX]","typeLabel":"string"},"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.0.keyFlows","typeLabel":"string[]"},"domainTerms":{"type":"array","maxItems":30,"items":{"type":"string","maxLength":80,"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.0.domainTerms.items.[INDEX]","typeLabel":"string"},"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.0.domainTerms","typeLabel":"string[]"},"testNotes":{"type":"string","maxLength":1200,"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.0.testNotes","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.0","typeLabel":"object"},{"type":"null","description":"User-provided, non-secret app profile used as planner context. Written by `PATCH /api/projects/{id}` (out of scope here) against a strict schema.","properties":{"appType":{"type":"string","maxLength":80},"summary":{"type":"string","maxLength":1200},"authModel":{"type":"string","maxLength":800},"keyFlows":{"type":"array","maxItems":12,"items":{"type":"string","maxLength":160}},"domainTerms":{"type":"array","maxItems":30,"items":{"type":"string","maxLength":80}},"testNotes":{"type":"string","maxLength":1200}},"additionalProperties":false,"uniqueKey":"projects.items.[INDEX].appContextJson.oneOf.1","typeLabel":"null"}],"uniqueKey":"projects.items.[INDEX].appContextJson","typeLabel":"object | null"},"appMapJson":{"oneOf":[{"type":"null","description":"Machine-collected map of routes, titles and visible labels observed during successful runs, used to ground the planner. Server-written only; no stable public shape.","additionalProperties":true,"uniqueKey":"projects.items.[INDEX].appMapJson.oneOf.0","typeLabel":"null"},{"type":"object","description":"Machine-collected map of routes, titles and visible labels observed during successful runs, used to ground the planner. Server-written only; no stable public shape.","additionalProperties":true,"uniqueKey":"projects.items.[INDEX].appMapJson.oneOf.1","typeLabel":"object"},{"type":"array","description":"Machine-collected map of routes, titles and visible labels observed during successful runs, used to ground the planner. Server-written only; no stable public shape.","additionalProperties":true,"uniqueKey":"projects.items.[INDEX].appMapJson.oneOf.2","typeLabel":"array"}],"uniqueKey":"projects.items.[INDEX].appMapJson","typeLabel":"null | object | array"}},"uniqueKey":"projects.items.[INDEX]","typeLabel":"Project · object"},"isRequired":true,"uniqueKey":"projects","typeLabel":"Project · object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"projects":[{"id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","orgId":"3c90c3cc-0d44-4b50-8888-8dd25736052a","name":"\u003cstring>","baseUrl":"\u003cstring>","createdAt":"2023-11-07T05:31:56Z","lastUsedAt":"2023-11-07T05:31:56Z","hasLoginState":true,"archivedAt":"2023-11-07T05:31:56Z","storageStateCapturedAt":"2023-11-07T05:31:56Z","timezone":"\u003cstring>","locale":"\u003cstring>","geolocationJson":{"latitude":0,"longitude":0,"accuracy":5000},"appContextJson":{"appType":"\u003cstring>","summary":"\u003cstring>","authModel":"\u003cstring>","keyFlows":["\u003cstring>"],"domainTerms":["\u003cstring>"],"testNotes":"\u003cstring>"},"appMapJson":{}}]}}},"exampleType":"generated"}},"exampleType":"generated"},"bc7628bf-a313-4e7f-8625-ddf0813b6f88":{"description":"No `Authorization: Bearer …` header, or the credential did not\nverify. Distinct messages the code can return:\n\n* `Missing or invalid Authorization header`\n* `Invalid or revoked API key`\n* `API key owner not found`\n* `API key's organization is no longer accessible`. The key's user\n has been removed from the org it is bound to\n* `Invalid token` / `Token missing sub claim`. Clerk JWT path\n\nRepeated failures burn the `auth:strict` bucket (5 per 15 minutes\nper IP) and then return `429` instead.\n","content":{"application/json":{"schema":{"type":"object","title":"Error","description":"The universal error envelope. Every failing handler in this surface responds with a JSON object carrying a human-readable `error` string; some add extra fields (see the other error schemas).","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable message. Not a stable machine-readable code.","isRequired":true,"uniqueKey":"error","typeLabel":"string"}},"additionalProperties":true,"uniqueKey":"","typeLabel":"Error · object"},"example":{"error":"Invalid or revoked API key"},"examples":{"Example":{"title":"Example","value":{"error":"Invalid or revoked API key"}}},"exampleType":"examples"}},"exampleType":"examples"},"fc3a309f-bfe1-48e0-88a0-8740335340f0":{"description":"Throttled. Every `/api/*` route sits behind `api:global` (600 / minute per IP); some routes add a tighter per-user limiter.","headers":{"Retry-After":{"description":"Seconds until the window frees up.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","title":"RateLimitError","description":"Emitted by the rate-limit middleware alongside a `Retry-After` header.","required":["error"],"properties":{"error":{"type":"string","description":"The limiter's reason, e.g. `Rate limit exceeded. Try again in 42s.`","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"retryAfter":{"oneOf":[{"type":"integer","description":"Seconds until the window frees. Mirrors `Retry-After`. May be absent/null when the limiter did not report a reset time, in which case the header defaults to 60.","uniqueKey":"retryAfter.oneOf.0","typeLabel":"integer"},{"type":"null","description":"Seconds until the window frees. Mirrors `Retry-After`. May be absent/null when the limiter did not report a reset time, in which case the header defaults to 60.","uniqueKey":"retryAfter.oneOf.1","typeLabel":"null"}],"uniqueKey":"retryAfter","typeLabel":"integer | null"}},"additionalProperties":true,"uniqueKey":"","typeLabel":"RateLimitError · object"},"examples":{"Example":{"title":"Example","value":{"error":"\u003cstring>","retryAfter":123}}},"exampleType":"generated"}},"exampleType":"generated"}},"security":{"fae8b6de-d283-4261-b3bd-0ce2f346e6af":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"tst_live_\u003c32 url-safe base64 chars>","description":"Send `Authorization: Bearer tst_live_…`.\n\nFormat (`services/api-keys.ts`): the literal prefix `tst_live_`\nfollowed by 24 random bytes rendered as 32 base64url characters.\nOnly the SHA-256 hash is stored server-side. The shape check that\nroutes a token down the API-key path rather than the Clerk JWT path\nrequires the `tst_live_` prefix and a total length of at least 25\ncharacters.\n\nKeys are minted in the dashboard at `/settings/api-keys`, in any\nworkspace, personal included. The same header also accepts a Clerk\nsession JWT, which is how the web app authenticates, but the JWT path\nis out of scope for this document.\n","scopes":[]}}},"servers":{"d4db3c55-f4bc-46f2-9432-5f123e333c25":{"url":"https://app.testorim.com","description":"Production. Single-origin deployment: Caddy on one GCP VM serves the SPA at `/` and reverse-proxies `/api/*` and `/ws` to the backend. This is also the default API base URL used by the Testorim CLI."},"7ea51c90-14cf-4c02-9601-e57633a5e03f":{"url":"http://localhost:3001","description":"A locally running Testorim backend, for self-hosted or development use. The default port is 3001."}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","bearerFormat":"tst_live_\u003c32 url-safe base64 chars>","description":"Send `Authorization: Bearer tst_live_…`.\n\nFormat (`services/api-keys.ts`): the literal prefix `tst_live_`\nfollowed by 24 random bytes rendered as 32 base64url characters.\nOnly the SHA-256 hash is stored server-side. The shape check that\nroutes a token down the API-key path rather than the Clerk JWT path\nrequires the `tst_live_` prefix and a total length of at least 25\ncharacters.\n\nKeys are minted in the dashboard at `/settings/api-keys`, in any\nworkspace, personal included. The same header also accepts a Clerk\nsession JWT, which is how the web app authenticates, but the JWT path\nis out of scope for this document.\n","scopes":[]},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"Send `Authorization: Bearer tst_live_…`.\n\nFormat (`services/api-keys.ts`): the literal prefix `tst_live_`\nfollowed by 24 random bytes rendered as 32 base64url characters.\nOnly the SHA-256 hash is stored server-side. The shape check that\nroutes a token down the API-key path rather than the Clerk JWT path\nrequires the `tst_live_` prefix and a total length of at least 25\ncharacters.\n\nKeys are minted in the dashboard at `/settings/api-keys`, in any\nworkspace, personal included. The same header also accepts a Clerk\nsession JWT, which is how the web app authenticates, but the JWT path\nis out of scope for this document.\n","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"ApiKeyAuth","name":"Authorization"}],"title":"ApiKeyAuth"}]},"originalFileLocation":"api-reference/openapi.yaml"},"subdomain":"fulgic","siteName":"Testorim","title":"List projects - Testorim","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-25T12:52:51.822Z","originalFileLocation":"api-reference/projects/list-projects.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"All non-archived projects in the key\u0026#x27;s organization, ordered by lastUsedAt descending. Returns whole rows. Deleted projects are soft-deleted (archivedAt set) and never appear here.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Testorim\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"List projects - Testorim\">\u003cmeta data-mint-head property=\"og:description\" content=\"All non-archived projects in the key\u0026#x27;s organization, ordered by lastUsedAt descending. Returns whole rows. Deleted projects are soft-deleted (archivedAt set) and never appear here.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Testorim\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.testorim.com/api-reference/projects/list-projects\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://fulgic.mintlify.site/_mintlify/api/og/v2?division=Projects\u0026amp;title=List+projects\u0026amp;description=All+non-archived+projects+in+the+key%27s+organization%2C+ordered+by+%60lastUsedAt%60+descending.+Returns+whole+rows.+Deleted+projects+are+soft-deleted+%28%60archivedAt%60+set\u0026amp;theme=21e417d08933df01149b8e86\u0026amp;signature=297490443129a399e0ed1b150377282e410ee39bc694bc1ceddd1f737cc959d0\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"List projects - Testorim\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"All non-archived projects in the key\u0026#x27;s organization, ordered by lastUsedAt descending. Returns whole rows. Deleted projects are soft-deleted (archivedAt set) and never appear here.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://fulgic.mintlify.site/_mintlify/api/og/v2?division=Projects\u0026amp;title=List+projects\u0026amp;description=All+non-archived+projects+in+the+key%27s+organization%2C+ordered+by+%60lastUsedAt%60+descending.+Returns+whole+rows.+Deleted+projects+are+soft-deleted+%28%60archivedAt%60+set\u0026amp;theme=21e417d08933df01149b8e86\u0026amp;signature=297490443129a399e0ed1b150377282e410ee39bc694bc1ceddd1f737cc959d0\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/fulgic/HlhB1s7g4HMZVSXy/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Testorim\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#059669\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.testorim.com/api-reference/projects/list-projects\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/projects/list-projects.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.testorim.com/#organization\",\"name\":\"Testorim\",\"url\":\"https://docs.testorim.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/fulgic/ZOzvtyg298rAaunK/logo/wordmark.png?fit=max\u0026auto=format\u0026n=ZOzvtyg298rAaunK\u0026q=85\u0026s=c49b84c50b62f2ccafcc2660391619e7\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.testorim.com#website\",\"name\":\"Testorim\",\"url\":\"https://docs.testorim.com\",\"publisher\":{\"@id\":\"https://docs.testorim.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.testorim.com/api-reference/projects/list-projects#webpage\",\"url\":\"https://docs.testorim.com/api-reference/projects/list-projects\",\"name\":\"List projects\",\"description\":\"All non-archived projects in the key's organization, ordered by lastUsedAt descending. Returns whole rows. Deleted projects are soft-deleted (archivedAt set) and never appear here.\",\"dateModified\":\"2026-09-25T12:52:51.822Z\",\"isPartOf\":{\"@id\":\"https://docs.testorim.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.testorim.com/api-reference/projects/list-projects#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.testorim.com/api-reference/projects/list-projects#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Endpoints\",\"item\":\"https://docs.testorim.com/api-reference/runs/start-a-test-run-headlessly\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"List projects\",\"item\":\"https://docs.testorim.com/api-reference/projects/list-projects\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.testorim.com/api-reference/projects/list-projects#apireference\",\"headline\":\"List projects\",\"name\":\"List projects\",\"description\":\"All non-archived projects in the key's organization, ordered by lastUsedAt descending. Returns whole rows. Deleted projects are soft-deleted (archivedAt set) and never appear here.\",\"url\":\"https://docs.testorim.com/api-reference/projects/list-projects\",\"mainEntityOfPage\":{\"@id\":\"https://docs.testorim.com/api-reference/projects/list-projects#webpage\"},\"dateModified\":\"2026-09-25T12:52:51.822Z\",\"publisher\":{\"@id\":\"https://docs.testorim.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.testorim.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Testorim\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Testorim","nav":{"global":{"anchors":[{"anchor":"Testorim app","icon":"monitor","href":"https://app.testorim.com"},{"anchor":"Website","icon":"globe","href":"https://testorim.com"}]},"tabs":[{"tab":"Documentation","pages":[{"title":"Documentation","href":""}]},{"tab":"Developers","pages":[{"title":"Developers","href":"/developers/platform-overview"}]},{"tab":"API reference","groups":[{"group":"Overview","pages":[{"title":"API reference","href":"/api-reference/introduction"},{"title":"Errors","href":"/api-reference/errors"}]},{"group":"Endpoints","pages":[{"group":"Runs","pages":[{"title":"Start a test run headlessly","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /api/runs/trigger","href":"/api-reference/runs/start-a-test-run-headlessly"},{"title":"List runs across the organization","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/runs","href":"/api-reference/runs/list-runs-across-the-organization"},{"title":"List in-flight runs, grouped by batch","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/runs/active","href":"/api-reference/runs/list-in-flight-runs-grouped-by-batch"},{"title":"Get one run with all artifacts","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/runs/{id}","href":"/api-reference/runs/get-one-run-with-all-artifacts"},{"title":"Cancel a single run","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /api/runs/{id}/cancel","href":"/api-reference/runs/cancel-a-single-run"},{"title":"Cancel every run in a batch","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /api/runs/batch/{batchId}/cancel","href":"/api-reference/runs/cancel-every-run-in-a-batch"},{"title":"List runs for one project","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/projects/{projectId}/runs","href":"/api-reference/runs/list-runs-for-one-project"}]},{"group":"Procedures","pages":[{"title":"List a project's saved procedures","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/projects/{projectId}/procedures","href":"/api-reference/procedures/list-a-projects-saved-procedures"},{"title":"Get one procedure by id","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/procedures/{id}","href":"/api-reference/procedures/get-one-procedure-by-id"},{"title":"Export a procedure as a standalone Playwright spec","description":"Renders the procedure to a self-contained `.spec.ts` Playwright test\nand returns it as a file download. Useful in CI when you want the\nsteps checked into a repo rather than executed by Testorim.\n\nNo secret is written into the file: a saved password reads\n`process.env.TESTORIM_SECRET_\u003cfield>`, a project variable\n`process.env.TESTORIM_VAR_\u003cname>`, a mid-run prompt answer\n`process.env.TESTORIM_PROMPT_\u003cfield>`.\n\n**This response is not JSON.** `Content-Type` is\n`text/typescript; charset=utf-8` and `Content-Disposition` carries\nboth an ASCII-sanitised `filename=` and an RFC 5987\n`filename*=UTF-8''…` form.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/procedures/{id}/export","href":"/api-reference/procedures/export-a-procedure-as-a-standalone-playwright-spec"}]},{"group":"Projects","pages":[{"title":"List projects","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/projects","href":"/api-reference/projects/list-projects"},{"title":"Create (or re-use) a project","description":"Creates a project for the key's organization.\n\n**This endpoint is idempotent-by-URL, and the status code tells you\nwhich happened.** The base URL is normalised\n(`https://` added when the scheme is missing, trailing slash on the\npath removed) and then matched against existing non-archived\nprojects in the org:\n\n* no match → the project is inserted and the response is\n **`201`** with `created: true`;\n* match → the existing project's `lastUsedAt` is bumped and the\n response is **`200`** with `created: false`.\n\nThe normalised URL keeps only the scheme, host and path (a query or\nfragment is dropped). It is checked by the SSRF guard, including a\nDNS lookup of the name, before anything is persisted, so a private or\ninternal host is refused with `400` and never stored.\n\nWhen `name` is omitted it is derived from the hostname with a leading\n`www.` stripped.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /api/projects","href":"/api-reference/projects/create-or-re-use-a-project"},{"title":"Get one project","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/projects/{id}","href":"/api-reference/projects/get-one-project"}]},{"group":"API keys","pages":[{"title":"List active API keys","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/keys","href":"/api-reference/api-keys/list-active-api-keys"},{"title":"Mint a new API key (browser session only)","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /api/keys","href":"/api-reference/api-keys/mint-a-new-api-key-browser-session-only"},{"title":"Revoke an API key","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /api/keys/{id}","href":"/api-reference/api-keys/revoke-an-api-key"}]},{"group":"Identity","pages":[{"title":"Identify the presented credential","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/me","href":"/api-reference/identity/identify-the-presented-credential"}]}]}]}]},"basePath":"","title":"List projects - Testorim","buildId":"dpl_42LwxxU1kGN114H4XzwGYXa9ZDah","deploymentId":"dpl_42LwxxU1kGN114H4XzwGYXa9ZDah","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-C-hEh3I2.js","utils-CnF4QiUD.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-C7PVNbel.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-8ytevL2A.js","snippetPresets-BT1alx3v.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","conditional-requirements-CFM0id0Q.js","ApiExamples-BLXC0i_W.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-CyLIGI9_.js","shallow-DC0lGVIW.js","getApiPlaygroundDisplay-CgDQ85tN.js","CodeSnippet-6-I-Gpv9.js","CodeSnippets-BAk1kDdu.js","Page-C945cI-W.js","getPastedJson-B276RuWN.js","icon-BqP8etTm.js","MethodPill-DM6sbxG1.js","DuplicateIcon-PyJglOaE.js","createIcon-CMeOMAc_.js","DynamicMarkdown-BoyYAA8K.js","SectionHeading-DAYv3gvZ.js","axios-vUo_bRtp.js","Markdown-BhTTmazV.js","clsx-CR-RHrVC.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-CBUH0-zX.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-BmARFYNC.js"]}