Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps//security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console “Automatic” prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an onboarding handle). If it can’t sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable specExtraction handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/ until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.
JWT login token tied to your Perfai user (not a separate API key). Obtain it via POST /api/v1/auth/token with your username and password (use the returned id_token) — the same login the web console performs. Carries org, user, and role; short-lived.
Advanced. A URL to your app's OpenAPI definition (or inline content) — provide it to skip discovery. Omit to let the platform map your API surface. REST/GraphQL is detected automatically.
Credentials for the primary tenant, one entry per role. Optional — omit to have the platform auto-create accounts (default), or for unauthenticated / public apps (with createTestAccounts=false). Each is stored as an encrypted auth record; admin/user/rbac roles are derived from the set.
Whether the platform autonomously creates test accounts (auto sign-up) when no credentials are supplied — mirroring the console "Automatic" onboarding. Default true. Only applies when BOTH credentials AND spec are omitted; ignored otherwise. Set false to register for an unauthenticated (public-endpoint-only) test — no accounts are created, so authenticated / RBAC / cross-tenant (BOLA) tests will not run.
Endpoints to exclude from every security test of this app, as "method:path" entries. Use it to keep destructive or disruptive operations out of scope — account deletion, logout, payment capture. Method may be a verb or "*"; path may use "**" as a glob. Applied as a blocklist, only when no include-filter is in force for the run.
Extra HTTP headers sent with requests to the application under test, as "Name: value" entries — a gateway API key, a tenant selector, a feature flag the app requires. Sent as supplied; never returned by the API.
How many exploration steps the platform may take while mapping your API surface. Raise it for large apps with deep navigation or many nested workflows — a mapping missing endpoints is the usual reason to. Higher values map more thoroughly but lengthen registration. Applies only when the platform maps the app itself (no spec supplied). Omit to use your organization's configured value, which itself defaults to 150.
Returned as IN_PROGRESS. The platform completes onboarding on its own; poll GET /apps/{appId} until COMPLETED. Registration is NOT completed by a security test — a test requires COMPLETED as a precondition.
Present only on the createTestAccounts=false no-spec path. Absent when a spec/credentials were supplied, auto-signup ran, or the vision run could not be enqueued.
Present when this registration replaced a previous, unusable app for the same URL (INTERRUPTED/NEEDS_INPUT/COMPLETED_PARTIAL/CANCELLED/PENDING, or a stuck IN_PROGRESS). A COMPLETED or actively-onboarding app is reused via 409 instead.
{ "appId": "<string>", "registrationStatus": "PENDING", "reason": "needs_login", "message": "We hit a snag — we're on it. Your results so far are saved.", "createdAt": "2023-11-07T05:31:56Z", "statusUrl": "<string>", "onboarding": { "mode": "auto-signup", "message": "<string>" }, "specExtraction": { "taskId": "<string>", "state": "QUEUED", "statusUrl": "<string>" }, "replaced": { "previousAppId": "<string>", "previousStatus": "PENDING" }}
{
"type": "<string>",
"title": "<string>"
}
{
"type": "<string>",
"title": "<string>"
}
{
"type": "<string>",
"title": "<string>"
}
{
"type": "<string>",
"title": "<string>"
}
{
"type": "<string>",
"title": "<string>"
}
{
"type": "<string>",
"title": "<string>"
}
{"docsConfig":{"theme":"luma","$schema":"https://mintlify.com/docs.json","name":"Perfai Security","colors":{"primary":"#ff56c9","light":"#ff9fde","dark":"#c93aa1"},"logo":{"light":"https://mintcdn.com/perfai/rTwm4ELrRh_6V5IS/logo/perfai-logo-light.png?fit=max\u0026auto=format\u0026n=rTwm4ELrRh_6V5IS\u0026q=85\u0026s=3def10cdef84b39c43037fec38395427","dark":"https://mintcdn.com/perfai/rTwm4ELrRh_6V5IS/logo/perfai-logo-pink.png?fit=max\u0026auto=format\u0026n=rTwm4ELrRh_6V5IS\u0026q=85\u0026s=328b75a61f5972d17bf41fd269cac7f1"},"favicon":"https://mintcdn.com/perfai/rTwm4ELrRh_6V5IS/favicon.svg?fit=max\u0026auto=format\u0026n=rTwm4ELrRh_6V5IS\u0026q=85\u0026s=2a9cfa43dd799782a41bd8691a8dce08","appearance":{"default":"dark","strict":true},"navbar":{"links":[{"href":"https://cloud.perfai.ai","label":"Dashboard"}],"primary":{"type":"button","label":"Get Started Free","href":"https://cloud.perfai.ai/signup"}},"footer":{"socials":{"x":"https://x.com/perfai_security","github":"https://github.com/PerfAI-Inc","linkedin":"https://linkedin.com/company/perfai"}},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","mcp","cursor","vscode"],"display":"header"},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"Dashboard","icon":"gauge","href":"https://cloud.perfai.ai"},{"anchor":"Website","icon":"globe","href":"https://perfai.ai"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"perfai","hasAudioNarration":false,"actualSubdomain":"perfai","customDomains":["docs.perfai.ai"],"gitSource":{"type":"github","owner":"perfai-inc","repo":"public-docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"collectionId":"98a24eb1-ba2b-4ce9-9fc0-2760cb1fea26","liveDeploymentHistoryId":"6ae0588e0c6a21c62ee242f4","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae0588e0c6a21c62ee242f4"},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ae0588e0c6a21c62ee242f4","clientVersion":"0.0.3990","searchFilterCounts":[{"language":"default","tag":"Core Concepts","count":48},{"language":"default","tag":"API","count":17},{"language":"default","tag":"AI Agents","count":17},{"language":"default","tag":"Reference","count":15},{"language":"default","tag":"Apps","count":6},{"language":"default","tag":"Reports","count":2},{"language":"default","tag":"Getting Started","count":2},{"language":"default","tag":"Changelog","count":1},{"language":"default","tag":"Hybrid Deployment","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"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":"editor-v7-file-tree","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":"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":"pause-universal-search-reconcile","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":"per-site-search-delta","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":"editor-private-page-search","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":"editor-nav-generations","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":"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":"byok-sep-25","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":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","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":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"isAtlas":false,"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":".docs-frame-img{display:block!important;width:100%!important;height:auto!important}"}],"page":{"pagePath":"api-reference/apps/register-app","slug":"/api-reference/apps/register-app","pageMetadata":{"title":"Register app","description":"Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps/{appId}/security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console \"Automatic\" prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an `onboarding` handle). If it can't sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable `specExtraction` handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/{appId} until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /apps","href":"/api-reference/apps/register-app","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: [\"Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps/\", \"/security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console “Automatic” prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an \", _jsx(_components.code, {\n children: \"onboarding\"\n }), \" handle). If it can’t sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable \", _jsx(_components.code, {\n children: \"specExtraction\"\n }), \" handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/\", \" until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.\"]\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":"Register app","description":"Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps/{appId}/security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console \"Automatic\" prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an `onboarding` handle). If it can't sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable `specExtraction` handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/{appId} until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /apps","href":"/api-reference/apps/register-app","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"tags":["Apps"],"operationId":"registerApp","summary":"Register app","description":"Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps/{appId}/security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console \"Automatic\" prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an `onboarding` handle). If it can't sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable `specExtraction` handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/{appId} until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.\n","requestBody":"bc5c0e1d-66f9-419d-af88-a631a36a5be2","responses":{"201":"5c39e5c5-ec6c-4fae-b1cb-c6285487a178","400":"ec28c434-fc77-487a-8d33-db2a7a8173f9","401":"d955fca9-ac72-4153-a138-209499095abc","402":"0672e461-267f-44b5-b353-f7fe2179741b","403":"fa53c95c-ecef-4b2c-8655-67826250b3b0","409":"c9619b5d-3d8a-470b-b936-e6b6d2b14fac","429":"76e98d89-bb19-4b75-9592-8292f764164b","500":"81efa4cb-5a52-4871-b952-30098eec28f0","503":"c63654f1-b026-4842-8a16-1d464fa3cda4"},"method":"post","type":"path","servers":["0d9567ed-83da-4d4a-8f66-24c2c310e39e","f6b1966e-37d4-4d2f-b6f4-5a3061f5bebb"],"security":["b23a3729-6dbc-496a-bec4-227020cc8717"],"path":"/apps","baseUrlOptions":["https://api.perfai.ai/v1","https://api.{customerDomain}/v1"],"title":"Register app","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["appUrl"],"additionalProperties":false,"properties":{"appUrl":{"type":"string","format":"uri","maxLength":2048,"description":"Base URL of the application under test (http/https).","isRequired":true,"uniqueKey":"appUrl","typeLabel":"string\u003curi>"},"label":{"type":"string","maxLength":150,"description":"Human-readable app name. Optional — defaults to the host of appUrl when omitted.","uniqueKey":"label","typeLabel":"string"},"spec":{"oneOf":[{"type":"string","maxLength":2000000,"description":"Advanced. A URL to your app's OpenAPI definition (or inline content) — provide it to skip discovery. Omit to let the platform map your API surface. REST/GraphQL is detected automatically.","uniqueKey":"spec.oneOf.0","typeLabel":"string"},{"type":"null","maxLength":2000000,"description":"Advanced. A URL to your app's OpenAPI definition (or inline content) — provide it to skip discovery. Omit to let the platform map your API surface. REST/GraphQL is detected automatically.","uniqueKey":"spec.oneOf.1","typeLabel":"null"}],"uniqueKey":"spec","typeLabel":"string | null"},"tenantOneCredentials":{"type":"array","maxItems":20,"items":{"type":"object","required":["role","username","password"],"additionalProperties":false,"description":"One authentication for a tenant: a role plus its username/password login. The API style (REST vs GraphQL) is detected automatically.\n","properties":{"role":{"type":"string","maxLength":100,"description":"Role this login represents (e.g. \"Admin\", \"User\", or a custom RBAC role). Drives privilege derivation and role-based access testing.","isRequired":true,"uniqueKey":"tenantOneCredentials.items.[INDEX].role","typeLabel":"string"},"username":{"type":"string","maxLength":320,"description":"Username or email used to authenticate.","isRequired":true,"uniqueKey":"tenantOneCredentials.items.[INDEX].username","typeLabel":"string"},"password":{"type":"string","maxLength":1024,"description":"Password. Encrypted at rest; never logged or returned.","isRequired":true,"uniqueKey":"tenantOneCredentials.items.[INDEX].password","typeLabel":"string"},"loginUrl":{"type":"string","format":"uri","maxLength":2048,"description":"URL where these credentials authenticate. Defaults to the app URL.","uniqueKey":"tenantOneCredentials.items.[INDEX].loginUrl","typeLabel":"string\u003curi>"}},"uniqueKey":"tenantOneCredentials.items.[INDEX]","typeLabel":"object"},"description":"Credentials for the primary tenant, one entry per role. Optional — omit to have the platform auto-create accounts (default), or for unauthenticated / public apps (with createTestAccounts=false). Each is stored as an encrypted auth record; admin/user/rbac roles are derived from the set.\n","uniqueKey":"tenantOneCredentials","typeLabel":"object[]"},"tenantTwoCredentials":{"type":"array","maxItems":20,"items":{"type":"object","required":["role","username","password"],"additionalProperties":false,"description":"One authentication for a tenant: a role plus its username/password login. The API style (REST vs GraphQL) is detected automatically.\n","properties":{"role":{"type":"string","maxLength":100,"description":"Role this login represents (e.g. \"Admin\", \"User\", or a custom RBAC role). Drives privilege derivation and role-based access testing.","isRequired":true,"uniqueKey":"tenantTwoCredentials.items.[INDEX].role","typeLabel":"string"},"username":{"type":"string","maxLength":320,"description":"Username or email used to authenticate.","isRequired":true,"uniqueKey":"tenantTwoCredentials.items.[INDEX].username","typeLabel":"string"},"password":{"type":"string","maxLength":1024,"description":"Password. Encrypted at rest; never logged or returned.","isRequired":true,"uniqueKey":"tenantTwoCredentials.items.[INDEX].password","typeLabel":"string"},"loginUrl":{"type":"string","format":"uri","maxLength":2048,"description":"URL where these credentials authenticate. Defaults to the app URL.","uniqueKey":"tenantTwoCredentials.items.[INDEX].loginUrl","typeLabel":"string\u003curi>"}},"uniqueKey":"tenantTwoCredentials.items.[INDEX]","typeLabel":"object"},"description":"Credentials for a second tenant, used for cross-tenant (BOLA) testing. Optional.","uniqueKey":"tenantTwoCredentials","typeLabel":"object[]"},"createTestAccounts":{"type":"boolean","default":true,"description":"Whether the platform autonomously creates test accounts (auto sign-up) when no credentials are supplied — mirroring the console \"Automatic\" onboarding. Default true. Only applies when BOTH credentials AND spec are omitted; ignored otherwise. Set false to register for an unauthenticated (public-endpoint-only) test — no accounts are created, so authenticated / RBAC / cross-tenant (BOLA) tests will not run.\n","uniqueKey":"createTestAccounts","typeLabel":"boolean"},"skipEndpoints":{"type":"array","maxItems":200,"items":{"type":"string","maxLength":500,"pattern":"^(\\*|[A-Za-z]+):[^:]+$","uniqueKey":"skipEndpoints.items.[INDEX]","typeLabel":"string"},"description":"Endpoints to exclude from every security test of this app, as \"method:path\" entries. Use it to keep destructive or disruptive operations out of scope — account deletion, logout, payment capture. Method may be a verb or \"*\"; path may use \"**\" as a glob. Applied as a blocklist, only when no include-filter is in force for the run.\n","example":["DELETE:/api/v1/users/{id}","POST:/api/v1/payments/capture","*:/internal/**"],"uniqueKey":"skipEndpoints","typeLabel":"string[]"},"headers":{"type":"array","maxItems":50,"items":{"type":"string","maxLength":4096,"uniqueKey":"headers.items.[INDEX]","typeLabel":"string"},"description":"Extra HTTP headers sent with requests to the application under test, as \"Name: value\" entries — a gateway API key, a tenant selector, a feature flag the app requires. Sent as supplied; never returned by the API.\n","example":["X-Api-Key: 9f8c1e02-5b6a-4b1e","X-Tenant-Id: acme"],"uniqueKey":"headers","typeLabel":"string[]"},"maxSteps":{"type":"integer","minimum":1,"maximum":1000,"description":"How many exploration steps the platform may take while mapping your API surface. Raise it for large apps with deep navigation or many nested workflows — a mapping missing endpoints is the usual reason to. Higher values map more thoroughly but lengthen registration. Applies only when the platform maps the app itself (no `spec` supplied). Omit to use your organization's configured value, which itself defaults to 150.\n","example":300,"uniqueKey":"maxSteps","typeLabel":"integer"}},"uniqueKey":"","typeLabel":"object"},"examples":{"minimal":{"title":"minimal","value":{"label":"Payments App","appUrl":"https://payments.example.com"}},"unauthenticated":{"title":"unauthenticated","value":{"label":"Payments App","appUrl":"https://payments.example.com","createTestAccounts":false}},"withCredentials":{"title":"withCredentials","value":{"label":"Payments App","appUrl":"https://payments.example.com","tenantOneCredentials":[{"role":"Admin","username":"admin@example.com","password":"••••••••"},{"role":"User","username":"user@example.com","password":"••••••••"}],"tenantTwoCredentials":[{"role":"Admin","username":"tenant2-admin@example.com","password":"••••••••"}]}},"specFirst":{"title":"specFirst","value":{"label":"Payments App","appUrl":"https://payments.example.com","spec":"https://payments.example.com/openapi.json"}}},"exampleType":"examples"}},"exampleType":"examples"},"responses":{"5c39e5c5-ec6c-4fae-b1cb-c6285487a178":{"description":"App registered; onboarding in progress.","headers":{"Location":{"description":"URL of the created app resource (poll for registrationStatus).","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"appId":{"type":"string","uniqueKey":"appId","typeLabel":"string"},"registrationStatus":{"type":"string","description":"Returned as IN_PROGRESS. The platform completes onboarding on its own; poll GET /apps/{appId} until COMPLETED. Registration is NOT completed by a security test — a test requires COMPLETED as a precondition.\n","enum":["PENDING","IN_PROGRESS","NEEDS_INPUT","COMPLETED","COMPLETED_PARTIAL","INTERRUPTED","CANCELLED"],"uniqueKey":"registrationStatus","typeLabel":"enum\u003cstring>"},"reason":{"oneOf":[{"type":"string","description":"Why a task or app is in its state. Null when the state needs no explanation. New values may be added; show `message` for any you do not recognise.\n","enum":["needs_login","needs_roles","needs_access","needs_app_url","needs_spec","app_unreachable","out_of_credits","no_response","paused","partial_coverage","our_side_error","dependency_lost",null],"uniqueKey":"reason.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","description":"Why a task or app is in its state. Null when the state needs no explanation. New values may be added; show `message` for any you do not recognise.\n","enum":["needs_login","needs_roles","needs_access","needs_app_url","needs_spec","app_unreachable","out_of_credits","no_response","paused","partial_coverage","our_side_error","dependency_lost",null],"uniqueKey":"reason.oneOf.1","typeLabel":"null"}],"uniqueKey":"reason","typeLabel":"enum\u003cstring> | null"},"message":{"type":"string","description":"One sentence for the user — the same wording the console shows for this state.","example":"We hit a snag — we're on it. Your results so far are saved.","uniqueKey":"message","typeLabel":"string"},"createdAt":{"type":"string","format":"date-time","uniqueKey":"createdAt","typeLabel":"string\u003cdate-time>"},"statusUrl":{"type":"string","uniqueKey":"statusUrl","typeLabel":"string"},"onboarding":{"oneOf":[{"type":"object","description":"Present on the default auto-signup path.","properties":{"mode":{"type":"string","example":"auto-signup","description":"Onboarding mode driving this registration.","uniqueKey":"onboarding.oneOf.0.mode","typeLabel":"string"},"message":{"type":"string","description":"Human-readable note on what the platform is doing.","uniqueKey":"onboarding.oneOf.0.message","typeLabel":"string"}},"uniqueKey":"onboarding.oneOf.0","typeLabel":"object"},{"type":"null","description":"Present on the default auto-signup path.","uniqueKey":"onboarding.oneOf.1","typeLabel":"null"}],"uniqueKey":"onboarding","typeLabel":"object | null"},"specExtraction":{"oneOf":[{"type":"object","description":"Present only on the createTestAccounts=false no-spec path. Absent when a spec/credentials were supplied, auto-signup ran, or the vision run could not be enqueued.","properties":{"taskId":{"type":"string","uniqueKey":"specExtraction.oneOf.0.taskId","typeLabel":"string"},"state":{"type":"string","description":"Same vocabulary as TaskState. Never FAILED.","enum":["QUEUED","RUNNING","NEEDS_INPUT","COMPLETED","COMPLETED_PARTIAL","INTERRUPTED","CANCELLED"],"uniqueKey":"specExtraction.oneOf.0.state","typeLabel":"enum\u003cstring>"},"statusUrl":{"type":"string","description":"Poll this until the vision run reaches COMPLETED.","uniqueKey":"specExtraction.oneOf.0.statusUrl","typeLabel":"string"}},"uniqueKey":"specExtraction.oneOf.0","typeLabel":"object"},{"type":"null","description":"Present only on the createTestAccounts=false no-spec path. Absent when a spec/credentials were supplied, auto-signup ran, or the vision run could not be enqueued.","uniqueKey":"specExtraction.oneOf.1","typeLabel":"null"}],"uniqueKey":"specExtraction","typeLabel":"object | null"},"replaced":{"oneOf":[{"type":"object","description":"Present when this registration replaced a previous, unusable app for the same URL (INTERRUPTED/NEEDS_INPUT/COMPLETED_PARTIAL/CANCELLED/PENDING, or a stuck IN_PROGRESS). A COMPLETED or actively-onboarding app is reused via 409 instead.\n","properties":{"previousAppId":{"type":"string","uniqueKey":"replaced.oneOf.0.previousAppId","typeLabel":"string"},"previousStatus":{"type":"string","description":"The replaced app's state: INTERRUPTED, NEEDS_INPUT, COMPLETED_PARTIAL, CANCELLED, PENDING, or a stuck IN_PROGRESS.","enum":["PENDING","IN_PROGRESS","NEEDS_INPUT","COMPLETED","COMPLETED_PARTIAL","INTERRUPTED","CANCELLED"],"uniqueKey":"replaced.oneOf.0.previousStatus","typeLabel":"enum\u003cstring>"}},"uniqueKey":"replaced.oneOf.0","typeLabel":"object"},{"type":"null","description":"Present when this registration replaced a previous, unusable app for the same URL (INTERRUPTED/NEEDS_INPUT/COMPLETED_PARTIAL/CANCELLED/PENDING, or a stuck IN_PROGRESS). A COMPLETED or actively-onboarding app is reused via 409 instead.\n","uniqueKey":"replaced.oneOf.1","typeLabel":"null"}],"uniqueKey":"replaced","typeLabel":"object | null"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"appId":"\u003cstring>","registrationStatus":"PENDING","reason":"needs_login","message":"We hit a snag — we're on it. Your results so far are saved.","createdAt":"2023-11-07T05:31:56Z","statusUrl":"\u003cstring>","onboarding":{"mode":"auto-signup","message":"\u003cstring>"},"specExtraction":{"taskId":"\u003cstring>","state":"QUEUED","statusUrl":"\u003cstring>"},"replaced":{"previousAppId":"\u003cstring>","previousStatus":"PENDING"}}}},"exampleType":"generated"}},"exampleType":"generated"},"ec28c434-fc77-487a-8d33-db2a7a8173f9":{"description":"Validation error.","content":{"application/problem+json":{"schema":{"type":"object","description":"RFC 9457 Problem Details.","properties":{"type":{"type":"string","description":"Error type URI, e.g. https://perfai.ai/errors/app-already-registered","uniqueKey":"type","typeLabel":"string"},"title":{"type":"string","uniqueKey":"title","typeLabel":"string"}},"additionalProperties":true,"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"type":"\u003cstring>","title":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"},"d955fca9-ac72-4153-a138-209499095abc":{"description":"Missing or expired JWT.","content":{"_mintlify/placeholder":{"schema":{"type":"object","description":""}}}},"0672e461-267f-44b5-b353-f7fe2179741b":{"description":"Organization credit balance exhausted (billing-enabled deployments only).","content":{"application/problem+json":{"schema":{"type":"object","description":"RFC 9457 Problem Details.","properties":{"type":{"type":"string","description":"Error type URI, e.g. https://perfai.ai/errors/app-already-registered","uniqueKey":"type","typeLabel":"string"},"title":{"type":"string","uniqueKey":"title","typeLabel":"string"}},"additionalProperties":true,"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"type":"\u003cstring>","title":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"},"fa53c95c-ecef-4b2c-8655-67826250b3b0":{"description":"Caller's role does not permit this operation (Viewer is read-only).","content":{"application/problem+json":{"schema":{"type":"object","description":"RFC 9457 Problem Details.","properties":{"type":{"type":"string","description":"Error type URI, e.g. https://perfai.ai/errors/app-already-registered","uniqueKey":"type","typeLabel":"string"},"title":{"type":"string","uniqueKey":"title","typeLabel":"string"}},"additionalProperties":true,"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"type":"\u003cstring>","title":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"},"c9619b5d-3d8a-470b-b936-e6b6d2b14fac":{"description":"A usable app (COMPLETED, or actively onboarding) already exists for this URL — app-already-registered, includes the existing appId to reuse. A stopped app (INTERRUPTED, NEEDS_INPUT, COMPLETED_PARTIAL or CANCELLED, or a long-stuck IN_PROGRESS) is replaced with a fresh 201 instead (see the `replaced` field). If an app for this URL exists that was not registered through this API, it is never replaced — app-registered-outside-api.\n","content":{"application/problem+json":{"schema":{"type":"object","description":"RFC 9457 Problem Details.","properties":{"type":{"type":"string","description":"Error type URI, e.g. https://perfai.ai/errors/app-already-registered","uniqueKey":"type","typeLabel":"string"},"title":{"type":"string","uniqueKey":"title","typeLabel":"string"}},"additionalProperties":true,"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"type":"\u003cstring>","title":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"},"76e98d89-bb19-4b75-9592-8292f764164b":{"description":"Rate limit exceeded. Back off and retry after the Retry-After header value.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."}},"content":{"_mintlify/placeholder":{"schema":{"type":"object","description":""}}}},"81efa4cb-5a52-4871-b952-30098eec28f0":{"description":"registration-failed — the app was not registered; retry the request.","content":{"application/problem+json":{"schema":{"type":"object","description":"RFC 9457 Problem Details.","properties":{"type":{"type":"string","description":"Error type URI, e.g. https://perfai.ai/errors/app-already-registered","uniqueKey":"type","typeLabel":"string"},"title":{"type":"string","uniqueKey":"title","typeLabel":"string"}},"additionalProperties":true,"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"type":"\u003cstring>","title":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"},"c63654f1-b026-4842-8a16-1d464fa3cda4":{"description":"onboarding-unavailable — this deployment does not have the onboarding workflow engine enabled, so autonomous sign-up cannot run. Register with a `spec` or with tenant credentials instead.\n","content":{"application/problem+json":{"schema":{"type":"object","description":"RFC 9457 Problem Details.","properties":{"type":{"type":"string","description":"Error type URI, e.g. https://perfai.ai/errors/app-already-registered","uniqueKey":"type","typeLabel":"string"},"title":{"type":"string","uniqueKey":"title","typeLabel":"string"}},"additionalProperties":true,"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"type":"\u003cstring>","title":"\u003cstring>"}}},"exampleType":"generated"}},"exampleType":"generated"}},"security":{"b23a3729-6dbc-496a-bec4-227020cc8717":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT login token tied to your Perfai user (not a separate API key). Obtain it via POST /api/v1/auth/token with your username and password (use the returned id_token) — the same login the web console performs. Carries org, user, and role; short-lived.\n","scopes":[],"schemeName":"bearerAuth"}}},"servers":{"0d9567ed-83da-4d4a-8f66-24c2c310e39e":{"url":"https://api.perfai.ai/v1","description":"Perfai cloud"},"f6b1966e-37d4-4d2f-b6f4-5a3061f5bebb":{"url":"https://api.{customerDomain}/v1","description":"On-premise deployment","variables":{"customerDomain":{"default":"example.com"}}}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT login token tied to your Perfai user (not a separate API key). Obtain it via POST /api/v1/auth/token with your username and password (use the returned id_token) — the same login the web console performs. Carries org, user, and role; short-lived.\n","scopes":[],"schemeName":"bearerAuth"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"JWT login token tied to your Perfai user (not a separate API key). Obtain it via POST /api/v1/auth/token with your username and password (use the returned id_token) — the same login the web console performs. Carries org, user, and role; short-lived.\n","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"bearerAuth","name":"Authorization"}],"title":"bearerAuth"}]},"originalFileLocation":"api-reference/openapi.yaml"},"subdomain":"perfai","siteName":"Perfai Security","title":"Register app - Perfai Security","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-23T13:24:38.855Z","originalFileLocation":"api-reference/apps/register-app.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=\"dark\";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=\"dark\"}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=\"Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps/{appId}/security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console \u0026quot;Automatic\u0026quot; prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an onboarding handle). If it can\u0026#x27;t sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable specExtraction handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/{appId} until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Perfai Security\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/perfai/O3_pF7bfPTnfLXzH/_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/perfai/O3_pF7bfPTnfLXzH/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/perfai/O3_pF7bfPTnfLXzH/_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/perfai/O3_pF7bfPTnfLXzH/_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/perfai/O3_pF7bfPTnfLXzH/_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/perfai/O3_pF7bfPTnfLXzH/_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/perfai/O3_pF7bfPTnfLXzH/_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/perfai/O3_pF7bfPTnfLXzH/_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/perfai/O3_pF7bfPTnfLXzH/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Register app - Perfai Security\">\u003cmeta data-mint-head property=\"og:description\" content=\"Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps/{appId}/security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console \u0026quot;Automatic\u0026quot; prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an onboarding handle). If it can\u0026#x27;t sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable specExtraction handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/{appId} until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Perfai Security\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.perfai.ai/api-reference/apps/register-app\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://perfai.mintlify.app/_mintlify/api/og/v2?division=Reference\u0026amp;title=Register+app\u0026amp;description=Registers+a+target+app+and+drives+it+to+a+testable+state.+No+security+test+is+auto-triggered+%E2%80%94+trigger+tests+explicitly+via+POST+%2Fapps%2F%7BappId%7D%2Fsecurity-agent.+O\u0026amp;theme=0b2278042ba83ad617564bbf\u0026amp;signature=ca6d91b2db09cb203fc5b0e66acee70215fae36a412084f40be17af2c9b360f8\">\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=\"Register app - Perfai Security\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps/{appId}/security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console \u0026quot;Automatic\u0026quot; prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an onboarding handle). If it can\u0026#x27;t sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable specExtraction handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/{appId} until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://perfai.mintlify.app/_mintlify/api/og/v2?division=Reference\u0026amp;title=Register+app\u0026amp;description=Registers+a+target+app+and+drives+it+to+a+testable+state.+No+security+test+is+auto-triggered+%E2%80%94+trigger+tests+explicitly+via+POST+%2Fapps%2F%7BappId%7D%2Fsecurity-agent.+O\u0026amp;theme=0b2278042ba83ad617564bbf\u0026amp;signature=ca6d91b2db09cb203fc5b0e66acee70215fae36a412084f40be17af2c9b360f8\">\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/perfai/O3_pF7bfPTnfLXzH/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Perfai Security\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#ff56c9\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.perfai.ai/api-reference/apps/register-app\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/apps/register-app.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.perfai.ai/#organization\",\"name\":\"Perfai Security\",\"url\":\"https://docs.perfai.ai\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/perfai/rTwm4ELrRh_6V5IS/logo/perfai-logo-light.png?fit=max\u0026auto=format\u0026n=rTwm4ELrRh_6V5IS\u0026q=85\u0026s=3def10cdef84b39c43037fec38395427\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.perfai.ai#website\",\"name\":\"Perfai Security\",\"url\":\"https://docs.perfai.ai\",\"publisher\":{\"@id\":\"https://docs.perfai.ai/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.perfai.ai/api-reference/apps/register-app#webpage\",\"url\":\"https://docs.perfai.ai/api-reference/apps/register-app\",\"name\":\"Register app\",\"description\":\"Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps/{appId}/security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console \\\"Automatic\\\" prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an onboarding handle). If it can't sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable specExtraction handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/{appId} until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.\",\"dateModified\":\"2026-10-23T13:24:38.855Z\",\"isPartOf\":{\"@id\":\"https://docs.perfai.ai#website\"},\"breadcrumb\":{\"@id\":\"https://docs.perfai.ai/api-reference/apps/register-app#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.perfai.ai/api-reference/apps/register-app#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Core Concepts\",\"item\":\"https://docs.perfai.ai/docs/core-concepts/apps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"API\",\"item\":\"https://docs.perfai.ai/docs/api/overview\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Reference\",\"item\":\"https://docs.perfai.ai/api-reference/apps/list-apps\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Register app\",\"item\":\"https://docs.perfai.ai/api-reference/apps/register-app\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.perfai.ai/api-reference/apps/register-app#apireference\",\"headline\":\"Register app\",\"name\":\"Register app\",\"description\":\"Registers a target app and drives it to a testable state. No security test is auto-triggered — trigger tests explicitly via POST /apps/{appId}/security-agent. Onboarding depends on the input: (a) URL only, no credentials, no spec (the DEFAULT, createTestAccounts not false) — the platform runs full autonomous onboarding like the console \\\"Automatic\\\" prompt: it creates test accounts (auto sign-up), validates logins, discovers roles, provisions RBAC accounts, maps the app and completes registration (response carries an onboarding handle). If it can't sign up (no public sign-up / CAPTCHA / SSO / unreachable) it pauses and emails the caller rather than degrading to an unauthenticated test. (b) credentials and/or a spec supplied — the platform uses them and schedules the registration-completing run. (c) createTestAccounts=false with no spec — a browserless pass maps your API surface (pollable specExtraction handle) for an unauthenticated test. The app resource is created synchronously (201 + Location header) with registrationStatus IN_PROGRESS; poll GET /apps/{appId} until registrationStatus is COMPLETED, then trigger a test. Registration is completed by onboarding, not by a security test. Supplied credentials are stored encrypted and never returned.\",\"url\":\"https://docs.perfai.ai/api-reference/apps/register-app\",\"mainEntityOfPage\":{\"@id\":\"https://docs.perfai.ai/api-reference/apps/register-app#webpage\"},\"dateModified\":\"2026-10-23T13:24:38.855Z\",\"publisher\":{\"@id\":\"https://docs.perfai.ai/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.perfai.ai#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Perfai Security\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Perfai Security","nav":{"global":{"anchors":[{"anchor":"Dashboard","icon":"gauge","href":"https://cloud.perfai.ai"},{"anchor":"Website","icon":"globe","href":"https://perfai.ai"}]},"pages":[{"group":"Getting Started","pages":[{"title":"Introduction","href":"/docs/introduction"},{"title":"Quickstart","href":"/docs/quickstart"}]},{"group":"Core Concepts","pages":[{"group":"Apps","pages":[{"title":"Apps","href":"/docs/core-concepts/apps"},{"title":"What Perfai scans","href":"/docs/core-concepts/what-perfai-scans"},{"title":"Bring Your Own Accounts","href":"/docs/use-cases/bring-your-own-accounts"},{"title":"Apps Without Public Sign-Up","href":"/docs/use-cases/private-signup-apps"},{"title":"Internal App Support","href":"/docs/use-cases/internal-app-support"},{"title":"Managing an App","href":"/docs/use-cases/managing-an-app"}]},{"title":"Insights","href":"/docs/core-concepts/insights"},{"title":"Issues","href":"/docs/core-concepts/issues"},{"group":"Reports","pages":[{"title":"Reports","href":"/docs/core-concepts/reports"},{"title":"Sample Security Report","href":"/docs/sample-security-report"}]},{"title":"Integrations","href":"/docs/core-concepts/integrations"},{"group":"AI Agents","pages":[{"title":"Perfai Cloud MCP Server","href":"/docs/mcp/overview"},{"title":"Claude Code","href":"/docs/mcp/claude-code"},{"title":"Claude","href":"/docs/mcp/claude"},{"title":"Cursor","href":"/docs/mcp/cursor"},{"title":"Replit","href":"/docs/mcp/replit"},{"title":"Lovable","href":"/docs/mcp/lovable"},{"title":"Bolt","href":"/docs/mcp/bolt"},{"title":"IBM Bob","href":"/docs/mcp/bob"},{"title":"VS Code (Copilot Agent Mode)","href":"/docs/mcp/vscode"},{"title":"Windsurf","href":"/docs/mcp/windsurf"},{"title":"Postman","href":"/docs/mcp/postman"},{"title":"Zed","href":"/docs/mcp/zed"},{"title":"AWS Kiro","href":"/docs/mcp/aws-kiro"},{"title":"Cline","href":"/docs/mcp/cline"},{"title":"LM Studio","href":"/docs/mcp/lm-studio"},{"title":"Continue.dev","href":"/docs/mcp/continue-dev"},{"title":"Generic MCP client","href":"/docs/mcp/generic"}]},{"group":"API","pages":[{"title":"Overview","href":"/docs/api/overview"},{"title":"Guide","href":"/docs/api/api-reference"},{"group":"Reference","pages":[{"title":"List apps","description":"Returns apps visible to the authenticated tenant, paginated, newest first.","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /apps","href":"/api-reference/apps/list-apps"},{"title":"Register app","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /apps","href":"/api-reference/apps/register-app"},{"title":"Get app (poll registration)","description":"Returns a single app including registrationStatus, with `reason` and `message` explaining it. Stop polling on COMPLETED, COMPLETED_PARTIAL, NEEDS_INPUT, INTERRUPTED or CANCELLED.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /apps/{appId}","href":"/api-reference/apps/get-app-poll-registration"},{"title":"Delete app","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /apps/{appId}","href":"/api-reference/apps/delete-app"},{"title":"Run Account Setup","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /apps/{appId}/account-setup","href":"/api-reference/apps/run-account-setup"},{"title":"Run Vision Agent","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /apps/{appId}/vision-agent","href":"/api-reference/vision-agent/run-vision-agent"},{"title":"Run Security Agent","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /apps/{appId}/security-agent","href":"/api-reference/security-agent/run-security-agent"},{"title":"Get task status","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /tasks/{taskId}","href":"/api-reference/tasks/get-task-status"},{"title":"Get vulnerabilities","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /apps/{appId}/vulnerabilities","href":"/api-reference/vulnerabilities/get-vulnerabilities"},{"title":"Get vulnerability","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /vulnerabilities/{vulnerabilityId}","href":"/api-reference/vulnerabilities/get-vulnerability"},{"title":"Dismiss vulnerability","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /vulnerabilities/{vulnerabilityId}/dismiss","href":"/api-reference/vulnerabilities/dismiss-vulnerability"},{"title":"Mark vulnerability fixed","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /vulnerabilities/{vulnerabilityId}/fix","href":"/api-reference/vulnerabilities/mark-vulnerability-fixed"},{"title":"Reopen vulnerability","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /vulnerabilities/{vulnerabilityId}/reopen","href":"/api-reference/vulnerabilities/reopen-vulnerability"},{"title":"Get reports","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /apps/{appId}/reports","href":"/api-reference/reports/get-reports"},{"title":"Download report","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /reports/{reportId}","href":"/api-reference/reports/download-report"}]}]},{"title":"Users","href":"/docs/core-concepts/users"},{"title":"Settings","href":"/docs/core-concepts/settings"},{"title":"Plans \u0026 Limits","href":"/docs/plans-and-limits"}]},{"group":"Hybrid Deployment","pages":[{"title":"Private Agents","href":"/docs/private-agents"}]},{"group":"Changelog","pages":[{"title":"Changelog","href":"/docs/changelog"}]}]},"title":"Register app - Perfai Security","buildId":"dpl_2oYXwqkEXirXBPk8wV1FtM5USFWi","deploymentId":"dpl_2oYXwqkEXirXBPk8wV1FtM5USFWi","dynamics":["c2aa737661","b0f84f53ff","a9bb46feb3","2b790eda92"],"chunks":["OpenApiReferenceProvider-WRhTSUDL.js","utils-ChMov4Kr.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-_REmC2bI.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-Bp6nVRCu.js","snippetPresets-DZadmXoU.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","Page-R3M_BF4L.js","ApiExamples-CY2WdoTl.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-DwYG-Q4l.js","shallow-BXQIGwv4.js","getApiPlaygroundDisplay-CK5nK5B9.js","CodeSnippet-TH4a2aGW.js","CodeSnippets-DwsQiOFS.js","getPastedJson-DD7kUzi_.js","icon-holE3QoJ.js","MethodPill-DUW0T8us.js","DuplicateIcon-CI_p4be-.js","createIcon-BdbRvavb.js","DynamicMarkdown-DN96a4Ur.js","SectionHeading-SCu36A9d.js","axios-vUo_bRtp.js","Markdown-CCeGv-zI.js","clsx-BGBGWFTt.js","lib--scc4DXi.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-Cv_O2fky.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-2C5OB2eV.js"]}