Keys owned by the user the credential belongs to, newest first.
Only keys that are usable right now are listed: revoked keys and
expired keys are filtered out in SQL.
Note the scoping difference from the rest of the API: this list is
per-user, not per-organization, so it can include keys bound to other
orgs the user belongs to. Each key carries orgId and orgName, the
workspace it acts in. Plaintext is never returned, only prefix, the
first 12 characters.
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/api-keys/list-active-api-keys","slug":"/api-reference/api-keys/list-active-api-keys","pageMetadata":{"title":"List active API keys","description":"Keys owned by the **user** the credential belongs to, newest first.\nOnly keys that are usable right now are listed: revoked keys and\nexpired keys are filtered out in SQL.\n\nNote the scoping difference from the rest of the API: this list is\nper-user, not per-organization, so it can include keys bound to other\norgs the user belongs to. Each key carries `orgId` and `orgName`, the\nworkspace it acts in. Plaintext is never returned, only `prefix`, the\nfirst 12 characters.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/keys","href":"/api-reference/api-keys/list-active-api-keys","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n p: \"p\",\n strong: \"strong\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsxs(_components.p, {\n children: [\"Keys owned by the \", _jsx(_components.strong, {\n children: \"user\"\n }), \" the credential belongs to, newest first.\\nOnly keys that are usable right now are listed: revoked keys and\\nexpired keys are filtered out in SQL.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Note the scoping difference from the rest of the API: this list is\\nper-user, not per-organization, so it can include keys bound to other\\norgs the user belongs to. Each key carries \", _jsx(_components.code, {\n children: \"orgId\"\n }), \" and \", _jsx(_components.code, {\n children: \"orgName\"\n }), \", the\\nworkspace it acts in. Plaintext is never returned, only \", _jsx(_components.code, {\n children: \"prefix\"\n }), \", the\\nfirst 12 characters.\"]\n })]\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 active API keys","description":"Keys owned by the **user** the credential belongs to, newest first.\nOnly keys that are usable right now are listed: revoked keys and\nexpired keys are filtered out in SQL.\n\nNote the scoping difference from the rest of the API: this list is\nper-user, not per-organization, so it can include keys bound to other\norgs the user belongs to. Each key carries `orgId` and `orgName`, the\nworkspace it acts in. Plaintext is never returned, only `prefix`, the\nfirst 12 characters.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api/keys","href":"/api-reference/api-keys/list-active-api-keys","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"tags":["API keys"],"operationId":"listApiKeys","summary":"List active API keys","description":"Keys owned by the **user** the credential belongs to, newest first.\nOnly keys that are usable right now are listed: revoked keys and\nexpired keys are filtered out in SQL.\n\nNote the scoping difference from the rest of the API: this list is\nper-user, not per-organization, so it can include keys bound to other\norgs the user belongs to. Each key carries `orgId` and `orgName`, the\nworkspace it acts in. Plaintext is never returned, only `prefix`, the\nfirst 12 characters.\n","security":["c86ef8ac-61f7-4130-a6be-b897532acc1d"],"responses":{"200":"6599f482-5284-422e-9e49-bc722051c6dc","401":"77a787b2-9756-4ab7-b600-c996b106b64d","429":"a3ac4e8d-681e-4264-8bf1-a49b11773c23","500":"9199a9c9-9ed8-4914-98ca-da2730c4a382"},"method":"get","type":"path","servers":["d4db3c55-f4bc-46f2-9432-5f123e333c25","7ea51c90-14cf-4c02-9601-e57633a5e03f"],"path":"/api/keys","baseUrlOptions":["https://app.testorim.com","http://localhost:3001"],"title":"List active API keys","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{},"responses":{"6599f482-5284-422e-9e49-bc722051c6dc":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"object","title":"ApiKey","description":"A key as returned by the list endpoint. Only active keys are listed and revoked and expired keys are filtered out, so there is no `revokedAt` field in this shape.","required":["id","name","prefix","createdAt","lastUsedAt","expiresAt","orgId","orgName"],"properties":{"id":{"type":"string","format":"uuid","description":"Use this in `DELETE /api/keys/{id}`.","isRequired":true,"uniqueKey":"keys.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"orgId":{"type":"string","format":"uuid","description":"The workspace the key acts in.","isRequired":true,"uniqueKey":"keys.items.[INDEX].orgId","typeLabel":"string\u003cuuid>"},"orgName":{"type":"string","isRequired":true,"uniqueKey":"keys.items.[INDEX].orgName","typeLabel":"string"},"name":{"type":"string","isRequired":true,"uniqueKey":"keys.items.[INDEX].name","typeLabel":"string"},"prefix":{"type":"string","description":"The first 12 characters of the plaintext, e.g. `tst_live_a1b`, display only, and not enough to authenticate with.","examples":["tst_live_a1b"],"isRequired":true,"uniqueKey":"keys.items.[INDEX].prefix","typeLabel":"string"},"createdAt":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"keys.items.[INDEX].createdAt","typeLabel":"string\u003cdate-time>"},"lastUsedAt":{"oneOf":[{"type":"string","format":"date-time","description":"Refreshed on each successful authentication, fire-and-forget, so it can lag slightly behind real usage.","isRequired":true,"uniqueKey":"keys.items.[INDEX].lastUsedAt.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Refreshed on each successful authentication, fire-and-forget, so it can lag slightly behind real usage.","isRequired":true,"uniqueKey":"keys.items.[INDEX].lastUsedAt.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"keys.items.[INDEX].lastUsedAt","typeLabel":"string\u003cdate-time> | null"},"expiresAt":{"oneOf":[{"type":"string","format":"date-time","description":"Null when the key never expires.","isRequired":true,"uniqueKey":"keys.items.[INDEX].expiresAt.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Null when the key never expires.","isRequired":true,"uniqueKey":"keys.items.[INDEX].expiresAt.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"keys.items.[INDEX].expiresAt","typeLabel":"string\u003cdate-time> | null"}},"uniqueKey":"keys.items.[INDEX]","typeLabel":"ApiKey · object"},"isRequired":true,"uniqueKey":"keys","typeLabel":"ApiKey · object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"keys":[{"id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","orgId":"3c90c3cc-0d44-4b50-8888-8dd25736052a","orgName":"\u003cstring>","name":"\u003cstring>","prefix":"tst_live_a1b","createdAt":"2023-11-07T05:31:56Z","lastUsedAt":"2023-11-07T05:31:56Z","expiresAt":"2023-11-07T05:31:56Z"}]}}},"exampleType":"generated"}},"exampleType":"generated"},"77a787b2-9756-4ab7-b600-c996b106b64d":{"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"},"a3ac4e8d-681e-4264-8bf1-a49b11773c23":{"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"},"9199a9c9-9ed8-4914-98ca-da2730c4a382":{"description":"Listing failed.","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":"Failed to list keys"},"examples":{"Example":{"title":"Example","value":{"error":"Failed to list keys"}}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{"c86ef8ac-61f7-4130-a6be-b897532acc1d":{"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 active API keys - Testorim","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-25T12:52:51.871Z","originalFileLocation":"api-reference/api-keys/list-active-api-keys.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=\"Keys owned by the user the credential belongs to, newest first. Only keys that are usable right now are listed: revoked keys and expired keys are filtered out in SQL. Note the scoping difference from the rest of the API: this list is per-user, not per-organization, so it can include keys bound to other orgs the user belongs to. Each key carries orgId and orgName, the workspace it acts in. Plaintext is never returned, only prefix, the first 12 characters.\">\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 active API keys - Testorim\">\u003cmeta data-mint-head property=\"og:description\" content=\"Keys owned by the user the credential belongs to, newest first. Only keys that are usable right now are listed: revoked keys and expired keys are filtered out in SQL. Note the scoping difference from the rest of the API: this list is per-user, not per-organization, so it can include keys bound to other orgs the user belongs to. Each key carries orgId and orgName, the workspace it acts in. Plaintext is never returned, only prefix, the first 12 characters.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Testorim\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.testorim.com/api-reference/api-keys/list-active-api-keys\">\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=API+keys\u0026amp;title=List+active+API+keys\u0026amp;description=Keys+owned+by+the+**user**+the+credential+belongs+to%2C+newest+first.%0AOnly+keys+that+are+usable+right+now+are+listed%3A+revoked+keys+and%0Aexpired+keys+are+filtered+o\u0026amp;theme=21e417d08933df01149b8e86\u0026amp;signature=8690b79697da401c7cba092b9424e2853188a2c5ce01a973fe2588bffcaa0302\">\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 active API keys - Testorim\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Keys owned by the user the credential belongs to, newest first. Only keys that are usable right now are listed: revoked keys and expired keys are filtered out in SQL. Note the scoping difference from the rest of the API: this list is per-user, not per-organization, so it can include keys bound to other orgs the user belongs to. Each key carries orgId and orgName, the workspace it acts in. Plaintext is never returned, only prefix, the first 12 characters.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://fulgic.mintlify.site/_mintlify/api/og/v2?division=API+keys\u0026amp;title=List+active+API+keys\u0026amp;description=Keys+owned+by+the+**user**+the+credential+belongs+to%2C+newest+first.%0AOnly+keys+that+are+usable+right+now+are+listed%3A+revoked+keys+and%0Aexpired+keys+are+filtered+o\u0026amp;theme=21e417d08933df01149b8e86\u0026amp;signature=8690b79697da401c7cba092b9424e2853188a2c5ce01a973fe2588bffcaa0302\">\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/api-keys/list-active-api-keys\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/api-keys/list-active-api-keys.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/api-keys/list-active-api-keys#webpage\",\"url\":\"https://docs.testorim.com/api-reference/api-keys/list-active-api-keys\",\"name\":\"List active API keys\",\"description\":\"Keys owned by the user the credential belongs to, newest first. Only keys that are usable right now are listed: revoked keys and expired keys are filtered out in SQL. Note the scoping difference from the rest of the API: this list is per-user, not per-organization, so it can include keys bound to other orgs the user belongs to. Each key carries orgId and orgName, the workspace it acts in. Plaintext is never returned, only prefix, the first 12 characters.\",\"dateModified\":\"2026-09-25T12:52:51.871Z\",\"isPartOf\":{\"@id\":\"https://docs.testorim.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.testorim.com/api-reference/api-keys/list-active-api-keys#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.testorim.com/api-reference/api-keys/list-active-api-keys#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 active API keys\",\"item\":\"https://docs.testorim.com/api-reference/api-keys/list-active-api-keys\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.testorim.com/api-reference/api-keys/list-active-api-keys#apireference\",\"headline\":\"List active API keys\",\"name\":\"List active API keys\",\"description\":\"Keys owned by the user the credential belongs to, newest first. Only keys that are usable right now are listed: revoked keys and expired keys are filtered out in SQL. Note the scoping difference from the rest of the API: this list is per-user, not per-organization, so it can include keys bound to other orgs the user belongs to. Each key carries orgId and orgName, the workspace it acts in. Plaintext is never returned, only prefix, the first 12 characters.\",\"url\":\"https://docs.testorim.com/api-reference/api-keys/list-active-api-keys\",\"mainEntityOfPage\":{\"@id\":\"https://docs.testorim.com/api-reference/api-keys/list-active-api-keys#webpage\"},\"dateModified\":\"2026-09-25T12:52:51.871Z\",\"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","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","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","description":"Org-scoped lookup. Archived (soft-deleted) projects are treated as missing and return `404`.","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)","description":"> **An API key cannot create another API key.** A request\n> authenticated with a key is refused `403` with\n> `code: \"api_key_scope\"` before it reaches the handler, deliberately\n> limiting the blast radius of a leaked key. Mint keys from the\n> dashboard at `/settings/api-keys` (which authenticates with a Clerk\n> session JWT). The operation is documented here for completeness,\n> not because CI can call it.\n\nThe new key is bound to the caller's user **and to their currently\nactive organization**, which then becomes the only org that key can\nact on.\n\nThe plaintext key is returned **once, in this response, and is never\nrecoverable.** Only its SHA-256 hash is stored. Copy it immediately.\n\n`expiresAt` accepts an ISO-8601 string or epoch milliseconds; it must\nparse and must be in the future.\n","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 active API keys - 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"]}