{"openapi":"3.0.0","paths":{"/":{"get":{"operationId":"RootController_index[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["internal"]}},"/v1":{"get":{"operationId":"RootController_index[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["internal"]}},"/tick":{"get":{"operationId":"RootController_tick[0]","parameters":[{"name":"sleepMs","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["internal"]}},"/v1/tick":{"get":{"operationId":"RootController_tick[1]_v1","parameters":[{"name":"sleepMs","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["internal"]}},"/sentry-test":{"get":{"operationId":"RootController_triggerSentryError[0]","parameters":[],"responses":{"200":{"description":""}},"tags":["internal"]}},"/v1/sentry-test":{"get":{"operationId":"RootController_triggerSentryError[1]_v1","parameters":[],"responses":{"200":{"description":""}},"tags":["internal"]}},"/sentry-test/non-http-error":{"get":{"operationId":"RootController_triggerNonHttpError[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Test endpoint: Throws a regular (non-HTTP) Error\nExpected behavior: Should be captured in Sentry and logged as warning\nThis simulates unexpected application errors like null pointer, database failures, etc.","tags":["internal"]}},"/v1/sentry-test/non-http-error":{"get":{"operationId":"RootController_triggerNonHttpError[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Test endpoint: Throws a regular (non-HTTP) Error\nExpected behavior: Should be captured in Sentry and logged as warning\nThis simulates unexpected application errors like null pointer, database failures, etc.","tags":["internal"]}},"/sentry-test/http-error":{"get":{"operationId":"RootController_triggerHttpError[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Test endpoint: Throws an HTTP 500 InternalServerErrorException\nExpected behavior:\n- By default: NOT sent to Sentry (logged as warning only)\n- With SENTRY_CAPTURE_HTTP_5XX=true: Sent to Sentry\nThis simulates controlled server errors","tags":["internal"]}},"/v1/sentry-test/http-error":{"get":{"operationId":"RootController_triggerHttpError[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Test endpoint: Throws an HTTP 500 InternalServerErrorException\nExpected behavior:\n- By default: NOT sent to Sentry (logged as warning only)\n- With SENTRY_CAPTURE_HTTP_5XX=true: Sent to Sentry\nThis simulates controlled server errors","tags":["internal"]}},"/account":{"get":{"operationId":"RootController_index[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/account":{"get":{"operationId":"RootController_index[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/account/tick":{"get":{"operationId":"RootController_tick[0]","parameters":[{"name":"sleepMs","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/account/tick":{"get":{"operationId":"RootController_tick[1]_v1","parameters":[{"name":"sleepMs","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/account/test/playwright/reddit-capi-fire":{"post":{"operationId":"TestController_fireRedditCapiDebug[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedditCapiDebugFireRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Debug endpoint: fires a single Reddit CAPI event with hardcoded-friendly defaults.\nBypasses all tenant/attribution gating in TrackingService so we can isolate whether\nthe CAPI HTTP path itself works end-to-end.\n\nPOST /account/test/playwright/reddit-capi-fire\nHeaders: x-playwright-api-key: <key>\nBody: { eventType: 'SignUp'|'Lead'|'Purchase', email?, rdt_cid?, value?, currency?, item_id?, item_name? }\n\nReturns: { ready, conversion_id, eventType, email, hint } — actual success/error\nlands in bridge-api logs as \"Reddit CAPI <Type> sent/failed (conversion_id=...)\".","tags":["account"]}},"/v1/account/test/playwright/reddit-capi-fire":{"post":{"operationId":"TestController_fireRedditCapiDebug[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedditCapiDebugFireRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Debug endpoint: fires a single Reddit CAPI event with hardcoded-friendly defaults.\nBypasses all tenant/attribution gating in TrackingService so we can isolate whether\nthe CAPI HTTP path itself works end-to-end.\n\nPOST /account/test/playwright/reddit-capi-fire\nHeaders: x-playwright-api-key: <key>\nBody: { eventType: 'SignUp'|'Lead'|'Purchase', email?, rdt_cid?, value?, currency?, item_id?, item_name? }\n\nReturns: { ready, conversion_id, eventType, email, hint } — actual success/error\nlands in bridge-api logs as \"Reddit CAPI <Type> sent/failed (conversion_id=...)\".","tags":["account"]}},"/account/test/addTenant/{appId}":{"get":{"operationId":"TestController_addTenant[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"owner","required":false,"in":"query","schema":{"type":"string"}},{"name":"name","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/account/test/addTenant/{appId}":{"get":{"operationId":"TestController_addTenant[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"owner","required":false,"in":"query","schema":{"type":"string"}},{"name":"name","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/account/test/playwright/account":{"post":{"operationId":"TestController_createPlaywrightAccount[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlaywrightAccountRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]},"delete":{"operationId":"TestController_removePlaywrightAccount[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovePlaywrightAccountRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Removes a Playwright test account.\n\nDELETE /account/test/playwright/account\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { email: string, appDomain: string }\n\nOnly removes accounts matching pattern: iman+playwright-test-*@nebulr.group","tags":["account"]}},"/v1/account/test/playwright/account":{"post":{"operationId":"TestController_createPlaywrightAccount[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlaywrightAccountRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]},"delete":{"operationId":"TestController_removePlaywrightAccount[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovePlaywrightAccountRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Removes a Playwright test account.\n\nDELETE /account/test/playwright/account\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { email: string, appDomain: string }\n\nOnly removes accounts matching pattern: iman+playwright-test-*@nebulr.group","tags":["account"]}},"/account/test/playwright/purge":{"post":{"operationId":"TestController_purgeTestAccounts[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurgeTestAccountsRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Purges all Playwright test accounts for an app.\nRemoves all accounts matching pattern: iman+playwright-test-*@nebulr.group\n\nPOST /account/test/playwright/purge\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string }\n\nReturns: { purgedCount: number, message: string }","tags":["account"]}},"/v1/account/test/playwright/purge":{"post":{"operationId":"TestController_purgeTestAccounts[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurgeTestAccountsRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Purges all Playwright test accounts for an app.\nRemoves all accounts matching pattern: iman+playwright-test-*@nebulr.group\n\nPOST /account/test/playwright/purge\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string }\n\nReturns: { purgedCount: number, message: string }","tags":["account"]}},"/account/test/playwright/signup-verification-link":{"get":{"operationId":"TestController_getSignupVerificationLink[0]","parameters":[{"name":"email","required":true,"in":"query","schema":{"type":"string"}},{"name":"appDomain","required":true,"in":"query","schema":{"type":"string"}},{"name":"originUrl","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Retrieves the signup verification link for a Playwright test account.\nThis allows E2E tests to complete the full signup flow by retrieving the\nverification link that would normally be sent via email.\n\nGET /account/test/playwright/signup-verification-link?email=...&appDomain=...&originUrl=...\nHeaders: x-playwright-api-key: <your-api-key>\n\nSecurity:\n- Email MUST match iman+playwright-test-*@nebulr.group pattern\n- In PROD, requires PLAYWRIGHT_TESTDATA_ENABLED_PROD=true\n\nReturns: { link: string, token: string }","tags":["account"]}},"/v1/account/test/playwright/signup-verification-link":{"get":{"operationId":"TestController_getSignupVerificationLink[1]_v1","parameters":[{"name":"email","required":true,"in":"query","schema":{"type":"string"}},{"name":"appDomain","required":true,"in":"query","schema":{"type":"string"}},{"name":"originUrl","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Retrieves the signup verification link for a Playwright test account.\nThis allows E2E tests to complete the full signup flow by retrieving the\nverification link that would normally be sent via email.\n\nGET /account/test/playwright/signup-verification-link?email=...&appDomain=...&originUrl=...\nHeaders: x-playwright-api-key: <your-api-key>\n\nSecurity:\n- Email MUST match iman+playwright-test-*@nebulr.group pattern\n- In PROD, requires PLAYWRIGHT_TESTDATA_ENABLED_PROD=true\n\nReturns: { link: string, token: string }","tags":["account"]}},"/account/test/playwright/password-reset-link":{"get":{"operationId":"TestController_getPasswordResetLink[0]","parameters":[{"name":"email","required":true,"in":"query","schema":{"type":"string"}},{"name":"appDomain","required":true,"in":"query","schema":{"type":"string"}},{"name":"originUrl","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Generates a fresh password reset link for a Playwright test account.\nAllows E2E tests to navigate to the set-password page without email interception.\n\nGET /account/test/playwright/password-reset-link?email=...&appDomain=...&originUrl=...\nHeaders: x-playwright-api-key: <your-api-key>\n\nReturns: { link: string, token: string }","tags":["account"]}},"/v1/account/test/playwright/password-reset-link":{"get":{"operationId":"TestController_getPasswordResetLink[1]_v1","parameters":[{"name":"email","required":true,"in":"query","schema":{"type":"string"}},{"name":"appDomain","required":true,"in":"query","schema":{"type":"string"}},{"name":"originUrl","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Generates a fresh password reset link for a Playwright test account.\nAllows E2E tests to navigate to the set-password page without email interception.\n\nGET /account/test/playwright/password-reset-link?email=...&appDomain=...&originUrl=...\nHeaders: x-playwright-api-key: <your-api-key>\n\nReturns: { link: string, token: string }","tags":["account"]}},"/account/test/playwright/health":{"get":{"operationId":"TestController_playwrightHealth[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Health check endpoint for Playwright tests.\nUse this to verify the test data API is reachable.\n\nGET /account/test/playwright/health\nHeaders: x-playwright-api-key: <your-api-key>","tags":["account"]}},"/v1/account/test/playwright/health":{"get":{"operationId":"TestController_playwrightHealth[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Health check endpoint for Playwright tests.\nUse this to verify the test data API is reachable.\n\nGET /account/test/playwright/health\nHeaders: x-playwright-api-key: <your-api-key>","tags":["account"]}},"/account/test/playwright/generate-jwt":{"post":{"operationId":"TestController_generateJwt[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateJwtRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Generates a signed JWT API token for a given app domain.\nUsed by E2E global setup to produce a fresh x-api-key that\nBridgeAuthGuard will accept (JWT fast-path).\n\nPOST /account/test/playwright/generate-jwt\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string }\n\nReturns: { token: string }","tags":["account"]}},"/v1/account/test/playwright/generate-jwt":{"post":{"operationId":"TestController_generateJwt[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateJwtRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Generates a signed JWT API token for a given app domain.\nUsed by E2E global setup to produce a fresh x-api-key that\nBridgeAuthGuard will accept (JWT fast-path).\n\nPOST /account/test/playwright/generate-jwt\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string }\n\nReturns: { token: string }","tags":["account"]}},"/account/test/playwright/setup-admin-app-with-owner":{"post":{"operationId":"TestController_setupAdminAppWithOwner[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupAdminAppWithOwnerRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets up the admin app (NBLOCKS_DASHBOARD) with an owner user, properly linked.\nThis is the RECOMMENDED endpoint for Playwright global setup.\n\nCombines:\n1. App creation (if needed)\n2. Owner/tenant creation (if needed)\n3. linkApp() call to set critical metadata\n\nPOST /account/test/playwright/setup-admin-app-with-owner\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { adminUiUrl: string, ownerEmail: string, ownerPassword?: string }\n\nReturns: { appId, domain, tenantId, userId, email, message }","tags":["account"]}},"/v1/account/test/playwright/setup-admin-app-with-owner":{"post":{"operationId":"TestController_setupAdminAppWithOwner[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupAdminAppWithOwnerRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets up the admin app (NBLOCKS_DASHBOARD) with an owner user, properly linked.\nThis is the RECOMMENDED endpoint for Playwright global setup.\n\nCombines:\n1. App creation (if needed)\n2. Owner/tenant creation (if needed)\n3. linkApp() call to set critical metadata\n\nPOST /account/test/playwright/setup-admin-app-with-owner\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { adminUiUrl: string, ownerEmail: string, ownerPassword?: string }\n\nReturns: { appId, domain, tenantId, userId, email, message }","tags":["account"]}},"/account/test/playwright/setup-test-app":{"post":{"operationId":"TestController_setupTestApp[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupTestAppRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets up a standalone test app with an owner user (separate from NBLOCKS_DASHBOARD).\nThis is designed for external projects (e.g., bridge-svelte) that need their own\ntest app to run E2E tests against.\n\nIdempotent — if the app already exists (by domain), returns the existing one.\nThe app is never deleted between test runs.\n\nPOST /account/test/playwright/setup-test-app\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { domain: string, appName: string, ownerEmail: string, ownerPassword?: string }\n\nReturns: { appId, domain, tenantId, userId, email, message }","tags":["account"]}},"/v1/account/test/playwright/setup-test-app":{"post":{"operationId":"TestController_setupTestApp[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupTestAppRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets up a standalone test app with an owner user (separate from NBLOCKS_DASHBOARD).\nThis is designed for external projects (e.g., bridge-svelte) that need their own\ntest app to run E2E tests against.\n\nIdempotent — if the app already exists (by domain), returns the existing one.\nThe app is never deleted between test runs.\n\nPOST /account/test/playwright/setup-test-app\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { domain: string, appName: string, ownerEmail: string, ownerPassword?: string }\n\nReturns: { appId, domain, tenantId, userId, email, message }","tags":["account"]}},"/account/test/playwright/test-app":{"delete":{"operationId":"TestController_deleteTestApp[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteTestAppRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Deletes a Playwright test app and cascades all its tenants/users.\nRefuses reserved domains (NBLOCKS_DASHBOARD, SDK_APP, BRIDGE_NEXTJS_TEST_DASHBOARD).\n\nIntended for worker-scoped fixture teardown: each parallel Playwright worker\ncreates its own isolated app via setup-test-app, then deletes it here when\nthe worker finishes.\n\nDELETE /account/test/playwright/test-app\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { domain: string }","tags":["account"]}},"/v1/account/test/playwright/test-app":{"delete":{"operationId":"TestController_deleteTestApp[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteTestAppRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Deletes a Playwright test app and cascades all its tenants/users.\nRefuses reserved domains (NBLOCKS_DASHBOARD, SDK_APP, BRIDGE_NEXTJS_TEST_DASHBOARD).\n\nIntended for worker-scoped fixture teardown: each parallel Playwright worker\ncreates its own isolated app via setup-test-app, then deletes it here when\nthe worker finishes.\n\nDELETE /account/test/playwright/test-app\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { domain: string }","tags":["account"]}},"/account/test/playwright/setup-sdk-app":{"post":{"operationId":"TestController_setupSdkApp[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupSdkAppRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets up the SDK_APP with a stable app ID for plugin testing (DEV only).\n\nUses SDK_APP_ID and SDK_APP_API_KEY env vars so the app ID is fixed and\npredictable — plugins can hardcode it in their .env.test files.\n\nConfigured with:\n- allowedOrigins: ['http://localhost:*'] (all localhost ports)\n- tenantSelfSignup: true\n- cloudViews: false\n\nIdempotent — safe to call on every test run.\n\nPOST /account/test/playwright/setup-sdk-app\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { ownerEmail: string, ownerPassword?: string }\n\nReturns: { appId, domain, tenantId, userId, email, message }","tags":["account"]}},"/v1/account/test/playwright/setup-sdk-app":{"post":{"operationId":"TestController_setupSdkApp[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupSdkAppRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets up the SDK_APP with a stable app ID for plugin testing (DEV only).\n\nUses SDK_APP_ID and SDK_APP_API_KEY env vars so the app ID is fixed and\npredictable — plugins can hardcode it in their .env.test files.\n\nConfigured with:\n- allowedOrigins: ['http://localhost:*'] (all localhost ports)\n- tenantSelfSignup: true\n- cloudViews: false\n\nIdempotent — safe to call on every test run.\n\nPOST /account/test/playwright/setup-sdk-app\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { ownerEmail: string, ownerPassword?: string }\n\nReturns: { appId, domain, tenantId, userId, email, message }","tags":["account"]}},"/account/test/playwright/sdk-demos-workspace":{"get":{"operationId":"TestController_getSdkDemosWorkspace[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Ensures the dedicated \"Bridge Plugin Demos\" workspace exists in NBLOCKS_DASHBOARD,\nowned by the primary admin user, and returns its tenant id. Idempotent — subsequent\ncalls return the same workspace.\n\nPlugin pre-setup scripts and standalone setup scripts use this to link SDK demo apps\n(SDK_APP, BRIDGE_NEXTJS_TEST_DASHBOARD, etc.) to a single dedicated workspace,\nseparate from the developer's main admin workspace. The admin UI shows it as\n\"Bridge Plugin Demos\" under the primary admin user.\n\nReturns nulls on a fresh / unseeded DB — caller skips linking gracefully.\n\nGET /account/test/playwright/sdk-demos-workspace\nHeaders: x-playwright-api-key: <your-api-key>\n\nReturns: { tenantId, name } where both may be null","tags":["account"]}},"/v1/account/test/playwright/sdk-demos-workspace":{"get":{"operationId":"TestController_getSdkDemosWorkspace[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Ensures the dedicated \"Bridge Plugin Demos\" workspace exists in NBLOCKS_DASHBOARD,\nowned by the primary admin user, and returns its tenant id. Idempotent — subsequent\ncalls return the same workspace.\n\nPlugin pre-setup scripts and standalone setup scripts use this to link SDK demo apps\n(SDK_APP, BRIDGE_NEXTJS_TEST_DASHBOARD, etc.) to a single dedicated workspace,\nseparate from the developer's main admin workspace. The admin UI shows it as\n\"Bridge Plugin Demos\" under the primary admin user.\n\nReturns nulls on a fresh / unseeded DB — caller skips linking gracefully.\n\nGET /account/test/playwright/sdk-demos-workspace\nHeaders: x-playwright-api-key: <your-api-key>\n\nReturns: { tenantId, name } where both may be null","tags":["account"]}},"/account/test/playwright/create-tenant-user":{"post":{"operationId":"TestController_createTenantUser[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantUserRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Creates a tenant/user in an existing app WITHOUT linking to a separate app.\nUse this to test \"new user signup\" flow before they create their first app.\n\nPOST /account/test/playwright/create-tenant-user\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, email: string, password?: string, tenantName?: string, firstName?: string, lastName?: string }\n\nReturns: { tenantId, userId, email, message }","tags":["account"]}},"/v1/account/test/playwright/create-tenant-user":{"post":{"operationId":"TestController_createTenantUser[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantUserRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Creates a tenant/user in an existing app WITHOUT linking to a separate app.\nUse this to test \"new user signup\" flow before they create their first app.\n\nPOST /account/test/playwright/create-tenant-user\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, email: string, password?: string, tenantName?: string, firstName?: string, lastName?: string }\n\nReturns: { tenantId, userId, email, message }","tags":["account"]}},"/account/test/playwright/add-tenant-to-user":{"post":{"operationId":"TestController_addTenantToUser[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddTenantToUserRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Adds a second tenant to an existing user (for multi-workspace / choose-user tests).\n\nPOST /account/test/playwright/add-tenant-to-user\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, email: string, tenantName?: string }\n\nReturns: { tenantId, userId, tenantName }","tags":["account"]}},"/v1/account/test/playwright/add-tenant-to-user":{"post":{"operationId":"TestController_addTenantToUser[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddTenantToUserRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Adds a second tenant to an existing user (for multi-workspace / choose-user tests).\n\nPOST /account/test/playwright/add-tenant-to-user\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, email: string, tenantName?: string }\n\nReturns: { tenantId, userId, tenantName }","tags":["account"]}},"/account/test/playwright/add-user-to-tenant":{"post":{"operationId":"TestController_addUserToTenant[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddUserToTenantRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Adds a user (creating one if needed) to a specific existing tenant inside\nan app with a specified role. Idempotent: an existing user already in the\ntenant is returned as-is (password is refreshed).\n\nPOST /account/test/playwright/add-user-to-tenant\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { workspaceId, tenantId, email, password?, role?: 'ADMIN'|'MEMBER',\n        firstName?, lastName? }\n\nReturns: { userId, email, tenantUserId, tenantId, role, created, token }\n  - token is a fresh Bearer access token for the user, ready for SDK login.\n  - created=true if the tenantUser was created, false if it already existed.","tags":["account"]}},"/v1/account/test/playwright/add-user-to-tenant":{"post":{"operationId":"TestController_addUserToTenant[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddUserToTenantRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Adds a user (creating one if needed) to a specific existing tenant inside\nan app with a specified role. Idempotent: an existing user already in the\ntenant is returned as-is (password is refreshed).\n\nPOST /account/test/playwright/add-user-to-tenant\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { workspaceId, tenantId, email, password?, role?: 'ADMIN'|'MEMBER',\n        firstName?, lastName? }\n\nReturns: { userId, email, tenantUserId, tenantId, role, created, token }\n  - token is a fresh Bearer access token for the user, ready for SDK login.\n  - created=true if the tenantUser was created, false if it already existed.","tags":["account"]}},"/account/test/playwright/update-tenant-user-role":{"post":{"operationId":"TestController_updateTenantUserRole[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenantUserRoleRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Changes an existing tenantUser's role by calling the REAL\ntenantUserService.update() — which bumps tokenVersion and publishes\n`user.state_changed` on the per-user realtime channel. The SDK subscribed\nto that channel refreshes its tokens, so the new role propagates live\n(no page reload). Drives the realtime live-role-change Playwright test.\n\nPOST /account/test/playwright/update-tenant-user-role\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { tenantUserId, tenantId, role: 'OWNER'|'ADMIN'|'MEMBER', appDomain? }\n\nReturns: { tenantUserId, role }","tags":["account"]}},"/v1/account/test/playwright/update-tenant-user-role":{"post":{"operationId":"TestController_updateTenantUserRole[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenantUserRoleRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Changes an existing tenantUser's role by calling the REAL\ntenantUserService.update() — which bumps tokenVersion and publishes\n`user.state_changed` on the per-user realtime channel. The SDK subscribed\nto that channel refreshes its tokens, so the new role propagates live\n(no page reload). Drives the realtime live-role-change Playwright test.\n\nPOST /account/test/playwright/update-tenant-user-role\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { tenantUserId, tenantId, role: 'OWNER'|'ADMIN'|'MEMBER', appDomain? }\n\nReturns: { tenantUserId, role }","tags":["account"]}},"/account/test/playwright/configure-app":{"post":{"operationId":"TestController_configureApp[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigureAppRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Configures app settings for test scenarios.\n\nPOST /account/test/playwright/configure-app\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, paymentsAutoRedirect?: boolean, stripeEnabled?: boolean, ... }\n\nReturns: { appId, message }","tags":["account"]}},"/v1/account/test/playwright/configure-app":{"post":{"operationId":"TestController_configureApp[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigureAppRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Configures app settings for test scenarios.\n\nPOST /account/test/playwright/configure-app\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, paymentsAutoRedirect?: boolean, stripeEnabled?: boolean, ... }\n\nReturns: { appId, message }","tags":["account"]}},"/account/test/playwright/mfa-last-code":{"get":{"operationId":"TestController_getLastMfaCode[0]","parameters":[{"name":"appDomain","required":true,"in":"query","schema":{"type":"string"}},{"name":"phoneNumber","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Retrieves the last MFA code generated for a phone number.\nThe code is cached in-memory when PLAYWRIGHT_TEST_API_KEY is set.\nUse this after triggering an MFA SMS to get the OTP without email/SMS access.\n\nGET /account/test/playwright/mfa-last-code?appDomain=...&phoneNumber=...\nHeaders: x-playwright-api-key: <your-api-key>\n\nReturns: { code: string, expiresAt: number }","tags":["account"]}},"/v1/account/test/playwright/mfa-last-code":{"get":{"operationId":"TestController_getLastMfaCode[1]_v1","parameters":[{"name":"appDomain","required":true,"in":"query","schema":{"type":"string"}},{"name":"phoneNumber","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Retrieves the last MFA code generated for a phone number.\nThe code is cached in-memory when PLAYWRIGHT_TEST_API_KEY is set.\nUse this after triggering an MFA SMS to get the OTP without email/SMS access.\n\nGET /account/test/playwright/mfa-last-code?appDomain=...&phoneNumber=...\nHeaders: x-playwright-api-key: <your-api-key>\n\nReturns: { code: string, expiresAt: number }","tags":["account"]}},"/account/test/playwright/enable-tenant-mfa":{"post":{"operationId":"TestController_enableTenantMfa[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableTenantMfaRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Enables MFA on a tenant.\nBoth app.mfaEnabled and tenant.mfa must be true for MFA to trigger.\n\nPOST /account/test/playwright/enable-tenant-mfa\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, tenantId: string }\n\nReturns: { message: string }","tags":["account"]}},"/v1/account/test/playwright/enable-tenant-mfa":{"post":{"operationId":"TestController_enableTenantMfa[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableTenantMfaRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Enables MFA on a tenant.\nBoth app.mfaEnabled and tenant.mfa must be true for MFA to trigger.\n\nPOST /account/test/playwright/enable-tenant-mfa\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, tenantId: string }\n\nReturns: { message: string }","tags":["account"]}},"/account/test/playwright/reset-user-mfa":{"post":{"operationId":"TestController_resetUserMfa[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetUserMfaRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Resets MFA for a user by clearing phoneNumber and mfaBackupCode.\nAfter reset, the user's next login will show the MFA SETUP flow.\n\nPOST /account/test/playwright/reset-user-mfa\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, username: string }\n\nReturns: { message: string }","tags":["account"]}},"/v1/account/test/playwright/reset-user-mfa":{"post":{"operationId":"TestController_resetUserMfa[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetUserMfaRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Resets MFA for a user by clearing phoneNumber and mfaBackupCode.\nAfter reset, the user's next login will show the MFA SETUP flow.\n\nPOST /account/test/playwright/reset-user-mfa\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, username: string }\n\nReturns: { message: string }","tags":["account"]}},"/account/test/playwright/create-plan":{"post":{"operationId":"TestController_createPlan[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Creates a plan in the app for test scenarios.\n\nPOST /account/test/playwright/create-plan\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, key?: string, name?: string, trial?: boolean, trialDays?: number, prices?: Price[] }\n\nReturns: { planId, key, name }","tags":["account"]}},"/v1/account/test/playwright/create-plan":{"post":{"operationId":"TestController_createPlan[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Creates a plan in the app for test scenarios.\n\nPOST /account/test/playwright/create-plan\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, key?: string, name?: string, trial?: boolean, trialDays?: number, prices?: Price[] }\n\nReturns: { planId, key, name }","tags":["account"]}},"/account/test/playwright/ensure-plan":{"post":{"operationId":"TestController_ensurePlan[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Idempotently ensures a plan exists (create-if-absent) for test scenarios.\n\nUnlike create-plan, when the plan already exists this returns it WITHOUT\nre-running the Stripe price sync/archive sweep. Used by specs that need a\nSTABLE, reusable plan (e.g. welcome-paywall) whose Stripe price is synced\nonce and reused — eliminating the create-then-checkout price-sync race.\n\nPOST /account/test/playwright/ensure-plan\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, key: string, name?: string, trial?: boolean, trialDays?: number, prices?: Price[] }\n\nReturns: { planId, key, name, created }","tags":["account"]}},"/v1/account/test/playwright/ensure-plan":{"post":{"operationId":"TestController_ensurePlan[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Idempotently ensures a plan exists (create-if-absent) for test scenarios.\n\nUnlike create-plan, when the plan already exists this returns it WITHOUT\nre-running the Stripe price sync/archive sweep. Used by specs that need a\nSTABLE, reusable plan (e.g. welcome-paywall) whose Stripe price is synced\nonce and reused — eliminating the create-then-checkout price-sync race.\n\nPOST /account/test/playwright/ensure-plan\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, key: string, name?: string, trial?: boolean, trialDays?: number, prices?: Price[] }\n\nReturns: { planId, key, name, created }","tags":["account"]}},"/account/test/playwright/expire-trial":{"post":{"operationId":"TestController_expireTrial[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpireTrialRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets a tenant's selected plan.\n\nPOST /account/test/playwright/set-tenant-plan\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, tenantId: string, planKey: string, currency: string, recurrenceInterval: string }\n\nReturns: { shouldSelectPlan, shouldSetupPayments, trial }","tags":["account"]}},"/v1/account/test/playwright/expire-trial":{"post":{"operationId":"TestController_expireTrial[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpireTrialRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets a tenant's selected plan.\n\nPOST /account/test/playwright/set-tenant-plan\nHeaders: x-playwright-api-key: <your-api-key>\nBody: { appDomain: string, tenantId: string, planKey: string, currency: string, recurrenceInterval: string }\n\nReturns: { shouldSelectPlan, shouldSetupPayments, trial }","tags":["account"]}},"/account/test/playwright/delete-plan":{"post":{"operationId":"TestController_deletePlan[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletePlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Deletes a plan from the app for test cleanup.\n\nPOST /account/test/playwright/delete-plan\nBody: { appDomain: string, key: string }","tags":["account"]}},"/v1/account/test/playwright/delete-plan":{"post":{"operationId":"TestController_deletePlan[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletePlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Deletes a plan from the app for test cleanup.\n\nPOST /account/test/playwright/delete-plan\nBody: { appDomain: string, key: string }","tags":["account"]}},"/account/test/playwright/sweep-plans":{"post":{"operationId":"TestController_sweepPlans[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SweepPlansRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Deletes every plan whose key starts with a prefix — cleanup for\nthrowaway suite plans that leaked when a run died before its\nafterAll (TBP-404).\n\nPOST /account/test/playwright/sweep-plans\nBody: { appDomain: string, keyPrefix: string }  (prefix min 8 chars)\nReturns: { deleted: string[] }","tags":["account"]}},"/v1/account/test/playwright/sweep-plans":{"post":{"operationId":"TestController_sweepPlans[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SweepPlansRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Deletes every plan whose key starts with a prefix — cleanup for\nthrowaway suite plans that leaked when a run died before its\nafterAll (TBP-404).\n\nPOST /account/test/playwright/sweep-plans\nBody: { appDomain: string, keyPrefix: string }  (prefix min 8 chars)\nReturns: { deleted: string[] }","tags":["account"]}},"/account/test/playwright/set-tenant-plan":{"post":{"operationId":"TestController_setTenantPlan[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTenantPlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets a tenant's selected plan.\n\nPOST /account/test/playwright/set-tenant-plan\nBody: { appDomain: string, tenantId: string, planKey: string, currency: string, recurrenceInterval: string }\n\nReturns: { shouldSelectPlan, shouldSetupPayments, trial }","tags":["account"]}},"/v1/account/test/playwright/set-tenant-plan":{"post":{"operationId":"TestController_setTenantPlan[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTenantPlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Sets a tenant's selected plan.\n\nPOST /account/test/playwright/set-tenant-plan\nBody: { appDomain: string, tenantId: string, planKey: string, currency: string, recurrenceInterval: string }\n\nReturns: { shouldSelectPlan, shouldSetupPayments, trial }","tags":["account"]}},"/account/test/playwright/clear-tenant-plan":{"post":{"operationId":"TestController_clearTenantPlan[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClearTenantPlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"TBP-370 — clears a tenant's selected plan, putting it in the state a\nnever-onboarded tenant is in.\n\nPOST /account/test/playwright/clear-tenant-plan\nBody: { appDomain: string, tenantId: string }\n\nReturns: { shouldSelectPlan, shouldSetupPayments, plan }\n\nExists so paywall / plan-selection / checkout E2Es stop deleting the app's\n`TEAM` plan and recreating it in a `finally` — that workaround mutates\nshared app state, so any spec running concurrently sees a plan-less app.\nThis touches one tenant and nothing else.","tags":["account"]}},"/v1/account/test/playwright/clear-tenant-plan":{"post":{"operationId":"TestController_clearTenantPlan[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClearTenantPlanRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"TBP-370 — clears a tenant's selected plan, putting it in the state a\nnever-onboarded tenant is in.\n\nPOST /account/test/playwright/clear-tenant-plan\nBody: { appDomain: string, tenantId: string }\n\nReturns: { shouldSelectPlan, shouldSetupPayments, plan }\n\nExists so paywall / plan-selection / checkout E2Es stop deleting the app's\n`TEAM` plan and recreating it in a `finally` — that workaround mutates\nshared app state, so any spec running concurrently sees a plan-less app.\nThis touches one tenant and nothing else.","tags":["account"]}},"/account/subscription/status":{"get":{"operationId":"SubscriptionController_getStatus[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"GET /account/subscription/status","tags":["account"]}},"/v1/account/subscription/status":{"get":{"operationId":"SubscriptionController_getStatus[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"GET /account/subscription/status","tags":["account"]}},"/account/subscription/plans":{"get":{"operationId":"SubscriptionController_getPlans[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"GET /account/subscription/plans","tags":["account"]}},"/v1/account/subscription/plans":{"get":{"operationId":"SubscriptionController_getPlans[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"GET /account/subscription/plans","tags":["account"]}},"/account/subscription/checkout":{"post":{"operationId":"SubscriptionController_startCheckout[0]","parameters":[],"responses":{"201":{"description":""}},"summary":"POST /account/subscription/checkout","tags":["account"]}},"/v1/account/subscription/checkout":{"post":{"operationId":"SubscriptionController_startCheckout[1]_v1","parameters":[],"responses":{"201":{"description":""}},"summary":"POST /account/subscription/checkout","tags":["account"]}},"/account/subscription/select":{"post":{"operationId":"SubscriptionController_selectFreePlan[0]","parameters":[],"responses":{"201":{"description":""}},"summary":"POST /account/subscription/select — free plans only","tags":["account"]}},"/v1/account/subscription/select":{"post":{"operationId":"SubscriptionController_selectFreePlan[1]_v1","parameters":[],"responses":{"201":{"description":""}},"summary":"POST /account/subscription/select — free plans only","tags":["account"]}},"/account/subscription/change":{"post":{"operationId":"SubscriptionController_changePlan[0]","parameters":[],"responses":{"201":{"description":""}},"summary":"POST /account/subscription/change — existing subscriber only","tags":["account"]}},"/v1/account/subscription/change":{"post":{"operationId":"SubscriptionController_changePlan[1]_v1","parameters":[],"responses":{"201":{"description":""}},"summary":"POST /account/subscription/change — existing subscriber only","tags":["account"]}},"/account/subscription/portal":{"get":{"operationId":"SubscriptionController_getBillingPortal[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"GET /account/subscription/portal","tags":["account"]}},"/v1/account/subscription/portal":{"get":{"operationId":"SubscriptionController_getBillingPortal[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"GET /account/subscription/portal","tags":["account"]}},"/account/app":{"get":{"operationId":"AppController_getApp[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAppResponseDto"}}}}},"tags":["account"]},"put":{"operationId":"AppController_updateApp[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAppRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAppResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"AppController_deleteApp[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Permanently delete this app and everything scoped to it.\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/v1/account/app":{"get":{"operationId":"AppController_getApp[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAppResponseDto"}}}}},"tags":["account"]},"put":{"operationId":"AppController_updateApp[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAppRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAppResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"AppController_deleteApp[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Permanently delete this app and everything scoped to it.\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/account/app/credentialsState":{"get":{"operationId":"AppController_getAppCredentialsState[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCredentialsStateResponseDto"}}}}},"tags":["account"]}},"/v1/account/app/credentialsState":{"get":{"operationId":"AppController_getAppCredentialsState[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCredentialsStateResponseDto"}}}}},"tags":["account"]}},"/account/app/credentials":{"put":{"operationId":"AppController_updateAppCredentials[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCredentialsRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCredentialsStateResponseDto"}}}}},"tags":["account"]}},"/v1/account/app/credentials":{"put":{"operationId":"AppController_updateAppCredentials[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCredentialsRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCredentialsStateResponseDto"}}}}},"tags":["account"]}},"/account/payments/plan":{"get":{"operationId":"PaymentsController_listPlans[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PlanResponse"}}}}}},"tags":["account"]},"post":{"operationId":"PaymentsController_createPlan[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanResponse"}}}}},"tags":["account"]}},"/v1/account/payments/plan":{"get":{"operationId":"PaymentsController_listPlans[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PlanResponse"}}}}}},"tags":["account"]},"post":{"operationId":"PaymentsController_createPlan[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanResponse"}}}}},"tags":["account"]}},"/account/payments/plan/{ref}":{"get":{"operationId":"PaymentsController_getPlan[0]","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanResponse"}}}}},"tags":["account"]},"put":{"operationId":"PaymentsController_updatePlan[0]","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePlanRequest"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanResponse"}}}}},"tags":["account"]},"delete":{"operationId":"PaymentsController_deletePlan[0]","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a billing plan by reference (TBP-806). Only a plan no workspace is\non; one that workspaces are on is refused with 409 `PLAN_IN_USE` and what\nto do instead (archive it, or move or delete those workspaces first).\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/v1/account/payments/plan/{ref}":{"get":{"operationId":"PaymentsController_getPlan[1]_v1","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanResponse"}}}}},"tags":["account"]},"put":{"operationId":"PaymentsController_updatePlan[1]_v1","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePlanRequest"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanResponse"}}}}},"tags":["account"]},"delete":{"operationId":"PaymentsController_deletePlan[1]_v1","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a billing plan by reference (TBP-806). Only a plan no workspace is\non; one that workspaces are on is refused with 409 `PLAN_IN_USE` and what\nto do instead (archive it, or move or delete those workspaces first).\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/account/payments/plan/{ref}/archive":{"post":{"operationId":"PaymentsController_archivePlan[0]","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Archive a plan (TBP-806): the workspaces on it keep it and keep being\nbilled; nobody new can choose it, and it leaves the plan picker. Body\n`{ \"archived\": false }` brings an archived plan back.","tags":["account"]}},"/v1/account/payments/plan/{ref}/archive":{"post":{"operationId":"PaymentsController_archivePlan[1]_v1","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"summary":"Archive a plan (TBP-806): the workspaces on it keep it and keep being\nbilled; nobody new can choose it, and it leaves the plan picker. Body\n`{ \"archived\": false }` brings an archived plan back.","tags":["account"]}},"/account/payments/plan/{ref}/deletion-preview":{"get":{"operationId":"PaymentsController_previewDeletePlan[0]","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"TBP-806 — what deleting the plan would do: delete or archive, and the\nworkspaces on it. Removes nothing. Same privilege and lookup as the delete\n(TBP-709: a route of its own, so an older server answers 404, never deletes).","tags":["account"]}},"/v1/account/payments/plan/{ref}/deletion-preview":{"get":{"operationId":"PaymentsController_previewDeletePlan[1]_v1","parameters":[{"name":"ref","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"TBP-806 — what deleting the plan would do: delete or archive, and the\nworkspaces on it. Removes nothing. Same privilege and lookup as the delete\n(TBP-709: a route of its own, so an older server answers 404, never deletes).","tags":["account"]}},"/account/payments/tax":{"get":{"operationId":"PaymentsController_listTaxes[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TaxResponse"}}}}}},"tags":["account"]},"post":{"operationId":"PaymentsController_createTax[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTaxRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxResponse"}}}}},"tags":["account"]}},"/v1/account/payments/tax":{"get":{"operationId":"PaymentsController_listTaxes[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TaxResponse"}}}}}},"tags":["account"]},"post":{"operationId":"PaymentsController_createTax[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTaxRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxResponse"}}}}},"tags":["account"]}},"/account/payments/tax/{id}":{"get":{"operationId":"PaymentsController_getTax[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxResponse"}}}}},"tags":["account"]},"put":{"operationId":"PaymentsController_updateTax[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTaxRequest"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxResponse"}}}}},"tags":["account"]},"delete":{"operationId":"PaymentsController_deleteTax[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a tax rate.\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/v1/account/payments/tax/{id}":{"get":{"operationId":"PaymentsController_getTax[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxResponse"}}}}},"tags":["account"]},"put":{"operationId":"PaymentsController_updateTax[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTaxRequest"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxResponse"}}}}},"tags":["account"]},"delete":{"operationId":"PaymentsController_deleteTax[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a tax rate.\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/account/stripe/webhook/{id}":{"post":{"operationId":"StripeController_webhook[0]","parameters":[{"name":"stripe-signature","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["account"]}},"/v1/account/stripe/webhook/{id}":{"post":{"operationId":"StripeController_webhook[1]_v1","parameters":[{"name":"stripe-signature","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["account"]}},"/account/stripe/confirm-checkout":{"post":{"operationId":"StripeController_confirmCheckout[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Verifies a Stripe checkout session was paid and belongs to the authenticated\ntenant + app, then syncs the subscription. Called by the SDK immediately\nafter Stripe redirects back — before the client refreshes tokens.","tags":["account"]}},"/v1/account/stripe/confirm-checkout":{"post":{"operationId":"StripeController_confirmCheckout[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Verifies a Stripe checkout session was paid and belongs to the authenticated\ntenant + app, then syncs the subscription. Called by the SDK immediately\nafter Stripe redirects back — before the client refreshes tokens.","tags":["account"]}},"/account/stripe/checkoutSession/{sessionId}/metadata":{"get":{"operationId":"StripeController_getCheckoutSessionMetadata[0]","parameters":[{"name":"sessionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Retrieves checkout session metadata (specifically redirectUri)\nUsed after payment to determine where to redirect the user","tags":["account"]}},"/v1/account/stripe/checkoutSession/{sessionId}/metadata":{"get":{"operationId":"StripeController_getCheckoutSessionMetadata[1]_v1","parameters":[{"name":"sessionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Retrieves checkout session metadata (specifically redirectUri)\nUsed after payment to determine where to redirect the user","tags":["account"]}},"/account/tenant":{"post":{"operationId":"TenantController_createTenant[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResponseDto"}}}}},"tags":["account"]},"get":{"operationId":"TenantController_listTenants[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TenantResponseDto"}}}}}},"summary":"List the workspaces of this app.\n\nAn app-scoped API token receives every workspace in the app — the\n`BridgeManagement` contract. A signed-in user receives only their own\nworkspace (TBP-557).","tags":["account"]}},"/v1/account/tenant":{"post":{"operationId":"TenantController_createTenant[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResponseDto"}}}}},"tags":["account"]},"get":{"operationId":"TenantController_listTenants[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TenantResponseDto"}}}}}},"summary":"List the workspaces of this app.\n\nAn app-scoped API token receives every workspace in the app — the\n`BridgeManagement` contract. A signed-in user receives only their own\nworkspace (TBP-557).","tags":["account"]}},"/account/tenant/byId/{id}":{"get":{"operationId":"TenantController_getTenant[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResponseDto"}}}}},"tags":["account"]}},"/v1/account/tenant/byId/{id}":{"get":{"operationId":"TenantController_getTenant[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResponseDto"}}}}},"tags":["account"]}},"/account/tenant/{id}/paymentDetails":{"get":{"operationId":"TenantController_getTenantPaymentDetails[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/account/tenant/{id}/paymentDetails":{"get":{"operationId":"TenantController_getTenantPaymentDetails[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/account/tenant/{id}/planDetails":{"post":{"operationId":"TenantController_setTenantPlanDetails[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTenantPlanDetails"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Subscribe to a plan","tags":["account"]}},"/v1/account/tenant/{id}/planDetails":{"post":{"operationId":"TenantController_setTenantPlanDetails[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTenantPlanDetails"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Subscribe to a plan","tags":["account"]}},"/account/tenant/{id}":{"put":{"operationId":"TenantController_updateTenant[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenantRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"TenantController_deleteTenant[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete a tenant and its workspace data.\n\nRequires the `TENANT_DELETE` privilege on the calling credential — the API token, or the signed-in user (Owner role only). A caller without it is refused with 403 (TBP-552, TBP-557). A signed-in user may only delete their own workspace.\n\nA workspace with a Stripe subscription has it set to cancel at the end of the current billing period first (no refund, no proration). When the subscription cannot be cancelled the delete is refused (409 or 502) and nothing is removed.\n\n`GET :id/deletion-preview` shows what this would remove, without removing it.","tags":["account"]}},"/v1/account/tenant/{id}":{"put":{"operationId":"TenantController_updateTenant[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTenantRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"TenantController_deleteTenant[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete a tenant and its workspace data.\n\nRequires the `TENANT_DELETE` privilege on the calling credential — the API token, or the signed-in user (Owner role only). A caller without it is refused with 403 (TBP-552, TBP-557). A signed-in user may only delete their own workspace.\n\nA workspace with a Stripe subscription has it set to cancel at the end of the current billing period first (no refund, no proration). When the subscription cannot be cancelled the delete is refused (409 or 502) and nothing is removed.\n\n`GET :id/deletion-preview` shows what this would remove, without removing it.","tags":["account"]}},"/account/tenant/{id}/deletion-preview":{"get":{"operationId":"TenantController_previewDeleteTenant[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Preview a tenant deletion: the members, the login accounts that go with them, what happens to the subscription, and the other side effects. Deletes nothing.\n\nNeeds the same `TENANT_DELETE` privilege and passes the same workspace checks as the delete.","tags":["account"]}},"/v1/account/tenant/{id}/deletion-preview":{"get":{"operationId":"TenantController_previewDeleteTenant[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Preview a tenant deletion: the members, the login accounts that go with them, what happens to the subscription, and the other side effects. Deletes nothing.\n\nNeeds the same `TENANT_DELETE` privilege and passes the same workspace checks as the delete.","tags":["account"]}},"/account/tenant/translate/text":{"post":{"operationId":"TenantController_translateText[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslateTextRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslateTextResponseDto"}}}}},"summary":"Translates a text using tenants locale, don't bother to provide targetLanguage","tags":["account"]}},"/v1/account/tenant/translate/text":{"post":{"operationId":"TenantController_translateText[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslateTextRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranslateTextResponseDto"}}}}},"summary":"Translates a text using tenants locale, don't bother to provide targetLanguage","tags":["account"]}},"/account/tenant/{id}/customerPortal":{"get":{"operationId":"TenantController_getCustomerPortal[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerPortalResponseDto"}}}}},"tags":["account"]}},"/v1/account/tenant/{id}/customerPortal":{"get":{"operationId":"TenantController_getCustomerPortal[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerPortalResponseDto"}}}}},"tags":["account"]}},"/account/tenant/file/upload/prepare":{"post":{"operationId":"TenantController_prepareFileUpload[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePresignedPostResponseDto"}}}}},"tags":["account"]}},"/v1/account/tenant/file/upload/prepare":{"post":{"operationId":"TenantController_prepareFileUpload[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePresignedPostResponseDto"}}}}},"tags":["account"]}},"/account/tenant/file/upload/finish":{"post":{"operationId":"TenantController_finishFileUpload[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishUploadRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}}},"tags":["account"]}},"/v1/account/tenant/file/upload/finish":{"post":{"operationId":"TenantController_finishFileUpload[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishUploadRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}}},"tags":["account"]}},"/account/tenant/user":{"get":{"operationId":"TenantController_listTenantUsers[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}}},"tags":["account"]},"post":{"operationId":"TenantController_createTenantUser[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}},"tags":["account"]}},"/v1/account/tenant/user":{"get":{"operationId":"TenantController_listTenantUsers[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}}},"tags":["account"]},"post":{"operationId":"TenantController_createTenantUser[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}},"tags":["account"]}},"/account/tenant/user/{id}":{"get":{"operationId":"TenantController_getTenantUser[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}},"tags":["account"]},"put":{"operationId":"TenantController_updateTenantUser[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"TenantController_deleteTenantUser[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Remove a user from the tenant.\n\nRequires the `USER_DELETE` privilege on the calling credential — the API token, or the signed-in user (Owner role only). A caller without it is refused with 403 (TBP-552, TBP-557). A signed-in user may only remove members of their own workspace.\n\n`GET user/:id/deletion-preview` shows what this would remove, without removing it.","tags":["account"]}},"/v1/account/tenant/user/{id}":{"get":{"operationId":"TenantController_getTenantUser[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}},"tags":["account"]},"put":{"operationId":"TenantController_updateTenantUser[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"TenantController_deleteTenantUser[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Remove a user from the tenant.\n\nRequires the `USER_DELETE` privilege on the calling credential — the API token, or the signed-in user (Owner role only). A caller without it is refused with 403 (TBP-552, TBP-557). A signed-in user may only remove members of their own workspace.\n\n`GET user/:id/deletion-preview` shows what this would remove, without removing it.","tags":["account"]}},"/account/tenant/user/{id}/associations":{"get":{"operationId":"TenantController_getTenantUserAssociations[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}}},"summary":"List all tenant users that another tenant user has access to via its user.\n\nAn app-scoped API token may enumerate any user in its app. A signed-in user\nmay only enumerate their own memberships (TBP-557).","tags":["account"]}},"/v1/account/tenant/user/{id}/associations":{"get":{"operationId":"TenantController_getTenantUserAssociations[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TenantUserResponseDto"}}}}}},"summary":"List all tenant users that another tenant user has access to via its user.\n\nAn app-scoped API token may enumerate any user in its app. A signed-in user\nmay only enumerate their own memberships (TBP-557).","tags":["account"]}},"/account/tenant/user/{id}/password":{"post":{"operationId":"TenantController_forgotPassword[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"tags":["account"]}},"/v1/account/tenant/user/{id}/password":{"post":{"operationId":"TenantController_forgotPassword[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"tags":["account"]}},"/account/tenant/user/{id}/passwordLink":{"get":{"operationId":"TenantController_getPasswordLink[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}}},"summary":"Get a password reset link for a user, without sending an email.\n\nServer-side credential only. The returned link is a bearer credential for that user's account, so it is available to API-token callers (`x-api-key`) and refused with 403 for a signed-in end-user JWT (TBP-557). A signed-in user who needs to reset a member's password should call `POST user/:id/password` instead, which mails the same link to that user's own address.","tags":["account"]}},"/v1/account/tenant/user/{id}/passwordLink":{"get":{"operationId":"TenantController_getPasswordLink[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}}},"summary":"Get a password reset link for a user, without sending an email.\n\nServer-side credential only. The returned link is a bearer credential for that user's account, so it is available to API-token callers (`x-api-key`) and refused with 403 for a signed-in end-user JWT (TBP-557). A signed-in user who needs to reset a member's password should call `POST user/:id/password` instead, which mails the same link to that user's own address.","tags":["account"]}},"/account/tenant/user/{id}/deletion-preview":{"get":{"operationId":"TenantController_previewDeleteTenantUser[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Preview removing a user from the tenant: whether their login account goes too and whether they are the workspace's last owner. Removes nothing.\n\nNeeds the same `USER_DELETE` privilege and passes the same workspace checks as the removal.","tags":["account"]}},"/v1/account/tenant/user/{id}/deletion-preview":{"get":{"operationId":"TenantController_previewDeleteTenantUser[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Preview removing a user from the tenant: whether their login account goes too and whether they are the workspace's last owner. Removes nothing.\n\nNeeds the same `USER_DELETE` privilege and passes the same workspace checks as the removal.","tags":["account"]}},"/account/tenant/user/{id}/email":{"post":{"operationId":"TenantController_emailTenantUser[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailUserRequestDto"}}}},"responses":{"201":{"description":""}},"tags":["account"]}},"/v1/account/tenant/user/{id}/email":{"post":{"operationId":"TenantController_emailTenantUser[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailUserRequestDto"}}}},"responses":{"201":{"description":""}},"tags":["account"]}},"/account/import/tenants":{"post":{"operationId":"ImportController_importTenants[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/account/import/tenants":{"post":{"operationId":"ImportController_importTenants[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/account/import/status/{operationId}":{"get":{"operationId":"ImportController_getImportStatus[0]","parameters":[{"name":"operationId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/account/import/status/{operationId}":{"get":{"operationId":"ImportController_getImportStatus[1]_v1","parameters":[{"name":"operationId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/account/import/tenantsFromFile":{"post":{"operationId":"ImportController_importTenantsFromFile[0]","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/account/import/tenantsFromFile":{"post":{"operationId":"ImportController_importTenantsFromFile[1]_v1","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/account/import/validateTenants":{"post":{"operationId":"ImportController_validateImportTenants[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/account/import/validateTenants":{"post":{"operationId":"ImportController_validateImportTenants[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/account/import/validateTenantsFromFile":{"post":{"operationId":"ImportController_validateImportTenantsFromFile[0]","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/account/import/validateTenantsFromFile":{"post":{"operationId":"ImportController_validateImportTenantsFromFile[1]_v1","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/account/role":{"get":{"operationId":"AccessRoleController_listRoles[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RoleResponseDto"}}}}}},"tags":["account"]},"post":{"operationId":"AccessRoleController_createRole[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRoleRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponseDto"}}}}},"tags":["account"]}},"/v1/account/role":{"get":{"operationId":"AccessRoleController_listRoles[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RoleResponseDto"}}}}}},"tags":["account"]},"post":{"operationId":"AccessRoleController_createRole[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRoleRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponseDto"}}}}},"tags":["account"]}},"/account/role/{id}":{"put":{"operationId":"AccessRoleController_updateRole[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRoleRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"AccessRoleController_deleteRole[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete a role from this app.\n\nRequires the `ROLE_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/v1/account/role/{id}":{"put":{"operationId":"AccessRoleController_updateRole[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRoleRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"AccessRoleController_deleteRole[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete a role from this app.\n\nRequires the `ROLE_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/account/role/privilege":{"get":{"operationId":"AccessRoleController_listPrivileges[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PrivilegeResponseDto"}}}}}},"tags":["account"]},"post":{"operationId":"AccessRoleController_createPrivilege[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePrivilegeRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivilegeResponseDto"}}}}},"tags":["account"]}},"/v1/account/role/privilege":{"get":{"operationId":"AccessRoleController_listPrivileges[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PrivilegeResponseDto"}}}}}},"tags":["account"]},"post":{"operationId":"AccessRoleController_createPrivilege[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePrivilegeRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivilegeResponseDto"}}}}},"tags":["account"]}},"/account/role/privilege/{id}":{"put":{"operationId":"AccessRoleController_updatePrivilege[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePrivilegeRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivilegeResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"AccessRoleController_deletePrivilege[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete a privilege from this app.\n\nRequires the `ROLE_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/v1/account/role/privilege/{id}":{"put":{"operationId":"AccessRoleController_updatePrivilege[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePrivilegeRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivilegeResponseDto"}}}}},"tags":["account"]},"delete":{"operationId":"AccessRoleController_deletePrivilege[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete a privilege from this app.\n\nRequires the `ROLE_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/billing/subscriptions":{"post":{"operationId":"BillingController_createSubscription[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCanonicalSubscriptionDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanonicalSubscriptionDto"}}}}},"tags":["account"]}},"/v1/billing/subscriptions":{"post":{"operationId":"BillingController_createSubscription[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCanonicalSubscriptionDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanonicalSubscriptionDto"}}}}},"tags":["account"]}},"/billing/state":{"get":{"operationId":"BillingController_getState[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingStateDto"}}}}},"tags":["account"]}},"/v1/billing/state":{"get":{"operationId":"BillingController_getState[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingStateDto"}}}}},"tags":["account"]}},"/billing/cancel":{"post":{"operationId":"BillingController_cancel[0]","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanonicalSubscriptionDto"}}}}},"summary":"US-6 self-service cancel. Transitions the JWT-derived workspace's\ncanonical Subscription to `cancel_at_period_end`. Stripe-side cancellation\nhappens through the existing UX path; the adapter mirrors back when the\nStripe webhook fires (idempotent on status).","tags":["account"]}},"/v1/billing/cancel":{"post":{"operationId":"BillingController_cancel[1]_v1","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanonicalSubscriptionDto"}}}}},"summary":"US-6 self-service cancel. Transitions the JWT-derived workspace's\ncanonical Subscription to `cancel_at_period_end`. Stripe-side cancellation\nhappens through the existing UX path; the adapter mirrors back when the\nStripe webhook fires (idempotent on status).","tags":["account"]}},"/billing/reactivate":{"post":{"operationId":"BillingController_reactivate[0]","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanonicalSubscriptionDto"}}}}},"summary":"US-6 self-service reactivate. Transitions from `cancel_at_period_end`\nback to `active`. Idempotent on other statuses.","tags":["account"]}},"/v1/billing/reactivate":{"post":{"operationId":"BillingController_reactivate[1]_v1","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanonicalSubscriptionDto"}}}}},"summary":"US-6 self-service reactivate. Transitions from `cancel_at_period_end`\nback to `active`. Idempotent on other statuses.","tags":["account"]}},"/billing/trial/start":{"post":{"operationId":"BillingController_startTrial[0]","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanonicalSubscriptionDto"}}}}},"summary":"US-8 self-service: start a trial on the workspace's canonical Subscription.\nResolves the key exactly against the app's own plan catalog (TBP-508) and\napplies its `trial` + `trialDays` policy. Stripe-side trial config\n(trial_period_days) is set through the existing checkout flow, not here.","tags":["account"]}},"/v1/billing/trial/start":{"post":{"operationId":"BillingController_startTrial[1]_v1","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CanonicalSubscriptionDto"}}}}},"summary":"US-8 self-service: start a trial on the workspace's canonical Subscription.\nResolves the key exactly against the app's own plan catalog (TBP-508) and\napplies its `trial` + `trialDays` policy. Stripe-side trial config\n(trial_period_days) is set through the existing checkout flow, not here.","tags":["account"]}},"/realtime/config":{"get":{"operationId":"RealtimeController_config[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["realtime"]}},"/v1/realtime/config":{"get":{"operationId":"RealtimeController_config[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["realtime"]}},"/realtime/diagnose":{"post":{"operationId":"RealtimeController_diagnose[0]","parameters":[{"name":"authorization","required":true,"in":"header","schema":{"type":"string"}},{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"x-bridge-realtime-ref","required":true,"in":"header","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeDiagnoseRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Explain why a realtime connection or subscription was refused.","tags":["realtime"]}},"/v1/realtime/diagnose":{"post":{"operationId":"RealtimeController_diagnose[1]_v1","parameters":[{"name":"authorization","required":true,"in":"header","schema":{"type":"string"}},{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"x-bridge-realtime-ref","required":true,"in":"header","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeDiagnoseRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Explain why a realtime connection or subscription was refused.","tags":["realtime"]}},"/realtime/authorize":{"post":{"operationId":"RealtimeAuthorizeController_authorize[0]","parameters":[{"name":"authorization","required":true,"in":"header","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["realtime"]}},"/v1/realtime/authorize":{"post":{"operationId":"RealtimeAuthorizeController_authorize[1]_v1","parameters":[{"name":"authorization","required":true,"in":"header","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["realtime"]}},"/account/auth/app-config":{"get":{"operationId":"AuthController_getAppConfig[0]","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAppConfigResponseDto"}}}}},"summary":"Returns the auth-relevant configuration for an app.\nThis endpoint is anonymous — SDK clients call it before login to discover\nwhich SSO / auth methods are enabled without needing an API key.\nThe app is identified by the required `x-app-id` header.","tags":["account"]}},"/v1/account/auth/app-config":{"get":{"operationId":"AuthController_getAppConfig[1]_v1","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAppConfigResponseDto"}}}}},"summary":"Returns the auth-relevant configuration for an app.\nThis endpoint is anonymous — SDK clients call it before login to discover\nwhich SSO / auth methods are enabled without needing an API key.\nThe app is identified by the required `x-app-id` header.","tags":["account"]}},"/account/auth/realtime-status":{"post":{"operationId":"AuthController_reportRealtimeStatus[0]","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeStatusRequestDto"}}}},"responses":{"202":{"description":""}},"summary":"Report how an app's realtime (live updates) connection is doing. Always 202 for a well-formed report.","tags":["account"]}},"/v1/account/auth/realtime-status":{"post":{"operationId":"AuthController_reportRealtimeStatus[1]_v1","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeStatusRequestDto"}}}},"responses":{"202":{"description":""}},"summary":"Report how an app's realtime (live updates) connection is doing. Always 202 for a well-formed report.","tags":["account"]}},"/account/auth/authenticate":{"post":{"operationId":"AuthController_authenticate[0]","parameters":[{"name":"user-agent","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthenticateRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthenticateResponseDto"}}}}},"summary":"Authenticate a user\nProvide the user credentials and recieve a session auth token","tags":["account"]}},"/v1/account/auth/authenticate":{"post":{"operationId":"AuthController_authenticate[1]_v1","parameters":[{"name":"user-agent","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthenticateRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthenticateResponseDto"}}}}},"summary":"Authenticate a user\nProvide the user credentials and recieve a session auth token","tags":["account"]}},"/account/auth/commitMfaCode":{"post":{"operationId":"AuthController_commitMfaCode[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitMfaCodeRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitMfaCodeResponseDto"}}}}},"summary":"Below actions are MFA related","tags":["account"]}},"/v1/account/auth/commitMfaCode":{"post":{"operationId":"AuthController_commitMfaCode[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitMfaCodeRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitMfaCodeResponseDto"}}}}},"summary":"Below actions are MFA related","tags":["account"]}},"/account/auth/startMfaUserSetup":{"post":{"operationId":"AuthController_startMfaUserSetup[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartUserMfaSetupRequestDto"}}}},"responses":{"201":{"description":""}},"tags":["account"]}},"/v1/account/auth/startMfaUserSetup":{"post":{"operationId":"AuthController_startMfaUserSetup[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartUserMfaSetupRequestDto"}}}},"responses":{"201":{"description":""}},"tags":["account"]}},"/account/auth/finishMfaUserSetup":{"post":{"operationId":"AuthController_finishMfaUserSetup[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishUserMfaSetupRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishUserMfaSetupResponseDto"}}}}},"tags":["account"]}},"/v1/account/auth/finishMfaUserSetup":{"post":{"operationId":"AuthController_finishMfaUserSetup[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishUserMfaSetupRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinishUserMfaSetupResponseDto"}}}}},"tags":["account"]}},"/account/auth/resetUserMfaSetup":{"post":{"operationId":"AuthController_resetUserMfaSetup[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetUserMfaSetupRequestDto"}}}},"responses":{"200":{"description":""}},"tags":["account"]}},"/v1/account/auth/resetUserMfaSetup":{"post":{"operationId":"AuthController_resetUserMfaSetup[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetUserMfaSetupRequestDto"}}}},"responses":{"200":{"description":""}},"tags":["account"]}},"/account/auth/authenticated":{"post":{"operationId":"AuthController_authenticated[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthenticatedRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Check if user is authenticated\nProvide the user credentials and recieve a session auth token","tags":["account"]},"get":{"operationId":"AuthController_getAuthenticated[0]","parameters":[{"name":"x-auth-token","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"See \"authenticated\"","tags":["account"]}},"/v1/account/auth/authenticated":{"post":{"operationId":"AuthController_authenticated[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthenticatedRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Check if user is authenticated\nProvide the user credentials and recieve a session auth token","tags":["account"]},"get":{"operationId":"AuthController_getAuthenticated[1]_v1","parameters":[{"name":"x-auth-token","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"See \"authenticated\"","tags":["account"]}},"/account/auth/deauthenticate":{"post":{"operationId":"AuthController_deauthenticate[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthenticatedRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Removes the user session","tags":["account"]},"get":{"operationId":"AuthController_getDeauthenticate[0]","parameters":[{"name":"x-auth-token","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"See \"deauthenticate\"","tags":["account"]}},"/v1/account/auth/deauthenticate":{"post":{"operationId":"AuthController_deauthenticate[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthenticatedRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Removes the user session","tags":["account"]},"get":{"operationId":"AuthController_getDeauthenticate[1]_v1","parameters":[{"name":"x-auth-token","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"See \"deauthenticate\"","tags":["account"]}},"/account/auth/password":{"post":{"operationId":"AuthController_forgotPassword[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequestDto"}}}},"responses":{"201":{"description":""}},"tags":["account"]},"put":{"operationId":"AuthController_updatePassword[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePasswordRequestDto"}}}},"responses":{"200":{"description":""}},"tags":["account"]}},"/v1/account/auth/password":{"post":{"operationId":"AuthController_forgotPassword[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequestDto"}}}},"responses":{"201":{"description":""}},"tags":["account"]},"put":{"operationId":"AuthController_updatePassword[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePasswordRequestDto"}}}},"responses":{"200":{"description":""}},"tags":["account"]}},"/account/auth/user":{"put":{"operationId":"AuthController_updateUser[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserInfoRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Updates a user during the onboarding process","tags":["account"]}},"/v1/account/auth/user":{"put":{"operationId":"AuthController_updateUser[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserInfoRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Updates a user during the onboarding process","tags":["account"]}},"/account/auth/listTenantUsers":{"post":{"operationId":"AuthController_listTenantUsers[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthListTenantUsersRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuthTenantUserResponseDto"}}}}}},"tags":["account"]}},"/v1/account/auth/listTenantUsers":{"post":{"operationId":"AuthController_listTenantUsers[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthListTenantUsersRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuthTenantUserResponseDto"}}}}}},"tags":["account"]}},"/account/auth/listMyTenantUsers":{"post":{"operationId":"AuthController_listMyTenantUsers[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthListTenantUsersRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuthTenantUserResponseDto"}}}}}},"tags":["account"]}},"/v1/account/auth/listMyTenantUsers":{"post":{"operationId":"AuthController_listMyTenantUsers[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthListTenantUsersRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuthTenantUserResponseDto"}}}}}},"tags":["account"]}},"/account/auth/workspaces":{"get":{"operationId":"AuthController_getWorkspaces[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuthTenantUserResponseDto"}}}}}},"summary":"GET /account/auth/workspaces\nReturns all workspaces (tenantUsers from active tenants) for the authenticated user.\nRequires a valid Bearer access token. Uses UserBearerGuard.","tags":["account"]}},"/v1/account/auth/workspaces":{"get":{"operationId":"AuthController_getWorkspaces[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuthTenantUserResponseDto"}}}}}},"summary":"GET /account/auth/workspaces\nReturns all workspaces (tenantUsers from active tenants) for the authenticated user.\nRequires a valid Bearer access token. Uses UserBearerGuard.","tags":["account"]}},"/account/auth/authorize":{"post":{"operationId":"AuthController_authorize[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeResponseDto"}}}}},"summary":"Check if user is authorized/granted for a certain app action\nRequires auth token and TenantUser context and asked privilege , if TenantUser context is missing an http error is thrown\nReturns if privilege is granted and also tenantId context back to caller.","tags":["account"]}},"/v1/account/auth/authorize":{"post":{"operationId":"AuthController_authorize[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeResponseDto"}}}}},"summary":"Check if user is authorized/granted for a certain app action\nRequires auth token and TenantUser context and asked privilege , if TenantUser context is missing an http error is thrown\nReturns if privilege is granted and also tenantId context back to caller.","tags":["account"]}},"/account/federation/connection":{"get":{"operationId":"FederationConnectionController_listConnections[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FederationConnectionResponse"}}}}}},"tags":["account"]},"post":{"operationId":"FederationConnectionController_createConnection[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFederationConnectionRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FederationConnectionResponse"}}}}},"tags":["account"]}},"/v1/account/federation/connection":{"get":{"operationId":"FederationConnectionController_listConnections[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FederationConnectionResponse"}}}}}},"tags":["account"]},"post":{"operationId":"FederationConnectionController_createConnection[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFederationConnectionRequest"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FederationConnectionResponse"}}}}},"tags":["account"]}},"/account/federation/connection/{id}":{"get":{"operationId":"FederationConnectionController_getConnection[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FederationConnectionResponse"}}}}},"tags":["account"]},"put":{"operationId":"FederationConnectionController_updateConnection[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFederationConnectionRequest"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FederationConnectionResponse"}}}}},"tags":["account"]},"delete":{"operationId":"FederationConnectionController_deleteConnection[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a federated identity-provider connection.\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/v1/account/federation/connection/{id}":{"get":{"operationId":"FederationConnectionController_getConnection[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FederationConnectionResponse"}}}}},"tags":["account"]},"put":{"operationId":"FederationConnectionController_updateConnection[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFederationConnectionRequest"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FederationConnectionResponse"}}}}},"tags":["account"]},"delete":{"operationId":"FederationConnectionController_deleteConnection[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Delete a federated identity-provider connection.\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/usage/ingest":{"post":{"operationId":"UsageController_ingest[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestUsageDto"}}}},"responses":{"201":{"description":""}},"tags":["account"]}},"/v1/usage/ingest":{"post":{"operationId":"UsageController_ingest[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestUsageDto"}}}},"responses":{"201":{"description":""}},"tags":["account"]}},"/usage/gauge/{metric}":{"put":{"operationId":"UsageController_setGauge[0]","parameters":[{"name":"metric","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetGaugeDto"}}}},"responses":{"200":{"description":""}},"summary":"Set the current value of a gauge metric (how many exist right now) for the workspace.","tags":["account"]}},"/v1/usage/gauge/{metric}":{"put":{"operationId":"UsageController_setGauge[1]_v1","parameters":[{"name":"metric","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetGaugeDto"}}}},"responses":{"200":{"description":""}},"summary":"Set the current value of a gauge metric (how many exist right now) for the workspace.","tags":["account"]}},"/usage/sync/{workspaceId}":{"post":{"operationId":"UsageController_sync[0]","parameters":[{"name":"workspaceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/usage/sync/{workspaceId}":{"post":{"operationId":"UsageController_sync[1]_v1","parameters":[{"name":"workspaceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/usage/quota/{metric}":{"get":{"operationId":"UsageController_getQuota[0]","parameters":[{"name":"metric","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Billing 2.0 US-11 — SDK initial hydration endpoint. Returns the live\nquota snapshot for the current authenticated user's workspace + the\ngiven metric. Returns `null` when the plan has no quota configured for\nthe metric (the SDK then treats it as unmetered for UI purposes).\n\nRoute order matters: this MUST be declared above `@Get(':workspaceId')`\nso Nest doesn't capture `quota` as a workspaceId path param.","tags":["account"]}},"/v1/usage/quota/{metric}":{"get":{"operationId":"UsageController_getQuota[1]_v1","parameters":[{"name":"metric","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Billing 2.0 US-11 — SDK initial hydration endpoint. Returns the live\nquota snapshot for the current authenticated user's workspace + the\ngiven metric. Returns `null` when the plan has no quota configured for\nthe metric (the SDK then treats it as unmetered for UI purposes).\n\nRoute order matters: this MUST be declared above `@Get(':workspaceId')`\nso Nest doesn't capture `quota` as a workspaceId path param.","tags":["account"]}},"/usage/{workspaceId}":{"get":{"operationId":"UsageController_snapshot[0]","parameters":[{"name":"workspaceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/usage/{workspaceId}":{"get":{"operationId":"UsageController_snapshot[1]_v1","parameters":[{"name":"workspaceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/webhooks/event-types":{"get":{"operationId":"WebhookController_listEventTypes[0]","parameters":[],"responses":{"200":{"description":""}},"tags":["account"]}},"/v1/webhooks/event-types":{"get":{"operationId":"WebhookController_listEventTypes[1]_v1","parameters":[],"responses":{"200":{"description":""}},"tags":["account"]}},"/webhooks/deliveries/{appId}":{"get":{"operationId":"WebhookController_listDeliveries[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}},"tags":["account"]}},"/v1/webhooks/deliveries/{appId}":{"get":{"operationId":"WebhookController_listDeliveries[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}},"tags":["account"]}},"/webhooks/deliveries/{deliveryId}/replay":{"post":{"operationId":"WebhookController_replay[0]","parameters":[{"name":"deliveryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"tags":["account"]}},"/v1/webhooks/deliveries/{deliveryId}/replay":{"post":{"operationId":"WebhookController_replay[1]_v1","parameters":[{"name":"deliveryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"tags":["account"]}},"/webhooks/secrets/rotate/{appId}":{"post":{"operationId":"WebhookController_rotateSecret[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"tags":["account"]}},"/v1/webhooks/secrets/rotate/{appId}":{"post":{"operationId":"WebhookController_rotateSecret[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"tags":["account"]}},"/account/internal/oauth2/createTenant":{"post":{"operationId":"PlatformInternalsController_createTenant[0]","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResponseDto"}}}}},"tags":["internal"]}},"/v1/account/internal/oauth2/createTenant":{"post":{"operationId":"PlatformInternalsController_createTenant[1]_v1","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantResponseDto"}}}}},"tags":["internal"]}},"/account/internal/oauth2/getClientConfig":{"post":{"operationId":"PlatformInternalsController_oauth2GetClientConfig[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"This endpoint is being used by the auth-api when pulling information for a client. Can be used to authenticate a client","tags":["internal"]}},"/v1/account/internal/oauth2/getClientConfig":{"post":{"operationId":"PlatformInternalsController_oauth2GetClientConfig[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"This endpoint is being used by the auth-api when pulling information for a client. Can be used to authenticate a client","tags":["internal"]}},"/account/internal/oauth2/listTenantUsers":{"post":{"operationId":"PlatformInternalsController_oauth2ListTenantUsers[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Used to power the choose-user view in auth-api. This is a required step when authenticating.\nIt can take federation connection as context in wich available tenant users are filtered","tags":["internal"]}},"/v1/account/internal/oauth2/listTenantUsers":{"post":{"operationId":"PlatformInternalsController_oauth2ListTenantUsers[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Used to power the choose-user view in auth-api. This is a required step when authenticating.\nIt can take federation connection as context in wich available tenant users are filtered","tags":["internal"]}},"/account/internal/getAppById":{"post":{"operationId":"PlatformInternalsController_getAppById[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Get light app data by appId (for internal services like communication)","tags":["internal"]}},"/v1/account/internal/getAppById":{"post":{"operationId":"PlatformInternalsController_getAppById[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Get light app data by appId (for internal services like communication)","tags":["internal"]}},"/account/internal/billing/ingestUsageEvent":{"post":{"operationId":"PlatformInternalsController_ingestUsageEvent[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Billing 2.0 — internal usage-event ingest. Backs the shared\nPlatformInternalsService.ingestUsageEvent `http` path used by the auth +\ncloud-views auto-instrumentation when running in 'http' transport mode.","tags":["internal"]}},"/v1/account/internal/billing/ingestUsageEvent":{"post":{"operationId":"PlatformInternalsController_ingestUsageEvent[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Billing 2.0 — internal usage-event ingest. Backs the shared\nPlatformInternalsService.ingestUsageEvent `http` path used by the auth +\ncloud-views auto-instrumentation when running in 'http' transport mode.","tags":["internal"]}},"/account/internal/billing/workspaceSnapshot":{"post":{"operationId":"PlatformInternalsController_workspaceBillingSnapshot[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Workspace plan and entitlements for flag evaluation.","tags":["internal"]}},"/v1/account/internal/billing/workspaceSnapshot":{"post":{"operationId":"PlatformInternalsController_workspaceBillingSnapshot[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Workspace plan and entitlements for flag evaluation.","tags":["internal"]}},"/account/internal/oauth2/sendMagicLink":{"post":{"operationId":"PlatformInternalsController_oauth2SendMagicLink[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"This endpoint is being used by the auth-api when emailing a magic link to a user.","tags":["internal"]}},"/v1/account/internal/oauth2/sendMagicLink":{"post":{"operationId":"PlatformInternalsController_oauth2SendMagicLink[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"This endpoint is being used by the auth-api when emailing a magic link to a user.","tags":["internal"]}},"/account/internal/oauth2/authenticate":{"post":{"operationId":"PlatformInternalsController_oauth2Authenticate[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiAuthenticateResponseDto"}}}}},"summary":"This endpoint is being used by the auth-api when authenticating user with classic credentials.","tags":["internal"]}},"/v1/account/internal/oauth2/authenticate":{"post":{"operationId":"PlatformInternalsController_oauth2Authenticate[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiAuthenticateResponseDto"}}}}},"summary":"This endpoint is being used by the auth-api when authenticating user with classic credentials.","tags":["internal"]}},"/account/internal/oauth2/credentialsConfig":{"post":{"operationId":"PlatformInternalsController_oauth2Credentials[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiCredentialsResponseDto"}}}}},"summary":"This is to either show password input or reset password when user tries to login using classic credentials","tags":["internal"]}},"/v1/account/internal/oauth2/credentialsConfig":{"post":{"operationId":"PlatformInternalsController_oauth2Credentials[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiCredentialsResponseDto"}}}}},"summary":"This is to either show password input or reset password when user tries to login using classic credentials","tags":["internal"]}},"/account/internal/oauth2/passkeysCredentialsConfig":{"post":{"operationId":"PlatformInternalsController_oauth2PasskeysCredentialsConfig[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiCredentialsResponseDto"}}}}},"tags":["internal"]}},"/v1/account/internal/oauth2/passkeysCredentialsConfig":{"post":{"operationId":"PlatformInternalsController_oauth2PasskeysCredentialsConfig[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiCredentialsResponseDto"}}}}},"tags":["internal"]}},"/account/internal/oauth2/passkeysCredentialsConfigFromPasskeysExternalId":{"post":{"operationId":"PlatformInternalsController_oauth2PasskeysCredentialsConfigFromPasskeysExternalId[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiCredentialsResponseDto"}}}}},"tags":["internal"]}},"/v1/account/internal/oauth2/passkeysCredentialsConfigFromPasskeysExternalId":{"post":{"operationId":"PlatformInternalsController_oauth2PasskeysCredentialsConfigFromPasskeysExternalId[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiCredentialsResponseDto"}}}}},"tags":["internal"]}},"/account/internal/oauth2/passkeysRegisterNewDevice":{"post":{"operationId":"PlatformInternalsController_oauth2PasskeysRegisterNewDevice[0]","parameters":[],"responses":{"201":{"description":""}},"summary":"Should be used by the auth-api when asking to register a new passkey device","tags":["internal"]}},"/v1/account/internal/oauth2/passkeysRegisterNewDevice":{"post":{"operationId":"PlatformInternalsController_oauth2PasskeysRegisterNewDevice[1]_v1","parameters":[],"responses":{"201":{"description":""}},"summary":"Should be used by the auth-api when asking to register a new passkey device","tags":["internal"]}},"/account/internal/passkeys/request-setup-link":{"post":{"operationId":"PlatformInternalsController_passkeysRequestSetupLink[0]","parameters":[],"responses":{"200":{"description":""}},"tags":["internal"]}},"/v1/account/internal/passkeys/request-setup-link":{"post":{"operationId":"PlatformInternalsController_passkeysRequestSetupLink[1]_v1","parameters":[],"responses":{"200":{"description":""}},"tags":["internal"]}},"/account/internal/passkeys/credentials-config":{"post":{"operationId":"PlatformInternalsController_passkeysCredentialsConfig[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiCredentialsResponseDto"}}}}},"tags":["internal"]}},"/v1/account/internal/passkeys/credentials-config":{"post":{"operationId":"PlatformInternalsController_passkeysCredentialsConfig[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiCredentialsResponseDto"}}}}},"tags":["internal"]}},"/account/internal/passkeys/register-device":{"post":{"operationId":"PlatformInternalsController_passkeysRegisterDevice[0]","parameters":[],"responses":{"201":{"description":""}},"tags":["internal"]}},"/v1/account/internal/passkeys/register-device":{"post":{"operationId":"PlatformInternalsController_passkeysRegisterDevice[1]_v1","parameters":[],"responses":{"201":{"description":""}},"tags":["internal"]}},"/account/internal/oauth2/federatedAuthenticate":{"post":{"operationId":"PlatformInternalsController_oauth2FederatedAuthenticate[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiAuthenticateResponseDto"}}}}},"summary":"This endpoint is being used by the auth-api when authenticating user from a trusted federation IDP","tags":["internal"]}},"/v1/account/internal/oauth2/federatedAuthenticate":{"post":{"operationId":"PlatformInternalsController_oauth2FederatedAuthenticate[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiAuthenticateResponseDto"}}}}},"summary":"This endpoint is being used by the auth-api when authenticating user from a trusted federation IDP","tags":["internal"]}},"/account/internal/oauth2/authenticateWithUsername":{"post":{"operationId":"PlatformInternalsController_oauth2AuthenticateWithUsername[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiAuthenticateResponseDto"}}}}},"summary":"This endpoint is being used by the auth-api when authenticating user credentials just by username, this is only used when trusting the user credentials in auth-api from either Passkeys or Magic link","tags":["internal"]}},"/v1/account/internal/oauth2/authenticateWithUsername":{"post":{"operationId":"PlatformInternalsController_oauth2AuthenticateWithUsername[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthApiAuthenticateResponseDto"}}}}},"summary":"This endpoint is being used by the auth-api when authenticating user credentials just by username, this is only used when trusting the user credentials in auth-api from either Passkeys or Magic link","tags":["internal"]}},"/account/internal/oauth2/resendMfaCode":{"post":{"operationId":"PlatformInternalsController_oauth2ResendMfaCode[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"TBP-775 — a new sign-in code; the session keeps only the returned challenge id.","tags":["internal"]}},"/v1/account/internal/oauth2/resendMfaCode":{"post":{"operationId":"PlatformInternalsController_oauth2ResendMfaCode[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"TBP-775 — a new sign-in code; the session keeps only the returned challenge id.","tags":["internal"]}},"/account/internal/oauth2/startMfaUserSetup":{"post":{"operationId":"PlatformInternalsController_oauth2StartMfaUserSetup[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"TBP-775 — texts a code to the number being set up; the number stays with the challenge.","tags":["internal"]}},"/v1/account/internal/oauth2/startMfaUserSetup":{"post":{"operationId":"PlatformInternalsController_oauth2StartMfaUserSetup[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"TBP-775 — texts a code to the number being set up; the number stays with the challenge.","tags":["internal"]}},"/account/internal/oauth2/verifyMfaCode":{"post":{"operationId":"PlatformInternalsController_oauth2VerifyMfaCode[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"TBP-775 — checks a sign-in code against its server-side challenge\n(expiry, attempt limit, single use).","tags":["internal"]}},"/v1/account/internal/oauth2/verifyMfaCode":{"post":{"operationId":"PlatformInternalsController_oauth2VerifyMfaCode[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"TBP-775 — checks a sign-in code against its server-side challenge\n(expiry, attempt limit, single use).","tags":["internal"]}},"/account/internal/oauth2/finishMfaUserSetup":{"post":{"operationId":"PlatformInternalsController_oauth2FinishMfaUserSetup[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"TBP-775 — checks the setup code, then saves the phone number it was sent\nto (proven valid) and returns the backup code.","tags":["internal"]}},"/v1/account/internal/oauth2/finishMfaUserSetup":{"post":{"operationId":"PlatformInternalsController_oauth2FinishMfaUserSetup[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"TBP-775 — checks the setup code, then saves the phone number it was sent\nto (proven valid) and returns the backup code.","tags":["internal"]}},"/account/internal/oauth2/createTestMfaChallenge":{"post":{"operationId":"PlatformInternalsController_oauth2CreateTestMfaChallenge[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Test fixtures only (Playwright): a challenge with a known code and no\ntext message. Refused unless the test key is configured.","tags":["internal"]}},"/v1/account/internal/oauth2/createTestMfaChallenge":{"post":{"operationId":"PlatformInternalsController_oauth2CreateTestMfaChallenge[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Test fixtures only (Playwright): a challenge with a known code and no\ntext message. Refused unless the test key is configured.","tags":["internal"]}},"/account/internal/oauth2/resetUserMfaSetup":{"post":{"operationId":"PlatformInternalsController_oauth2ResetUserMfaSetup[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"We reset the users phone number","tags":["internal"]}},"/v1/account/internal/oauth2/resetUserMfaSetup":{"post":{"operationId":"PlatformInternalsController_oauth2ResetUserMfaSetup[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"We reset the users phone number","tags":["internal"]}},"/account/internal/oauth2/getAuthContext":{"post":{"operationId":"PlatformInternalsController_getAuthContext[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"This endpoint is being used by the auth-api when accepted user credentials and the wanted tenant is known. This data is sufficient for generating a access_token","tags":["internal"]}},"/v1/account/internal/oauth2/getAuthContext":{"post":{"operationId":"PlatformInternalsController_getAuthContext[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"This endpoint is being used by the auth-api when accepted user credentials and the wanted tenant is known. This data is sufficient for generating a access_token","tags":["internal"]}},"/account/internal/app":{"post":{"operationId":"PlatformInternalsController_createApp[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppResponseDto"}}}}},"summary":"Nblock dashboard will call these endpoints instead of the normal ones due to it is not providing the AppSecret and operates in god mode.\nA JWT approach would be better and remove the need for this internal traffic","tags":["internal"]}},"/v1/account/internal/app":{"post":{"operationId":"PlatformInternalsController_createApp[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppResponseDto"}}}}},"summary":"Nblock dashboard will call these endpoints instead of the normal ones due to it is not providing the AppSecret and operates in god mode.\nA JWT approach would be better and remove the need for this internal traffic","tags":["internal"]}},"/account/internal/listApps":{"get":{"operationId":"PlatformInternalsController_listApps[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AppLightResponseDto"}}}}}},"summary":"Lists all apps that the nblocks tenant \"owns\"","tags":["internal"]}},"/v1/account/internal/listApps":{"get":{"operationId":"PlatformInternalsController_listApps[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AppLightResponseDto"}}}}}},"summary":"Lists all apps that the nblocks tenant \"owns\"","tags":["internal"]}},"/account/internal/app/{appId}":{"get":{"operationId":"PlatformInternalsController_getApp[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppConfigResponseDto"}}}}},"summary":"Get full details for a single app","tags":["internal"]},"put":{"operationId":"PlatformInternalsController_updateApp[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAppRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppConfigResponseDto"}}}}},"summary":"Update a single app","tags":["internal"]}},"/v1/account/internal/app/{appId}":{"get":{"operationId":"PlatformInternalsController_getApp[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppConfigResponseDto"}}}}},"summary":"Get full details for a single app","tags":["internal"]},"put":{"operationId":"PlatformInternalsController_updateApp[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAppRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppConfigResponseDto"}}}}},"summary":"Update a single app","tags":["internal"]}},"/account/internal/stripeWebhook/{appId}/repair":{"post":{"operationId":"PlatformInternalsController_repairStripeWebhook[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppConfigResponseDto"}}}}},"summary":"Re-run Stripe setup for an app and replace its Stripe webhook endpoint","tags":["internal"]}},"/v1/account/internal/stripeWebhook/{appId}/repair":{"post":{"operationId":"PlatformInternalsController_repairStripeWebhook[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppConfigResponseDto"}}}}},"summary":"Re-run Stripe setup for an app and replace its Stripe webhook endpoint","tags":["internal"]}},"/account/internal/stripe/{appId}/disconnect":{"post":{"operationId":"PlatformInternalsController_disconnectStripe[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Disconnect Stripe from an app and remove its Stripe webhook endpoint","tags":["internal"]}},"/v1/account/internal/stripe/{appId}/disconnect":{"post":{"operationId":"PlatformInternalsController_disconnectStripe[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Disconnect Stripe from an app and remove its Stripe webhook endpoint","tags":["internal"]}},"/account/internal/stripe/{appId}/disconnectPreview":{"get":{"operationId":"PlatformInternalsController_previewStripeDisconnect[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Report what disconnecting Stripe from an app would cost, without doing it","tags":["internal"]}},"/v1/account/internal/stripe/{appId}/disconnectPreview":{"get":{"operationId":"PlatformInternalsController_previewStripeDisconnect[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Report what disconnecting Stripe from an app would cost, without doing it","tags":["internal"]}},"/account/internal/appSecret/{appId}":{"delete":{"operationId":"PlatformInternalsController_resetAppSecret[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Generate a new app secret","tags":["internal"]}},"/v1/account/internal/appSecret/{appId}":{"delete":{"operationId":"PlatformInternalsController_resetAppSecret[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Generate a new app secret","tags":["internal"]}},"/account/internal/oauth2/forgotPassword":{"post":{"operationId":"PlatformInternalsController_oauth2ForgotPassword[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"---------------- End of Nblocks dashboard ---------------------","tags":["internal"]}},"/v1/account/internal/oauth2/forgotPassword":{"post":{"operationId":"PlatformInternalsController_oauth2ForgotPassword[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"---------------- End of Nblocks dashboard ---------------------","tags":["internal"]}},"/account/internal/oauth2/updatePassword":{"put":{"operationId":"PlatformInternalsController_oauth2UpdatePassword[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Used by SDK auth service to commit a new password using the reset token without an app API key.\nThe internal account API key is sufficient; appId is resolved from the body.","tags":["internal"]}},"/v1/account/internal/oauth2/updatePassword":{"put":{"operationId":"PlatformInternalsController_oauth2UpdatePassword[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Used by SDK auth service to commit a new password using the reset token without an app API key.\nThe internal account API key is sufficient; appId is resolved from the body.","tags":["internal"]}},"/account/internal/oauth2/validatePasswordToken":{"get":{"operationId":"PlatformInternalsController_oauth2ValidatePasswordToken[0]","parameters":[{"name":"token","required":true,"in":"query","schema":{"type":"string"}},{"name":"origin","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Validates a forgot-password token and returns the associated appId.\n\nNo app API key required — the token is proof of access.\nThe optional `origin` query param is forwarded from the browser's Origin header;\nif provided, it must match one of the app's registered allowedOrigins (or the\nconfigured cloud-views URL) or a 403 is returned.","tags":["internal"]}},"/v1/account/internal/oauth2/validatePasswordToken":{"get":{"operationId":"PlatformInternalsController_oauth2ValidatePasswordToken[1]_v1","parameters":[{"name":"token","required":true,"in":"query","schema":{"type":"string"}},{"name":"origin","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Validates a forgot-password token and returns the associated appId.\n\nNo app API key required — the token is proof of access.\nThe optional `origin` query param is forwarded from the browser's Origin header;\nif provided, it must match one of the app's registered allowedOrigins (or the\nconfigured cloud-views URL) or a 403 is returned.","tags":["internal"]}},"/account/internal/resolveAppData":{"post":{"operationId":"PlatformInternalsController_startTransaction[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartStopAppTransactionRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAppTransactionResponseDto"}}}}},"summary":"Resolve app, tenant and tenant-user context from an application API key.","tags":["internal"]}},"/v1/account/internal/resolveAppData":{"post":{"operationId":"PlatformInternalsController_startTransaction[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartStopAppTransactionRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAppTransactionResponseDto"}}}}},"summary":"Resolve app, tenant and tenant-user context from an application API key.","tags":["internal"]}},"/account/internal/endTransaction":{"post":{"operationId":"PlatformInternalsController_endTransaction[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartStopAppTransactionRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAppTransactionResponseDto"}}}}},"summary":"Close out a resolved app transaction, returning the same resolved context.","tags":["internal"]}},"/v1/account/internal/endTransaction":{"post":{"operationId":"PlatformInternalsController_endTransaction[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartStopAppTransactionRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAppTransactionResponseDto"}}}}},"summary":"Close out a resolved app transaction, returning the same resolved context.","tags":["internal"]}},"/account/internal/oauth2/revokeToken":{"post":{"operationId":"PlatformInternalsController_oauth2RevokeToken[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Used by auth-api to record a revoked refresh token JTI.\nOnce recorded, the token cannot be used to obtain new access tokens.","tags":["internal"]}},"/v1/account/internal/oauth2/revokeToken":{"post":{"operationId":"PlatformInternalsController_oauth2RevokeToken[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Used by auth-api to record a revoked refresh token JTI.\nOnce recorded, the token cannot be used to obtain new access tokens.","tags":["internal"]}},"/account/internal/oauth2/isTokenRevoked":{"post":{"operationId":"PlatformInternalsController_oauth2IsTokenRevoked[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Used by auth-api to check whether a refresh token JTI has been revoked.","tags":["internal"]}},"/v1/account/internal/oauth2/isTokenRevoked":{"post":{"operationId":"PlatformInternalsController_oauth2IsTokenRevoked[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Used by auth-api to check whether a refresh token JTI has been revoked.","tags":["internal"]}},"/account/nblocks/testApp":{"post":{"operationId":"PublicNblocksController_createTestApp[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestAppDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppResponseDto"}}}}},"summary":"This is called by both nblocks-cli < 1.1.0 and admin-ui (20230803) create-app.screen","tags":["internal"]}},"/v1/account/nblocks/testApp":{"post":{"operationId":"PublicNblocksController_createTestApp[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestAppDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppResponseDto"}}}}},"summary":"This is called by both nblocks-cli < 1.1.0 and admin-ui (20230803) create-app.screen","tags":["internal"]}},"/account/nblocks/app":{"post":{"operationId":"PublicNblocksController_createApp[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppResponseDto"}}}}},"summary":"This is called by both nblocks-cli >= 1.1.0 and admin-ui create-app.screen","tags":["internal"]}},"/v1/account/nblocks/app":{"post":{"operationId":"PublicNblocksController_createApp[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppResponseDto"}}}}},"summary":"This is called by both nblocks-cli >= 1.1.0 and admin-ui create-app.screen","tags":["internal"]}},"/tracking/attribution":{"post":{"operationId":"TrackingController_storeAttribution[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoreAttributionDto"}}}},"responses":{"200":{"description":""}},"tags":["tracking"]}},"/v1/tracking/attribution":{"post":{"operationId":"TrackingController_storeAttribution[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoreAttributionDto"}}}},"responses":{"200":{"description":""}},"tags":["tracking"]}},"/tracking/pixel-event-fired":{"post":{"operationId":"TrackingController_clearPendingPixelEvent[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClearPendingPixelEventDto"}}}},"responses":{"200":{"description":""}},"summary":"Clears a single pending pixel event from the tenant's metadata.\nCalled by the client after it has fired the matching dataLayer event so\nthe next /subscription/status response doesn't re-serve the same event.\n\nIdempotent — returns { cleared: false } when the tenant or the event is\nnot found. The client should treat this as fire-and-forget.","tags":["tracking"]}},"/v1/tracking/pixel-event-fired":{"post":{"operationId":"TrackingController_clearPendingPixelEvent[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClearPendingPixelEventDto"}}}},"responses":{"200":{"description":""}},"summary":"Clears a single pending pixel event from the tenant's metadata.\nCalled by the client after it has fired the matching dataLayer event so\nthe next /subscription/status response doesn't re-serve the same event.\n\nIdempotent — returns { cleared: false } when the tenant or the event is\nnot found. The client should treat this as fire-and-forget.","tags":["tracking"]}},"/account/ms-azure-marketplace/signup/{appId}":{"get":{"operationId":"MsAzureMarketplaceController_signup[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"token","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["account"]}},"/v1/account/ms-azure-marketplace/signup/{appId}":{"get":{"operationId":"MsAzureMarketplaceController_signup[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"token","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["account"]}},"/account/ms-azure-marketplace/webhook/{appId}":{"post":{"operationId":"MsAzureMarketplaceController_webhook[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["account"]}},"/v1/account/ms-azure-marketplace/webhook/{appId}":{"post":{"operationId":"MsAzureMarketplaceController_webhook[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["account"]}},"/account//app/custom-tenant-user-params-config":{"post":{"operationId":"CustomParamsConfigController_upsert[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomParamsConfigInputDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Upsert custom parameter configurations for a specific app","tags":["account"]},"get":{"operationId":"CustomParamsConfigController_findByAppId[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Find custom parameter configurations by app ID","tags":["account"]},"delete":{"operationId":"CustomParamsConfigController_deleteByApp[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Delete this app's custom parameter configuration.\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/v1/account//app/custom-tenant-user-params-config":{"post":{"operationId":"CustomParamsConfigController_upsert[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomParamsConfigInputDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Upsert custom parameter configurations for a specific app","tags":["account"]},"get":{"operationId":"CustomParamsConfigController_findByAppId[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Find custom parameter configurations by app ID","tags":["account"]},"delete":{"operationId":"CustomParamsConfigController_deleteByApp[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Delete this app's custom parameter configuration.\n\nRequires the `APP_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/account/api-token/introspect":{"post":{"operationId":"ApiTokenController_introspect[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntrospectTokenDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Token introspection (RFC 6750-style) for backend Bridge plugins.\n\nA plugin (e.g. bridge-nestjs) that receives an `x-api-key` API token\nPOSTs it here to learn whether it is active and what it is scoped to,\ninstead of verifying the signature locally. This keeps API tokens signed\nwith the per-app HS256 secret (which the plugin never holds) while giving\nthe plugin instant revocation — the Bridge re-checks the backing record\non every call.\n\nThe endpoint is intentionally unauthenticated: the presented token IS the\ncredential, and the response only ever echoes claims already inside that\ntoken. A forged/invalid/revoked token yields `{ active: false }` and\nnothing else — no information leak. App-scoping is enforced cryptographically\n(only the issuing app's secret verifies the signature); the caller is\nresponsible for comparing the returned `appId` to its own configured appId.","tags":["account"]}},"/v1/account/api-token/introspect":{"post":{"operationId":"ApiTokenController_introspect[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntrospectTokenDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Token introspection (RFC 6750-style) for backend Bridge plugins.\n\nA plugin (e.g. bridge-nestjs) that receives an `x-api-key` API token\nPOSTs it here to learn whether it is active and what it is scoped to,\ninstead of verifying the signature locally. This keeps API tokens signed\nwith the per-app HS256 secret (which the plugin never holds) while giving\nthe plugin instant revocation — the Bridge re-checks the backing record\non every call.\n\nThe endpoint is intentionally unauthenticated: the presented token IS the\ncredential, and the response only ever echoes claims already inside that\ntoken. A forged/invalid/revoked token yields `{ active: false }` and\nnothing else — no information leak. App-scoping is enforced cryptographically\n(only the issuing app's secret verifies the signature); the caller is\nresponsible for comparing the returned `appId` to its own configured appId.","tags":["account"]}},"/account/api-token/workspace":{"post":{"operationId":"ApiTokenController_createWorkspaceToken[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkspaceTokenDto"}}}},"responses":{"201":{"description":""}},"summary":"Create a workspace-scoped API token.\nThe requesting user must be OWNER or ADMIN of the workspace.\nPrivileges are constrained by app.allowedTokenPrivileges (if set).\n\nRequires the `TOKEN_WRITE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]},"get":{"operationId":"ApiTokenController_listWorkspaceTokens[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all API tokens for a workspace.","tags":["account"]}},"/v1/account/api-token/workspace":{"post":{"operationId":"ApiTokenController_createWorkspaceToken[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkspaceTokenDto"}}}},"responses":{"201":{"description":""}},"summary":"Create a workspace-scoped API token.\nThe requesting user must be OWNER or ADMIN of the workspace.\nPrivileges are constrained by app.allowedTokenPrivileges (if set).\n\nRequires the `TOKEN_WRITE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]},"get":{"operationId":"ApiTokenController_listWorkspaceTokens[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"List all API tokens for a workspace.","tags":["account"]}},"/account/api-token/workspace/{id}":{"delete":{"operationId":"ApiTokenController_revokeWorkspaceToken[0]","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Revoke (delete) a workspace API token.\n\nRequires the `TOKEN_WRITE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/v1/account/api-token/workspace/{id}":{"delete":{"operationId":"ApiTokenController_revokeWorkspaceToken[1]_v1","parameters":[{"name":"x-tenant-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Revoke (delete) a workspace API token.\n\nRequires the `TOKEN_WRITE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/account/api-token/app":{"get":{"operationId":"ApiTokenController_listAppTokens[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"List all app-scoped tokens for an app (no tenant).","tags":["account"]},"post":{"operationId":"ApiTokenController_createAppToken[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppTokenDto"}}}},"responses":{"201":{"description":""}},"summary":"Create an app-scoped API token (no tenant restriction).\n\nRequires the `TOKEN_WRITE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/v1/account/api-token/app":{"get":{"operationId":"ApiTokenController_listAppTokens[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"List all app-scoped tokens for an app (no tenant).","tags":["account"]},"post":{"operationId":"ApiTokenController_createAppToken[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppTokenDto"}}}},"responses":{"201":{"description":""}},"summary":"Create an app-scoped API token (no tenant restriction).\n\nRequires the `TOKEN_WRITE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["account"]}},"/account/api-token/app/{id}":{"delete":{"operationId":"ApiTokenController_revokeAppToken[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Revoke (delete) an app-scoped API token.\n\nRequires the `TOKEN_WRITE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).\n\n`GET app/:id/deletion-preview` shows what this would do, without revoking.","tags":["account"]}},"/v1/account/api-token/app/{id}":{"delete":{"operationId":"ApiTokenController_revokeAppToken[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Revoke (delete) an app-scoped API token.\n\nRequires the `TOKEN_WRITE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).\n\n`GET app/:id/deletion-preview` shows what this would do, without revoking.","tags":["account"]}},"/account/api-token/app/{id}/deletion-preview":{"get":{"operationId":"ApiTokenController_previewRevokeAppToken[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Preview revoking an app-scoped API token: its privileges, its last use, and whether it is the token making the call. Revokes nothing.\n\nNeeds the same `TOKEN_WRITE` privilege as the revoke.","tags":["account"]}},"/v1/account/api-token/app/{id}/deletion-preview":{"get":{"operationId":"ApiTokenController_previewRevokeAppToken[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Preview revoking an app-scoped API token: its privileges, its last use, and whether it is the token making the call. Revokes nothing.\n\nNeeds the same `TOKEN_WRITE` privilege as the revoke.","tags":["account"]}},"/account/api-token/me/app/available-privileges":{"get":{"operationId":"ApiTokenUserController_listAvailablePrivileges[0]","parameters":[],"responses":{"200":{"description":""}},"tags":["account"]}},"/v1/account/api-token/me/app/available-privileges":{"get":{"operationId":"ApiTokenUserController_listAvailablePrivileges[1]_v1","parameters":[],"responses":{"200":{"description":""}},"tags":["account"]}},"/account/api-token/me/app":{"get":{"operationId":"ApiTokenUserController_listAppTokens[0]","parameters":[],"responses":{"200":{"description":""}},"tags":["account"]},"post":{"operationId":"ApiTokenUserController_createAppToken[0]","parameters":[],"responses":{"201":{"description":""}},"tags":["account"]}},"/v1/account/api-token/me/app":{"get":{"operationId":"ApiTokenUserController_listAppTokens[1]_v1","parameters":[],"responses":{"200":{"description":""}},"tags":["account"]},"post":{"operationId":"ApiTokenUserController_createAppToken[1]_v1","parameters":[],"responses":{"201":{"description":""}},"tags":["account"]}},"/account/api-token/me/app/{id}":{"delete":{"operationId":"ApiTokenUserController_revokeAppToken[0]","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["account"]}},"/v1/account/api-token/me/app/{id}":{"delete":{"operationId":"ApiTokenUserController_revokeAppToken[1]_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["account"]}},"/entitlements":{"get":{"operationId":"EntitlementController_getEntitlements[0]","parameters":[],"responses":{"200":{"description":""}},"tags":["account"]}},"/v1/entitlements":{"get":{"operationId":"EntitlementController_getEntitlements[1]_v1","parameters":[],"responses":{"200":{"description":""}},"tags":["account"]}},"/admin/debug/inject-drift":{"post":{"operationId":"ReconciliationController_injectDrift[0]","parameters":[],"responses":{"201":{"description":""}},"tags":["account"]}},"/v1/admin/debug/inject-drift":{"post":{"operationId":"ReconciliationController_injectDrift[1]_v1","parameters":[],"responses":{"201":{"description":""}},"tags":["account"]}},"/admin/reconcile/{workspaceId}":{"post":{"operationId":"ReconciliationController_reconcileWorkspace[0]","parameters":[{"name":"workspaceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/admin/reconcile/{workspaceId}":{"post":{"operationId":"ReconciliationController_reconcileWorkspace[1]_v1","parameters":[{"name":"workspaceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/admin/reconcile/{workspaceId}/{metric}":{"post":{"operationId":"ReconciliationController_reconcileWorkspaceMetric[0]","parameters":[{"name":"workspaceId","required":true,"in":"path","schema":{"type":"string"}},{"name":"metric","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/v1/admin/reconcile/{workspaceId}/{metric}":{"post":{"operationId":"ReconciliationController_reconcileWorkspaceMetric[1]_v1","parameters":[{"name":"workspaceId","required":true,"in":"path","schema":{"type":"string"}},{"name":"metric","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["account"]}},"/admin/file/prepareUploadAnonymous":{"post":{"operationId":"FileController_prepareUploadAnonymous[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadResponseDto"}}}}},"tags":["admin"]}},"/v1/admin/file/prepareUploadAnonymous":{"post":{"operationId":"FileController_prepareUploadAnonymous[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadResponseDto"}}}}},"tags":["admin"]}},"/admin/file/prepareUpload":{"post":{"operationId":"FileController_prepareUpload[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadResponseDto"}}}}},"tags":["admin"]}},"/v1/admin/file/prepareUpload":{"post":{"operationId":"FileController_prepareUpload[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepareUploadResponseDto"}}}}},"tags":["admin"]}},"/event-log":{"post":{"operationId":"EventLogController_enqueueEvent[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEventDto"}}}},"responses":{"201":{"description":""}},"tags":["event-log"]}},"/v1/event-log":{"post":{"operationId":"EventLogController_enqueueEvent[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEventDto"}}}},"responses":{"201":{"description":""}},"tags":["event-log"]}},"/event-log/charts":{"get":{"operationId":"EventLogController_getCharts[0]","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"eventName","required":true,"in":"query","schema":{"type":"string"}},{"name":"interval","required":true,"in":"query","schema":{"type":"string","enum":["hour","day","week","month"]}},{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":""}},"tags":["event-log"]}},"/v1/event-log/charts":{"get":{"operationId":"EventLogController_getCharts[1]_v1","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"eventName","required":true,"in":"query","schema":{"type":"string"}},{"name":"interval","required":true,"in":"query","schema":{"type":"string","enum":["hour","day","week","month"]}},{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":""}},"tags":["event-log"]}},"/event-log/query":{"post":{"operationId":"EventLogController_queryEvents[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryEventsDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["event-log"]}},"/v1/event-log/query":{"post":{"operationId":"EventLogController_queryEvents[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryEventsDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["event-log"]}},"/event-log/entities/{entityType}/{entityValue}":{"get":{"operationId":"EventLogController_getEntityJourney[0]","parameters":[{"name":"entityType","required":true,"in":"path","schema":{"type":"string"}},{"name":"entityValue","required":true,"in":"path","schema":{"type":"string"}},{"name":"appId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["event-log"]}},"/v1/event-log/entities/{entityType}/{entityValue}":{"get":{"operationId":"EventLogController_getEntityJourney[1]_v1","parameters":[{"name":"entityType","required":true,"in":"path","schema":{"type":"string"}},{"name":"entityValue","required":true,"in":"path","schema":{"type":"string"}},{"name":"appId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["event-log"]}},"/event-log/audit":{"get":{"operationId":"EventLogController_getAuditLog[0]","parameters":[{"name":"appId","required":false,"in":"query","description":"TBP-594 — optional. The controller runs every request through\n`boundAppId(req, query.appId)`, which takes the app from the authenticated\ntoken and rejects a supplied value that disagrees with it. Requiring it\nhere meant a caller holding a perfectly good app token still had to know\nand repeat its own app id, and the management SDK does not carry one — it\nhas the key, not the claims. Omitted, the token's app is used; supplied and\nmismatched, it still 403s.","schema":{"type":"string"}},{"name":"eventName","required":false,"in":"query","description":"Top-level event type, e.g. `tenant_created`, `user_logged_in`.","schema":{"type":"string"}},{"name":"action","required":false,"in":"query","deprecated":true,"schema":{"type":"string"}},{"name":"userId","required":false,"in":"query","description":"Matches `extracted.userId`.","schema":{"type":"string"}},{"name":"actor","required":false,"in":"query","deprecated":true,"schema":{"type":"string"}},{"name":"tenantId","required":false,"in":"query","description":"Matches `extracted.tenantId`.","schema":{"type":"string"}},{"name":"email","required":false,"in":"query","description":"Matches `extracted.email`, compared lowercased.","schema":{"type":"string"}},{"name":"target","required":false,"in":"query","deprecated":true,"schema":{"type":"string"}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":500,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"type":"number"}}],"responses":{"200":{"description":""}},"tags":["event-log"]}},"/v1/event-log/audit":{"get":{"operationId":"EventLogController_getAuditLog[1]_v1","parameters":[{"name":"appId","required":false,"in":"query","description":"TBP-594 — optional. The controller runs every request through\n`boundAppId(req, query.appId)`, which takes the app from the authenticated\ntoken and rejects a supplied value that disagrees with it. Requiring it\nhere meant a caller holding a perfectly good app token still had to know\nand repeat its own app id, and the management SDK does not carry one — it\nhas the key, not the claims. Omitted, the token's app is used; supplied and\nmismatched, it still 403s.","schema":{"type":"string"}},{"name":"eventName","required":false,"in":"query","description":"Top-level event type, e.g. `tenant_created`, `user_logged_in`.","schema":{"type":"string"}},{"name":"action","required":false,"in":"query","deprecated":true,"schema":{"type":"string"}},{"name":"userId","required":false,"in":"query","description":"Matches `extracted.userId`.","schema":{"type":"string"}},{"name":"actor","required":false,"in":"query","deprecated":true,"schema":{"type":"string"}},{"name":"tenantId","required":false,"in":"query","description":"Matches `extracted.tenantId`.","schema":{"type":"string"}},{"name":"email","required":false,"in":"query","description":"Matches `extracted.email`, compared lowercased.","schema":{"type":"string"}},{"name":"target","required":false,"in":"query","deprecated":true,"schema":{"type":"string"}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":500,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"minimum":0,"type":"number"}}],"responses":{"200":{"description":""}},"tags":["event-log"]}},"/event-log/journeys/stats":{"get":{"operationId":"EventLogController_getJourneyStats[0]","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"entityType","required":false,"in":"query","schema":{"type":"string"}},{"name":"startEvent","required":true,"in":"query","schema":{"type":"string"}},{"name":"endEvent","required":true,"in":"query","schema":{"type":"string"}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["event-log"]}},"/v1/event-log/journeys/stats":{"get":{"operationId":"EventLogController_getJourneyStats[1]_v1","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"entityType","required":false,"in":"query","schema":{"type":"string"}},{"name":"startEvent","required":true,"in":"query","schema":{"type":"string"}},{"name":"endEvent","required":true,"in":"query","schema":{"type":"string"}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["event-log"]}},"/admin/flags/flags":{"get":{"operationId":"FeatureFlagsAdminController_getFlags[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FlagOutput"}}}}}},"tags":["admin"]}},"/v1/admin/flags/flags":{"get":{"operationId":"FeatureFlagsAdminController_getFlags[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FlagOutput"}}}}}},"tags":["admin"]}},"/admin/flags/flag":{"post":{"operationId":"FeatureFlagsAdminController_createFlag[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagInput"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagOutput"}}}}},"tags":["admin"]}},"/v1/admin/flags/flag":{"post":{"operationId":"FeatureFlagsAdminController_createFlag[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagInput"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagOutput"}}}}},"tags":["admin"]}},"/admin/flags/flag/{flagId}":{"put":{"operationId":"FeatureFlagsAdminController_updateFlag[0]","parameters":[{"name":"flagId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagInput"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagOutput"}}}}},"tags":["admin"]},"delete":{"operationId":"FeatureFlagsAdminController_deleteFlag[0]","parameters":[{"name":"flagId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete a feature flag and its rules.\n\nRequires the `FLAG_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).\n\n`GET flag/:flagId/deletion-preview` shows what this would remove, without removing it.","tags":["admin"]}},"/v1/admin/flags/flag/{flagId}":{"put":{"operationId":"FeatureFlagsAdminController_updateFlag[1]_v1","parameters":[{"name":"flagId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagInput"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagOutput"}}}}},"tags":["admin"]},"delete":{"operationId":"FeatureFlagsAdminController_deleteFlag[1]_v1","parameters":[{"name":"flagId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete a feature flag and its rules.\n\nRequires the `FLAG_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).\n\n`GET flag/:flagId/deletion-preview` shows what this would remove, without removing it.","tags":["admin"]}},"/admin/flags/flag/{flagId}/deletion-preview":{"get":{"operationId":"FeatureFlagsAdminController_previewDeleteFlag[0]","parameters":[{"name":"flagId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Preview deleting a feature flag: the flag and what deleting it does. Deletes nothing.\n\nNeeds the same `FLAG_DELETE` privilege as the delete.","tags":["admin"]}},"/v1/admin/flags/flag/{flagId}/deletion-preview":{"get":{"operationId":"FeatureFlagsAdminController_previewDeleteFlag[1]_v1","parameters":[{"name":"flagId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Preview deleting a feature flag: the flag and what deleting it does. Deletes nothing.\n\nNeeds the same `FLAG_DELETE` privilege as the delete.","tags":["admin"]}},"/admin/flags/segments":{"get":{"operationId":"FeatureFlagsAdminController_getSegments[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SegmentOutput"}}}}}},"tags":["admin"]}},"/v1/admin/flags/segments":{"get":{"operationId":"FeatureFlagsAdminController_getSegments[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SegmentOutput"}}}}}},"tags":["admin"]}},"/admin/flags/segment":{"post":{"operationId":"FeatureFlagsAdminController_createSegment[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentInput"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentOutput"}}}}},"tags":["admin"]}},"/v1/admin/flags/segment":{"post":{"operationId":"FeatureFlagsAdminController_createSegment[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentInput"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentOutput"}}}}},"tags":["admin"]}},"/admin/flags/segment/{segmentId}":{"put":{"operationId":"FeatureFlagsAdminController_updateSegment[0]","parameters":[{"name":"segmentId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentInput"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentOutput"}}}}},"tags":["admin"]},"delete":{"operationId":"FeatureFlagsAdminController_deleteSegment[0]","parameters":[{"name":"segmentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete an audience segment.\n\nRequires the `FLAG_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["admin"]}},"/v1/admin/flags/segment/{segmentId}":{"put":{"operationId":"FeatureFlagsAdminController_updateSegment[1]_v1","parameters":[{"name":"segmentId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentInput"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentOutput"}}}}},"tags":["admin"]},"delete":{"operationId":"FeatureFlagsAdminController_deleteSegment[1]_v1","parameters":[{"name":"segmentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Permanently delete an audience segment.\n\nRequires the `FLAG_DELETE` privilege on the calling API token. Destructive privileges are opt-in and are never granted by default, so a token without it is refused with 403 (TBP-552).","tags":["admin"]}},"/admin/flags-internal/flags/{appId}":{"get":{"operationId":"FeatureFlagsInternalController_getFlags[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}},"tags":["internal"]}},"/v1/admin/flags-internal/flags/{appId}":{"get":{"operationId":"FeatureFlagsInternalController_getFlags[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}},"tags":["internal"]}},"/admin/flags-internal/flags-cache/{appId}":{"get":{"operationId":"FeatureFlagsInternalController_getFlagsCache[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}},"summary":"Hydration endpoint for the FF 2.0 SDK cache. Returns all enabled flags for\nthe workspace in the same `CachedFlag` shape the realtime `flag.updated`\npush delivers, so the SDK can call `bridge.hydrate(flags)` on init and\nhave the cache populated before the first `bridge.flag()` call.","tags":["internal"]}},"/v1/admin/flags-internal/flags-cache/{appId}":{"get":{"operationId":"FeatureFlagsInternalController_getFlagsCache[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}}},"summary":"Hydration endpoint for the FF 2.0 SDK cache. Returns all enabled flags for\nthe workspace in the same `CachedFlag` shape the realtime `flag.updated`\npush delivers, so the SDK can call `bridge.hydrate(flags)` on init and\nhave the cache populated before the first `bridge.flag()` call.","tags":["internal"]}},"/admin/flags/onboarding/status":{"get":{"description":"Returns per-signal detection state for the FF onboarding wizard. Polled every 5–7s by `/onboarding/flags` while the user is integrating.","operationId":"OnboardingStatusController_getStatus[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagOnboardingStatusDto"}}}}},"summary":"Feature-flag onboarding live-signal status (TBP-205)","tags":["admin"]}},"/v1/admin/flags/onboarding/status":{"get":{"description":"Returns per-signal detection state for the FF onboarding wizard. Polled every 5–7s by `/onboarding/flags` while the user is integrating.","operationId":"OnboardingStatusController_getStatus[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagOnboardingStatusDto"}}}}},"summary":"Feature-flag onboarding live-signal status (TBP-205)","tags":["admin"]}},"/mcp":{"post":{"operationId":"McpController_handleMcpRequest[0]","parameters":[],"responses":{"201":{"description":""}},"summary":"MCP Streamable HTTP endpoint. Requires `Authorization: Bearer <ApiToken JWT>`;\nunauthenticated calls answer 401 with a `WWW-Authenticate` header pointing at\nthe OAuth protected-resource metadata. Stateless — no session is created.","tags":["mcp"]},"get":{"operationId":"McpController_handleMcpGet[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Stateless server: there is no SSE stream to resume. 405 per the MCP\nstreamable-http spec, JSON-RPC-shaped body.","tags":["mcp"]},"delete":{"operationId":"McpController_handleMcpDelete[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Stateless server: there is no session to delete. 405 per the MCP\nstreamable-http spec, JSON-RPC-shaped body.","tags":["mcp"]}},"/v1/mcp":{"post":{"operationId":"McpController_handleMcpRequest[1]_v1","parameters":[],"responses":{"201":{"description":""}},"summary":"MCP Streamable HTTP endpoint. Requires `Authorization: Bearer <ApiToken JWT>`;\nunauthenticated calls answer 401 with a `WWW-Authenticate` header pointing at\nthe OAuth protected-resource metadata. Stateless — no session is created.","tags":["mcp"]},"get":{"operationId":"McpController_handleMcpGet[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Stateless server: there is no SSE stream to resume. 405 per the MCP\nstreamable-http spec, JSON-RPC-shaped body.","tags":["mcp"]},"delete":{"operationId":"McpController_handleMcpDelete[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Stateless server: there is no session to delete. 405 per the MCP\nstreamable-http spec, JSON-RPC-shaped body.","tags":["mcp"]}},"/cli/workspace/apps":{"get":{"operationId":"CliWorkspaceController_listApps[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"List the apps this CLI login can act on, and which one it was signed for.","tags":["cli-workspace"]},"post":{"operationId":"CliWorkspaceController_createApp[0]","parameters":[],"responses":{"201":{"description":""}},"summary":"Create an app in the workspace of the person who logged in.","tags":["cli-workspace"]}},"/v1/cli/workspace/apps":{"get":{"operationId":"CliWorkspaceController_listApps[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"List the apps this CLI login can act on, and which one it was signed for.","tags":["cli-workspace"]},"post":{"operationId":"CliWorkspaceController_createApp[1]_v1","parameters":[],"responses":{"201":{"description":""}},"summary":"Create an app in the workspace of the person who logged in.","tags":["cli-workspace"]}},"/cli/workspace/apps/{appId}/token":{"post":{"operationId":"CliWorkspaceController_tokenForApp[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Issue the token one CLI command uses on one app of this login.","tags":["cli-workspace"]}},"/v1/cli/workspace/apps/{appId}/token":{"post":{"operationId":"CliWorkspaceController_tokenForApp[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Issue the token one CLI command uses on one app of this login.","tags":["cli-workspace"]}},"/.well-known/mcp/server-card.json":{"get":{"description":"Static description of the Bridge MCP server for directories: identity, the remote endpoint, OAuth 2 sign-in, and its tools, prompts and resources. No sign-in needed.","operationId":"McpServerCardController_getServerCard","parameters":[],"responses":{"200":{"description":"MCP server card"}},"summary":"MCP server card","tags":["mcp"]}},"/account/integration/diagnose":{"post":{"operationId":"IntegrationCheckController_diagnose[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnoseIntegrationRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Compare a project's Bridge env vars against the app and list every difference with its fix.","tags":["account"]}},"/v1/account/integration/diagnose":{"post":{"operationId":"IntegrationCheckController_diagnose[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiagnoseIntegrationRequestDto"}}}},"responses":{"200":{"description":""}},"summary":"Compare a project's Bridge env vars against the app and list every difference with its fix.","tags":["account"]}},"/account/integration/status":{"get":{"operationId":"IntegrationCheckController_status[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Readiness checklist: what is configured, what is missing, and the next step for each.","tags":["account"]}},"/v1/account/integration/status":{"get":{"operationId":"IntegrationCheckController_status[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Readiness checklist: what is configured, what is missing, and the next step for each.","tags":["account"]}},"/account/integration/test-user":{"post":{"operationId":"IntegrationCheckController_createTestUser[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestUserRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Create a marked test user in its own marked workspace, with a generated password.","tags":["account"]}},"/v1/account/integration/test-user":{"post":{"operationId":"IntegrationCheckController_createTestUser[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestUserRequestDto"}}}},"responses":{"201":{"description":""}},"summary":"Create a marked test user in its own marked workspace, with a generated password.","tags":["account"]}},"/account/integration/verify-login":{"post":{"operationId":"IntegrationCheckController_verifyLogin[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyLoginRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Sign in for real and verify the issued token against the JWKS; returns evidence, never tokens.","tags":["account"]}},"/v1/account/integration/verify-login":{"post":{"operationId":"IntegrationCheckController_verifyLogin[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyLoginRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Sign in for real and verify the issued token against the JWKS; returns evidence, never tokens.","tags":["account"]}},"/account/integration/auth-attempts":{"get":{"operationId":"IntegrationCheckController_authAttempts[0]","parameters":[{"name":"user","required":true,"in":"query","schema":{"type":"string"}},{"name":"since","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"A user's recent sign-in attempts, each failure with its reason and fix.","tags":["account"]}},"/v1/account/integration/auth-attempts":{"get":{"operationId":"IntegrationCheckController_authAttempts[1]_v1","parameters":[{"name":"user","required":true,"in":"query","schema":{"type":"string"}},{"name":"since","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"A user's recent sign-in attempts, each failure with its reason and fix.","tags":["account"]}},"/auth/authenticate":{"post":{"description":"Submit username/password credentials. Returns session token and tenant user info.","operationId":"PasswordController_authenticate[0]","parameters":[],"responses":{"200":{"description":"Authentication successful"},"401":{"description":"Invalid credentials or expired OAuth context"}},"summary":"Authenticate with password","tags":["auth"]}},"/auth/auth/authenticate":{"post":{"description":"Submit username/password credentials. Returns session token and tenant user info.","operationId":"PasswordController_authenticate[1]","parameters":[],"responses":{"200":{"description":"Authentication successful"},"401":{"description":"Invalid credentials or expired OAuth context"}},"summary":"Authenticate with password","tags":["auth"]}},"/v1/auth/authenticate":{"post":{"description":"Submit username/password credentials. Returns session token and tenant user info.","operationId":"PasswordController_authenticate[2]_v1","parameters":[],"responses":{"200":{"description":"Authentication successful"},"401":{"description":"Invalid credentials or expired OAuth context"}},"summary":"Authenticate with password","tags":["auth"]}},"/v1/auth/auth/authenticate":{"post":{"description":"Submit username/password credentials. Returns session token and tenant user info.","operationId":"PasswordController_authenticate[3]_v1","parameters":[],"responses":{"200":{"description":"Authentication successful"},"401":{"description":"Invalid credentials or expired OAuth context"}},"summary":"Authenticate with password","tags":["auth"]}},"/auth/token":{"post":{"description":"Standard OAuth 2.0 token endpoint. Exchange an authorization code or refresh token for access/id tokens.","operationId":"TokenController_exchangeToken[0]","parameters":[],"responses":{"200":{"description":"Token exchange successful"},"400":{"description":"Invalid grant type or missing parameters"}},"summary":"Exchange tokens","tags":["auth"]}},"/v1/auth/token":{"post":{"description":"Standard OAuth 2.0 token endpoint. Exchange an authorization code or refresh token for access/id tokens.","operationId":"TokenController_exchangeToken[1]_v1","parameters":[],"responses":{"200":{"description":"Token exchange successful"},"400":{"description":"Invalid grant type or missing parameters"}},"summary":"Exchange tokens","tags":["auth"]}},"/auth/token/direct":{"post":{"description":"Exchange a session JWT and tenantUserId for access/refresh/id tokens. SDK mode only.","operationId":"TokenController_directTokenExchange[0]","parameters":[],"responses":{"200":{"description":"Token issuance successful"},"401":{"description":"Invalid session, MFA not completed, or tenant user mismatch"}},"summary":"Direct token exchange (SDK)","tags":["auth"]}},"/v1/auth/token/direct":{"post":{"description":"Exchange a session JWT and tenantUserId for access/refresh/id tokens. SDK mode only.","operationId":"TokenController_directTokenExchange[1]_v1","parameters":[],"responses":{"200":{"description":"Token issuance successful"},"401":{"description":"Invalid session, MFA not completed, or tenant user mismatch"}},"summary":"Direct token exchange (SDK)","tags":["auth"]}},"/auth/token/code-from-token/{appId}":{"post":{"description":"Convert an SDK access token into a short-lived authorization code for OAuth callback.","operationId":"TokenController_generateCodeFromToken[0]","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Authorization code generated"},"401":{"description":"Invalid access token or mismatched app"}},"summary":"Generate auth code from access token","tags":["auth"]}},"/v1/auth/token/code-from-token/{appId}":{"post":{"description":"Convert an SDK access token into a short-lived authorization code for OAuth callback.","operationId":"TokenController_generateCodeFromToken[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Authorization code generated"},"401":{"description":"Invalid access token or mismatched app"}},"summary":"Generate auth code from access token","tags":["auth"]}},"/auth/token/cloudviews-session":{"post":{"description":"Exchange a one-shot cloud-views session ticket for SDK access/refresh/id tokens. Used by /cli/authorize after federated CLI login.","operationId":"TokenController_redeemCloudViewsSession[0]","parameters":[],"responses":{"200":{"description":"Token issuance successful"},"401":{"description":"Invalid, expired, or already-redeemed ticket"}},"summary":"Redeem cloud-views session ticket","tags":["auth"]}},"/v1/auth/token/cloudviews-session":{"post":{"description":"Exchange a one-shot cloud-views session ticket for SDK access/refresh/id tokens. Used by /cli/authorize after federated CLI login.","operationId":"TokenController_redeemCloudViewsSession[1]_v1","parameters":[],"responses":{"200":{"description":"Token issuance successful"},"401":{"description":"Invalid, expired, or already-redeemed ticket"}},"summary":"Redeem cloud-views session ticket","tags":["auth"]}},"/auth/token/workspace-list":{"post":{"description":"Return all workspaces the authenticated user has access to.","operationId":"TokenController_workspaceList[0]","parameters":[],"responses":{"200":{"description":"List of workspaces"},"401":{"description":"Invalid access token"}},"summary":"List workspaces (SDK)","tags":["auth"]}},"/v1/auth/token/workspace-list":{"post":{"description":"Return all workspaces the authenticated user has access to.","operationId":"TokenController_workspaceList[1]_v1","parameters":[],"responses":{"200":{"description":"List of workspaces"},"401":{"description":"Invalid access token"}},"summary":"List workspaces (SDK)","tags":["auth"]}},"/auth/token/workspace-switch":{"post":{"description":"Exchange a valid access token and targetTenantUserId for new tokens scoped to the target tenant.","operationId":"TokenController_workspaceSwitch[0]","parameters":[],"responses":{"200":{"description":"New tokens issued for target workspace"},"401":{"description":"Invalid access token or targetTenantUserId does not belong to this user"}},"summary":"Workspace switch (SDK)","tags":["auth"]}},"/v1/auth/token/workspace-switch":{"post":{"description":"Exchange a valid access token and targetTenantUserId for new tokens scoped to the target tenant.","operationId":"TokenController_workspaceSwitch[1]_v1","parameters":[],"responses":{"200":{"description":"New tokens issued for target workspace"},"401":{"description":"Invalid access token or targetTenantUserId does not belong to this user"}},"summary":"Workspace switch (SDK)","tags":["auth"]}},"/auth/token/{grant}/{appId}":{"post":{"description":"Exchange auth code or refresh token using app-specific defaults. Grant is \"code\" or \"refresh\".","operationId":"TokenController_exchangeTokenShorthand[0]","parameters":[{"name":"grant","required":true,"in":"path","description":"Grant type shorthand","schema":{"enum":["code","refresh"],"type":"string"}},{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Token exchange successful"},"400":{"description":"Invalid grant type"}},"summary":"Shorthand token exchange","tags":["auth"]}},"/v1/auth/token/{grant}/{appId}":{"post":{"description":"Exchange auth code or refresh token using app-specific defaults. Grant is \"code\" or \"refresh\".","operationId":"TokenController_exchangeTokenShorthand[1]_v1","parameters":[{"name":"grant","required":true,"in":"path","description":"Grant type shorthand","schema":{"enum":["code","refresh"],"type":"string"}},{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Token exchange successful"},"400":{"description":"Invalid grant type"}},"summary":"Shorthand token exchange","tags":["auth"]}},"/auth/refresh-token":{"post":{"description":"TBP-90 SDK flow. Re-fetches user/tenant state from mongo and issues a fresh JWT with current claims (role, plan, tokenVersion). Accepts the current access token in the Bearer header; expired tokens are accepted within a 5-minute grace window.","operationId":"RefreshTokenController_refreshToken[0]","parameters":[{"name":"authorization","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Fresh tokens issued"},"401":{"description":"Missing / invalid / too-stale Bearer token"}},"summary":"Refresh access token via realtime state-change signal","tags":["auth"]}},"/v1/auth/refresh-token":{"post":{"description":"TBP-90 SDK flow. Re-fetches user/tenant state from mongo and issues a fresh JWT with current claims (role, plan, tokenVersion). Accepts the current access token in the Bearer header; expired tokens are accepted within a 5-minute grace window.","operationId":"RefreshTokenController_refreshToken[1]_v1","parameters":[{"name":"authorization","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Fresh tokens issued"},"401":{"description":"Missing / invalid / too-stale Bearer token"}},"summary":"Refresh access token via realtime state-change signal","tags":["auth"]}},"/auth/me":{"get":{"description":"Debug endpoint returning current OAuth context and session state.","operationId":"AuthCoreController_getMe[0]","parameters":[],"responses":{"200":{"description":"Current auth context and session info"}},"summary":"Get current auth state","tags":["auth"]}},"/auth/auth/me":{"get":{"description":"Debug endpoint returning current OAuth context and session state.","operationId":"AuthCoreController_getMe[1]","parameters":[],"responses":{"200":{"description":"Current auth context and session info"}},"summary":"Get current auth state","tags":["auth"]}},"/v1/auth/me":{"get":{"description":"Debug endpoint returning current OAuth context and session state.","operationId":"AuthCoreController_getMe[2]_v1","parameters":[],"responses":{"200":{"description":"Current auth context and session info"}},"summary":"Get current auth state","tags":["auth"]}},"/v1/auth/auth/me":{"get":{"description":"Debug endpoint returning current OAuth context and session state.","operationId":"AuthCoreController_getMe[3]_v1","parameters":[],"responses":{"200":{"description":"Current auth context and session info"}},"summary":"Get current auth state","tags":["auth"]}},"/auth/logout":{"get":{"description":"Clear session and OAuth context cookies.","operationId":"AuthCoreController_logout[0]","parameters":[],"responses":{"200":{"description":"Cookies cleared"}},"summary":"Logout","tags":["auth"]}},"/auth/auth/logout":{"get":{"description":"Clear session and OAuth context cookies.","operationId":"AuthCoreController_logout[1]","parameters":[],"responses":{"200":{"description":"Cookies cleared"}},"summary":"Logout","tags":["auth"]}},"/v1/auth/logout":{"get":{"description":"Clear session and OAuth context cookies.","operationId":"AuthCoreController_logout[2]_v1","parameters":[],"responses":{"200":{"description":"Cookies cleared"}},"summary":"Logout","tags":["auth"]}},"/v1/auth/auth/logout":{"get":{"description":"Clear session and OAuth context cookies.","operationId":"AuthCoreController_logout[3]_v1","parameters":[],"responses":{"200":{"description":"Cookies cleared"}},"summary":"Logout","tags":["auth"]}},"/auth/federation/{appId}":{"get":{"description":"Initiate SSO federation flow for SDK popup mode. Creates OAuth context and redirects to the federation provider.","operationId":"AuthCoreController_startFederation[0]","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"provider","required":true,"in":"query","schema":{"type":"string"}},{"name":"mode","required":true,"in":"query","schema":{"type":"string"}},{"name":"targetOrigin","required":true,"in":"query","schema":{"type":"string"}},{"name":"redirect_uri","required":true,"in":"query","schema":{"type":"string"}},{"name":"cli_flow","required":true,"in":"query","schema":{"type":"string"}},{"name":"cli_return","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to federation provider"}},"summary":"Start federation SSO","tags":["auth"]}},"/auth/auth/federation/{appId}":{"get":{"description":"Initiate SSO federation flow for SDK popup mode. Creates OAuth context and redirects to the federation provider.","operationId":"AuthCoreController_startFederation[1]","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"provider","required":true,"in":"query","schema":{"type":"string"}},{"name":"mode","required":true,"in":"query","schema":{"type":"string"}},{"name":"targetOrigin","required":true,"in":"query","schema":{"type":"string"}},{"name":"redirect_uri","required":true,"in":"query","schema":{"type":"string"}},{"name":"cli_flow","required":true,"in":"query","schema":{"type":"string"}},{"name":"cli_return","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to federation provider"}},"summary":"Start federation SSO","tags":["auth"]}},"/v1/auth/federation/{appId}":{"get":{"description":"Initiate SSO federation flow for SDK popup mode. Creates OAuth context and redirects to the federation provider.","operationId":"AuthCoreController_startFederation[2]_v1","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"provider","required":true,"in":"query","schema":{"type":"string"}},{"name":"mode","required":true,"in":"query","schema":{"type":"string"}},{"name":"targetOrigin","required":true,"in":"query","schema":{"type":"string"}},{"name":"redirect_uri","required":true,"in":"query","schema":{"type":"string"}},{"name":"cli_flow","required":true,"in":"query","schema":{"type":"string"}},{"name":"cli_return","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to federation provider"}},"summary":"Start federation SSO","tags":["auth"]}},"/v1/auth/auth/federation/{appId}":{"get":{"description":"Initiate SSO federation flow for SDK popup mode. Creates OAuth context and redirects to the federation provider.","operationId":"AuthCoreController_startFederation[3]_v1","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"provider","required":true,"in":"query","schema":{"type":"string"}},{"name":"mode","required":true,"in":"query","schema":{"type":"string"}},{"name":"targetOrigin","required":true,"in":"query","schema":{"type":"string"}},{"name":"redirect_uri","required":true,"in":"query","schema":{"type":"string"}},{"name":"cli_flow","required":true,"in":"query","schema":{"type":"string"}},{"name":"cli_return","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to federation provider"}},"summary":"Start federation SSO","tags":["auth"]}},"/auth/credentialsConfig":{"post":{"description":"Check what authentication methods are available for a username (password, passkeys, federation).","operationId":"AuthCoreController_getCredentialsConfig[0]","parameters":[],"responses":{"200":{"description":"Available authentication methods"},"401":{"description":"Invalid OAuth context or unknown user"}},"summary":"Get credentials config","tags":["auth"]}},"/auth/auth/credentialsConfig":{"post":{"description":"Check what authentication methods are available for a username (password, passkeys, federation).","operationId":"AuthCoreController_getCredentialsConfig[1]","parameters":[],"responses":{"200":{"description":"Available authentication methods"},"401":{"description":"Invalid OAuth context or unknown user"}},"summary":"Get credentials config","tags":["auth"]}},"/v1/auth/credentialsConfig":{"post":{"description":"Check what authentication methods are available for a username (password, passkeys, federation).","operationId":"AuthCoreController_getCredentialsConfig[2]_v1","parameters":[],"responses":{"200":{"description":"Available authentication methods"},"401":{"description":"Invalid OAuth context or unknown user"}},"summary":"Get credentials config","tags":["auth"]}},"/v1/auth/auth/credentialsConfig":{"post":{"description":"Check what authentication methods are available for a username (password, passkeys, federation).","operationId":"AuthCoreController_getCredentialsConfig[3]_v1","parameters":[],"responses":{"200":{"description":"Available authentication methods"},"401":{"description":"Invalid OAuth context or unknown user"}},"summary":"Get credentials config","tags":["auth"]}},"/auth/tenantUsers":{"get":{"description":"Get available tenant users for the authenticated session.","operationId":"AuthCoreController_getTenantUsers[0]","parameters":[],"responses":{"200":{"description":"List of tenant users"},"401":{"description":"Invalid session or OAuth context"}},"summary":"List tenant users","tags":["auth"]}},"/auth/auth/tenantUsers":{"get":{"description":"Get available tenant users for the authenticated session.","operationId":"AuthCoreController_getTenantUsers[1]","parameters":[],"responses":{"200":{"description":"List of tenant users"},"401":{"description":"Invalid session or OAuth context"}},"summary":"List tenant users","tags":["auth"]}},"/v1/auth/tenantUsers":{"get":{"description":"Get available tenant users for the authenticated session.","operationId":"AuthCoreController_getTenantUsers[2]_v1","parameters":[],"responses":{"200":{"description":"List of tenant users"},"401":{"description":"Invalid session or OAuth context"}},"summary":"List tenant users","tags":["auth"]}},"/v1/auth/auth/tenantUsers":{"get":{"description":"Get available tenant users for the authenticated session.","operationId":"AuthCoreController_getTenantUsers[3]_v1","parameters":[],"responses":{"200":{"description":"List of tenant users"},"401":{"description":"Invalid session or OAuth context"}},"summary":"List tenant users","tags":["auth"]}},"/auth/commitMfaCode":{"post":{"description":"Verify an MFA code to complete the multi-factor authentication step.","operationId":"AuthCoreController_commitMfaCode[0]","parameters":[],"responses":{"200":{"description":"MFA code verified, session updated"},"400":{"description":"Invalid MFA code"},"401":{"description":"Invalid session"}},"summary":"Submit MFA code","tags":["auth"]}},"/auth/auth/commitMfaCode":{"post":{"description":"Verify an MFA code to complete the multi-factor authentication step.","operationId":"AuthCoreController_commitMfaCode[1]","parameters":[],"responses":{"200":{"description":"MFA code verified, session updated"},"400":{"description":"Invalid MFA code"},"401":{"description":"Invalid session"}},"summary":"Submit MFA code","tags":["auth"]}},"/v1/auth/commitMfaCode":{"post":{"description":"Verify an MFA code to complete the multi-factor authentication step.","operationId":"AuthCoreController_commitMfaCode[2]_v1","parameters":[],"responses":{"200":{"description":"MFA code verified, session updated"},"400":{"description":"Invalid MFA code"},"401":{"description":"Invalid session"}},"summary":"Submit MFA code","tags":["auth"]}},"/v1/auth/auth/commitMfaCode":{"post":{"description":"Verify an MFA code to complete the multi-factor authentication step.","operationId":"AuthCoreController_commitMfaCode[3]_v1","parameters":[],"responses":{"200":{"description":"MFA code verified, session updated"},"400":{"description":"Invalid MFA code"},"401":{"description":"Invalid session"}},"summary":"Submit MFA code","tags":["auth"]}},"/auth/resendMfaCode":{"post":{"description":"Resend the MFA SMS code during the MFA challenge step.","operationId":"AuthCoreController_resendMfaCode[0]","parameters":[],"responses":{"200":{"description":"New MFA code sent"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Resend MFA code","tags":["auth"]}},"/auth/auth/resendMfaCode":{"post":{"description":"Resend the MFA SMS code during the MFA challenge step.","operationId":"AuthCoreController_resendMfaCode[1]","parameters":[],"responses":{"200":{"description":"New MFA code sent"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Resend MFA code","tags":["auth"]}},"/v1/auth/resendMfaCode":{"post":{"description":"Resend the MFA SMS code during the MFA challenge step.","operationId":"AuthCoreController_resendMfaCode[2]_v1","parameters":[],"responses":{"200":{"description":"New MFA code sent"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Resend MFA code","tags":["auth"]}},"/v1/auth/auth/resendMfaCode":{"post":{"description":"Resend the MFA SMS code during the MFA challenge step.","operationId":"AuthCoreController_resendMfaCode[3]_v1","parameters":[],"responses":{"200":{"description":"New MFA code sent"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Resend MFA code","tags":["auth"]}},"/auth/startMfaUserSetup":{"post":{"description":"Begin MFA setup by sending an SMS verification code to the provided phone number.","operationId":"AuthCoreController_startMfaUserSetup[0]","parameters":[],"responses":{"200":{"description":"SMS code sent"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Start MFA setup","tags":["auth"]}},"/auth/auth/startMfaUserSetup":{"post":{"description":"Begin MFA setup by sending an SMS verification code to the provided phone number.","operationId":"AuthCoreController_startMfaUserSetup[1]","parameters":[],"responses":{"200":{"description":"SMS code sent"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Start MFA setup","tags":["auth"]}},"/v1/auth/startMfaUserSetup":{"post":{"description":"Begin MFA setup by sending an SMS verification code to the provided phone number.","operationId":"AuthCoreController_startMfaUserSetup[2]_v1","parameters":[],"responses":{"200":{"description":"SMS code sent"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Start MFA setup","tags":["auth"]}},"/v1/auth/auth/startMfaUserSetup":{"post":{"description":"Begin MFA setup by sending an SMS verification code to the provided phone number.","operationId":"AuthCoreController_startMfaUserSetup[3]_v1","parameters":[],"responses":{"200":{"description":"SMS code sent"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Start MFA setup","tags":["auth"]}},"/auth/finishMfaUserSetup":{"post":{"description":"Complete MFA setup by verifying the SMS code and registering the phone number.","operationId":"AuthCoreController_finishMfaUserSetup[0]","parameters":[],"responses":{"200":{"description":"MFA setup completed"},"400":{"description":"Invalid MFA code"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Finish MFA setup","tags":["auth"]}},"/auth/auth/finishMfaUserSetup":{"post":{"description":"Complete MFA setup by verifying the SMS code and registering the phone number.","operationId":"AuthCoreController_finishMfaUserSetup[1]","parameters":[],"responses":{"200":{"description":"MFA setup completed"},"400":{"description":"Invalid MFA code"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Finish MFA setup","tags":["auth"]}},"/v1/auth/finishMfaUserSetup":{"post":{"description":"Complete MFA setup by verifying the SMS code and registering the phone number.","operationId":"AuthCoreController_finishMfaUserSetup[2]_v1","parameters":[],"responses":{"200":{"description":"MFA setup completed"},"400":{"description":"Invalid MFA code"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Finish MFA setup","tags":["auth"]}},"/v1/auth/auth/finishMfaUserSetup":{"post":{"description":"Complete MFA setup by verifying the SMS code and registering the phone number.","operationId":"AuthCoreController_finishMfaUserSetup[3]_v1","parameters":[],"responses":{"200":{"description":"MFA setup completed"},"400":{"description":"Invalid MFA code"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Finish MFA setup","tags":["auth"]}},"/auth/resetUserMfaSetup":{"post":{"description":"Reset MFA using a backup code. Allows re-enrollment with a new phone number.","operationId":"AuthCoreController_resetUserMfaSetup[0]","parameters":[],"responses":{"200":{"description":"MFA reset successful"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Reset MFA setup","tags":["auth"]}},"/auth/auth/resetUserMfaSetup":{"post":{"description":"Reset MFA using a backup code. Allows re-enrollment with a new phone number.","operationId":"AuthCoreController_resetUserMfaSetup[1]","parameters":[],"responses":{"200":{"description":"MFA reset successful"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Reset MFA setup","tags":["auth"]}},"/v1/auth/resetUserMfaSetup":{"post":{"description":"Reset MFA using a backup code. Allows re-enrollment with a new phone number.","operationId":"AuthCoreController_resetUserMfaSetup[2]_v1","parameters":[],"responses":{"200":{"description":"MFA reset successful"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Reset MFA setup","tags":["auth"]}},"/v1/auth/auth/resetUserMfaSetup":{"post":{"description":"Reset MFA using a backup code. Allows re-enrollment with a new phone number.","operationId":"AuthCoreController_resetUserMfaSetup[3]_v1","parameters":[],"responses":{"200":{"description":"MFA reset successful"},"401":{"description":"Invalid session or wrong MFA state"}},"summary":"Reset MFA setup","tags":["auth"]}},"/auth/error":{"get":{"description":"Redirects to error callback URL based on OAuth context.","operationId":"AuthCoreController_handleError[0]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"},"401":{"description":"Invalid OAuth context"}},"summary":"Handle auth error","tags":["auth"]}},"/auth/auth/error":{"get":{"description":"Redirects to error callback URL based on OAuth context.","operationId":"AuthCoreController_handleError[1]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"},"401":{"description":"Invalid OAuth context"}},"summary":"Handle auth error","tags":["auth"]}},"/v1/auth/error":{"get":{"description":"Redirects to error callback URL based on OAuth context.","operationId":"AuthCoreController_handleError[2]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"},"401":{"description":"Invalid OAuth context"}},"summary":"Handle auth error","tags":["auth"]}},"/v1/auth/auth/error":{"get":{"description":"Redirects to error callback URL based on OAuth context.","operationId":"AuthCoreController_handleError[3]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"},"401":{"description":"Invalid OAuth context"}},"summary":"Handle auth error","tags":["auth"]}},"/auth/error/magic-link/expired":{"get":{"description":"Redirects to error page for expired magic links.","operationId":"AuthCoreController_handleMagicLinkExpiredError[0]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Handle magic link expired error","tags":["auth"]}},"/auth/auth/error/magic-link/expired":{"get":{"description":"Redirects to error page for expired magic links.","operationId":"AuthCoreController_handleMagicLinkExpiredError[1]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Handle magic link expired error","tags":["auth"]}},"/v1/auth/error/magic-link/expired":{"get":{"description":"Redirects to error page for expired magic links.","operationId":"AuthCoreController_handleMagicLinkExpiredError[2]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Handle magic link expired error","tags":["auth"]}},"/v1/auth/auth/error/magic-link/expired":{"get":{"description":"Redirects to error page for expired magic links.","operationId":"AuthCoreController_handleMagicLinkExpiredError[3]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Handle magic link expired error","tags":["auth"]}},"/auth/revoke":{"post":{"description":"Marks a refresh token as revoked so it can no longer be used to obtain new access tokens.","operationId":"AuthCoreController_revokeToken[0]","parameters":[],"responses":{"200":{"description":"Token revoked (or was already invalid)"}},"summary":"Revoke refresh token","tags":["auth"]}},"/auth/auth/revoke":{"post":{"description":"Marks a refresh token as revoked so it can no longer be used to obtain new access tokens.","operationId":"AuthCoreController_revokeToken[1]","parameters":[],"responses":{"200":{"description":"Token revoked (or was already invalid)"}},"summary":"Revoke refresh token","tags":["auth"]}},"/v1/auth/revoke":{"post":{"description":"Marks a refresh token as revoked so it can no longer be used to obtain new access tokens.","operationId":"AuthCoreController_revokeToken[2]_v1","parameters":[],"responses":{"200":{"description":"Token revoked (or was already invalid)"}},"summary":"Revoke refresh token","tags":["auth"]}},"/v1/auth/auth/revoke":{"post":{"description":"Marks a refresh token as revoked so it can no longer be used to obtain new access tokens.","operationId":"AuthCoreController_revokeToken[3]_v1","parameters":[],"responses":{"200":{"description":"Token revoked (or was already invalid)"}},"summary":"Revoke refresh token","tags":["auth"]}},"/auth/error/federation/missingUser/{federation}":{"get":{"description":"Redirects to error page when a federated user is not found.","operationId":"AuthCoreController_handleFederationMissingUserError[0]","parameters":[{"name":"federation","required":true,"in":"path","description":"Federation provider type","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Handle federation missing user error","tags":["auth"]}},"/auth/auth/error/federation/missingUser/{federation}":{"get":{"description":"Redirects to error page when a federated user is not found.","operationId":"AuthCoreController_handleFederationMissingUserError[1]","parameters":[{"name":"federation","required":true,"in":"path","description":"Federation provider type","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Handle federation missing user error","tags":["auth"]}},"/v1/auth/error/federation/missingUser/{federation}":{"get":{"description":"Redirects to error page when a federated user is not found.","operationId":"AuthCoreController_handleFederationMissingUserError[2]_v1","parameters":[{"name":"federation","required":true,"in":"path","description":"Federation provider type","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Handle federation missing user error","tags":["auth"]}},"/v1/auth/auth/error/federation/missingUser/{federation}":{"get":{"description":"Redirects to error page when a federated user is not found.","operationId":"AuthCoreController_handleFederationMissingUserError[3]_v1","parameters":[{"name":"federation","required":true,"in":"path","description":"Federation provider type","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Handle federation missing user error","tags":["auth"]}},"/auth/magic-link":{"post":{"description":"Send a magic link to the user's email for passwordless login.","operationId":"MagicLinkController_requestMagicLink[0]","parameters":[],"responses":{"200":{"description":"Magic link sent (or faked for non-existent users)"},"400":{"description":"successUrl is not one of the app's allowed origins"},"401":{"description":"Invalid OAuth context"}},"summary":"Request magic link","tags":["auth"]}},"/auth/auth/magic-link":{"post":{"description":"Send a magic link to the user's email for passwordless login.","operationId":"MagicLinkController_requestMagicLink[1]","parameters":[],"responses":{"200":{"description":"Magic link sent (or faked for non-existent users)"},"400":{"description":"successUrl is not one of the app's allowed origins"},"401":{"description":"Invalid OAuth context"}},"summary":"Request magic link","tags":["auth"]}},"/v1/auth/magic-link":{"post":{"description":"Send a magic link to the user's email for passwordless login.","operationId":"MagicLinkController_requestMagicLink[2]_v1","parameters":[],"responses":{"200":{"description":"Magic link sent (or faked for non-existent users)"},"400":{"description":"successUrl is not one of the app's allowed origins"},"401":{"description":"Invalid OAuth context"}},"summary":"Request magic link","tags":["auth"]}},"/v1/auth/auth/magic-link":{"post":{"description":"Send a magic link to the user's email for passwordless login.","operationId":"MagicLinkController_requestMagicLink[3]_v1","parameters":[],"responses":{"200":{"description":"Magic link sent (or faked for non-existent users)"},"400":{"description":"successUrl is not one of the app's allowed origins"},"401":{"description":"Invalid OAuth context"}},"summary":"Request magic link","tags":["auth"]}},"/auth/magic-link/login":{"get":{"description":"User clicks magic link from email. Validates token, creates session, redirects to next step.","operationId":"MagicLinkController_loginWithMagicLink[0]","parameters":[{"name":"t","required":true,"in":"query","description":"Magic link token","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Verify magic link","tags":["auth"]}},"/auth/auth/magic-link/login":{"get":{"description":"User clicks magic link from email. Validates token, creates session, redirects to next step.","operationId":"MagicLinkController_loginWithMagicLink[1]","parameters":[{"name":"t","required":true,"in":"query","description":"Magic link token","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Verify magic link","tags":["auth"]}},"/v1/auth/magic-link/login":{"get":{"description":"User clicks magic link from email. Validates token, creates session, redirects to next step.","operationId":"MagicLinkController_loginWithMagicLink[2]_v1","parameters":[{"name":"t","required":true,"in":"query","description":"Magic link token","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Verify magic link","tags":["auth"]}},"/v1/auth/auth/magic-link/login":{"get":{"description":"User clicks magic link from email. Validates token, creates session, redirects to next step.","operationId":"MagicLinkController_loginWithMagicLink[3]_v1","parameters":[{"name":"t","required":true,"in":"query","description":"Magic link token","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Verify magic link","tags":["auth"]}},"/auth/magic-link/test-token":{"get":{"operationId":"MagicLinkController_getTestMagicLinkToken[0]","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"username","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"GET /auth/magic-link/test-token — TEST ONLY (protected by playwright API key)\nReturns a valid magic link JWT without sending an email.\nUsed by e2e tests to test the /authenticate endpoint.","tags":["auth"]}},"/auth/auth/magic-link/test-token":{"get":{"operationId":"MagicLinkController_getTestMagicLinkToken[1]","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"username","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"GET /auth/magic-link/test-token — TEST ONLY (protected by playwright API key)\nReturns a valid magic link JWT without sending an email.\nUsed by e2e tests to test the /authenticate endpoint.","tags":["auth"]}},"/v1/auth/magic-link/test-token":{"get":{"operationId":"MagicLinkController_getTestMagicLinkToken[2]_v1","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"username","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"GET /auth/magic-link/test-token — TEST ONLY (protected by playwright API key)\nReturns a valid magic link JWT without sending an email.\nUsed by e2e tests to test the /authenticate endpoint.","tags":["auth"]}},"/v1/auth/auth/magic-link/test-token":{"get":{"operationId":"MagicLinkController_getTestMagicLinkToken[3]_v1","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"username","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"GET /auth/magic-link/test-token — TEST ONLY (protected by playwright API key)\nReturns a valid magic link JWT without sending an email.\nUsed by e2e tests to test the /authenticate endpoint.","tags":["auth"]}},"/auth/magic-link/authenticate":{"post":{"description":"Exchange a magic link JWT for an AuthResult (session + tenant users). SDK mode only.","operationId":"MagicLinkController_authenticateWithMagicLinkToken[0]","parameters":[],"responses":{"200":{"description":"Authentication successful, returns session and tenant users"},"401":{"description":"Invalid or expired magic link token"}},"summary":"Authenticate with magic link token (SDK mode)","tags":["auth"]}},"/auth/auth/magic-link/authenticate":{"post":{"description":"Exchange a magic link JWT for an AuthResult (session + tenant users). SDK mode only.","operationId":"MagicLinkController_authenticateWithMagicLinkToken[1]","parameters":[],"responses":{"200":{"description":"Authentication successful, returns session and tenant users"},"401":{"description":"Invalid or expired magic link token"}},"summary":"Authenticate with magic link token (SDK mode)","tags":["auth"]}},"/v1/auth/magic-link/authenticate":{"post":{"description":"Exchange a magic link JWT for an AuthResult (session + tenant users). SDK mode only.","operationId":"MagicLinkController_authenticateWithMagicLinkToken[2]_v1","parameters":[],"responses":{"200":{"description":"Authentication successful, returns session and tenant users"},"401":{"description":"Invalid or expired magic link token"}},"summary":"Authenticate with magic link token (SDK mode)","tags":["auth"]}},"/v1/auth/auth/magic-link/authenticate":{"post":{"description":"Exchange a magic link JWT for an AuthResult (session + tenant users). SDK mode only.","operationId":"MagicLinkController_authenticateWithMagicLinkToken[3]_v1","parameters":[],"responses":{"200":{"description":"Authentication successful, returns session and tenant users"},"401":{"description":"Invalid or expired magic link token"}},"summary":"Authenticate with magic link token (SDK mode)","tags":["auth"]}},"/auth/passkeys/request-setup-link":{"post":{"description":"Send an email with a link to register a new passkey device.","operationId":"PasskeysController_requestSetupLink[0]","parameters":[],"responses":{"200":{"description":"Setup link sent"},"401":{"description":"Invalid OAuth context or missing username"}},"summary":"Request passkey setup link","tags":["auth"]}},"/auth/auth/passkeys/request-setup-link":{"post":{"description":"Send an email with a link to register a new passkey device.","operationId":"PasskeysController_requestSetupLink[1]","parameters":[],"responses":{"200":{"description":"Setup link sent"},"401":{"description":"Invalid OAuth context or missing username"}},"summary":"Request passkey setup link","tags":["auth"]}},"/v1/auth/passkeys/request-setup-link":{"post":{"description":"Send an email with a link to register a new passkey device.","operationId":"PasskeysController_requestSetupLink[2]_v1","parameters":[],"responses":{"200":{"description":"Setup link sent"},"401":{"description":"Invalid OAuth context or missing username"}},"summary":"Request passkey setup link","tags":["auth"]}},"/v1/auth/auth/passkeys/request-setup-link":{"post":{"description":"Send an email with a link to register a new passkey device.","operationId":"PasskeysController_requestSetupLink[3]_v1","parameters":[],"responses":{"200":{"description":"Setup link sent"},"401":{"description":"Invalid OAuth context or missing username"}},"summary":"Request passkey setup link","tags":["auth"]}},"/auth/passkeys/registration-options":{"get":{"description":"Generate WebAuthn registration options for creating a new passkey.","operationId":"PasskeysController_getRegistrationOptions[0]","parameters":[{"name":"forgotPasswordToken","required":false,"in":"query","description":"Token from password reset flow","schema":{"type":"string"}},{"name":"passkeySetupToken","required":false,"in":"query","description":"Token from passkey setup email","schema":{"type":"string"}}],"responses":{"200":{"description":"WebAuthn registration options"},"401":{"description":"Invalid tokens"}},"summary":"Get passkey registration options","tags":["auth"]}},"/auth/auth/passkeys/registration-options":{"get":{"description":"Generate WebAuthn registration options for creating a new passkey.","operationId":"PasskeysController_getRegistrationOptions[1]","parameters":[{"name":"forgotPasswordToken","required":false,"in":"query","description":"Token from password reset flow","schema":{"type":"string"}},{"name":"passkeySetupToken","required":false,"in":"query","description":"Token from passkey setup email","schema":{"type":"string"}}],"responses":{"200":{"description":"WebAuthn registration options"},"401":{"description":"Invalid tokens"}},"summary":"Get passkey registration options","tags":["auth"]}},"/v1/auth/passkeys/registration-options":{"get":{"description":"Generate WebAuthn registration options for creating a new passkey.","operationId":"PasskeysController_getRegistrationOptions[2]_v1","parameters":[{"name":"forgotPasswordToken","required":false,"in":"query","description":"Token from password reset flow","schema":{"type":"string"}},{"name":"passkeySetupToken","required":false,"in":"query","description":"Token from passkey setup email","schema":{"type":"string"}}],"responses":{"200":{"description":"WebAuthn registration options"},"401":{"description":"Invalid tokens"}},"summary":"Get passkey registration options","tags":["auth"]}},"/v1/auth/auth/passkeys/registration-options":{"get":{"description":"Generate WebAuthn registration options for creating a new passkey.","operationId":"PasskeysController_getRegistrationOptions[3]_v1","parameters":[{"name":"forgotPasswordToken","required":false,"in":"query","description":"Token from password reset flow","schema":{"type":"string"}},{"name":"passkeySetupToken","required":false,"in":"query","description":"Token from passkey setup email","schema":{"type":"string"}}],"responses":{"200":{"description":"WebAuthn registration options"},"401":{"description":"Invalid tokens"}},"summary":"Get passkey registration options","tags":["auth"]}},"/auth/passkeys/verify-registration":{"post":{"description":"Verify the WebAuthn registration response and register the new device.","operationId":"PasskeysController_verifyRegistration[0]","parameters":[{"name":"forgotPasswordToken","required":true,"in":"query","schema":{"type":"string"}},{"name":"passkeySetupToken","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Registration verified"},"401":{"description":"Verification failed or invalid tokens"}},"summary":"Verify passkey registration","tags":["auth"]}},"/auth/auth/passkeys/verify-registration":{"post":{"description":"Verify the WebAuthn registration response and register the new device.","operationId":"PasskeysController_verifyRegistration[1]","parameters":[{"name":"forgotPasswordToken","required":true,"in":"query","schema":{"type":"string"}},{"name":"passkeySetupToken","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Registration verified"},"401":{"description":"Verification failed or invalid tokens"}},"summary":"Verify passkey registration","tags":["auth"]}},"/v1/auth/passkeys/verify-registration":{"post":{"description":"Verify the WebAuthn registration response and register the new device.","operationId":"PasskeysController_verifyRegistration[2]_v1","parameters":[{"name":"forgotPasswordToken","required":true,"in":"query","schema":{"type":"string"}},{"name":"passkeySetupToken","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Registration verified"},"401":{"description":"Verification failed or invalid tokens"}},"summary":"Verify passkey registration","tags":["auth"]}},"/v1/auth/auth/passkeys/verify-registration":{"post":{"description":"Verify the WebAuthn registration response and register the new device.","operationId":"PasskeysController_verifyRegistration[3]_v1","parameters":[{"name":"forgotPasswordToken","required":true,"in":"query","schema":{"type":"string"}},{"name":"passkeySetupToken","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Registration verified"},"401":{"description":"Verification failed or invalid tokens"}},"summary":"Verify passkey registration","tags":["auth"]}},"/auth/passkeys/authentication-options":{"get":{"description":"Generate WebAuthn authentication options for signing in with a passkey.","operationId":"PasskeysController_getAuthenticationOptions[0]","parameters":[],"responses":{"200":{"description":"WebAuthn authentication options"},"401":{"description":"Invalid OAuth context"}},"summary":"Get passkey authentication options","tags":["auth"]}},"/auth/auth/passkeys/authentication-options":{"get":{"description":"Generate WebAuthn authentication options for signing in with a passkey.","operationId":"PasskeysController_getAuthenticationOptions[1]","parameters":[],"responses":{"200":{"description":"WebAuthn authentication options"},"401":{"description":"Invalid OAuth context"}},"summary":"Get passkey authentication options","tags":["auth"]}},"/v1/auth/passkeys/authentication-options":{"get":{"description":"Generate WebAuthn authentication options for signing in with a passkey.","operationId":"PasskeysController_getAuthenticationOptions[2]_v1","parameters":[],"responses":{"200":{"description":"WebAuthn authentication options"},"401":{"description":"Invalid OAuth context"}},"summary":"Get passkey authentication options","tags":["auth"]}},"/v1/auth/auth/passkeys/authentication-options":{"get":{"description":"Generate WebAuthn authentication options for signing in with a passkey.","operationId":"PasskeysController_getAuthenticationOptions[3]_v1","parameters":[],"responses":{"200":{"description":"WebAuthn authentication options"},"401":{"description":"Invalid OAuth context"}},"summary":"Get passkey authentication options","tags":["auth"]}},"/auth/passkeys/verify-authentication":{"post":{"description":"Verify WebAuthn authentication response. Creates session on success.","operationId":"PasskeysController_verifyAuthentication[0]","parameters":[],"responses":{"200":{"description":"Authentication successful, session created"},"401":{"description":"Authentication failed or passkey not registered"}},"summary":"Verify passkey authentication","tags":["auth"]}},"/auth/auth/passkeys/verify-authentication":{"post":{"description":"Verify WebAuthn authentication response. Creates session on success.","operationId":"PasskeysController_verifyAuthentication[1]","parameters":[],"responses":{"200":{"description":"Authentication successful, session created"},"401":{"description":"Authentication failed or passkey not registered"}},"summary":"Verify passkey authentication","tags":["auth"]}},"/v1/auth/passkeys/verify-authentication":{"post":{"description":"Verify WebAuthn authentication response. Creates session on success.","operationId":"PasskeysController_verifyAuthentication[2]_v1","parameters":[],"responses":{"200":{"description":"Authentication successful, session created"},"401":{"description":"Authentication failed or passkey not registered"}},"summary":"Verify passkey authentication","tags":["auth"]}},"/v1/auth/auth/passkeys/verify-authentication":{"post":{"description":"Verify WebAuthn authentication response. Creates session on success.","operationId":"PasskeysController_verifyAuthentication[3]_v1","parameters":[],"responses":{"200":{"description":"Authentication successful, session created"},"401":{"description":"Authentication failed or passkey not registered"}},"summary":"Verify passkey authentication","tags":["auth"]}},"/auth/.well-known/openid-configuration":{"get":{"description":"Returns the OpenID Connect discovery document with issuer, endpoints, and supported features.","operationId":"WellKnownController_getOpenIdConfiguration[0]","parameters":[],"responses":{"200":{"description":"OpenID Connect configuration"}},"summary":"OpenID Connect discovery","tags":["auth"]}},"/v1/auth/.well-known/openid-configuration":{"get":{"description":"Returns the OpenID Connect discovery document with issuer, endpoints, and supported features.","operationId":"WellKnownController_getOpenIdConfiguration[1]_v1","parameters":[],"responses":{"200":{"description":"OpenID Connect configuration"}},"summary":"OpenID Connect discovery","tags":["auth"]}},"/auth/.well-known/jwks.json":{"get":{"description":"Returns the JWKS containing public keys used to verify access tokens and ID tokens.","operationId":"WellKnownController_getJwks[0]","parameters":[],"responses":{"200":{"description":"JWKS document"}},"summary":"JSON Web Key Set","tags":["auth"]}},"/v1/auth/.well-known/jwks.json":{"get":{"description":"Returns the JWKS containing public keys used to verify access tokens and ID tokens.","operationId":"WellKnownController_getJwks[1]_v1","parameters":[],"responses":{"200":{"description":"JWKS document"}},"summary":"JSON Web Key Set","tags":["auth"]}},"/auth/entry/email":{"get":{"description":"Create OAuth context from email entry link arguments and redirect to Cloud Views.","operationId":"EntryController_redeemEmailEntry[0]","parameters":[{"name":"appId","required":true,"in":"query","description":"Application ID","schema":{"type":"string"}},{"name":"flow","required":true,"in":"query","description":"Hosted UI flow type","schema":{"type":"string"}},{"name":"args","required":true,"in":"query","description":"Base64-encoded flow arguments","schema":{"type":"string"}},{"name":"cv_env","required":false,"in":"query","description":"Cloud Views environment","schema":{"enum":["bridge","nblocks"],"type":"string"}}],"responses":{"302":{"description":"Redirects to Cloud Views"}},"summary":"Redeem email entry link","tags":["auth"]}},"/v1/auth/entry/email":{"get":{"description":"Create OAuth context from email entry link arguments and redirect to Cloud Views.","operationId":"EntryController_redeemEmailEntry[1]_v1","parameters":[{"name":"appId","required":true,"in":"query","description":"Application ID","schema":{"type":"string"}},{"name":"flow","required":true,"in":"query","description":"Hosted UI flow type","schema":{"type":"string"}},{"name":"args","required":true,"in":"query","description":"Base64-encoded flow arguments","schema":{"type":"string"}},{"name":"cv_env","required":false,"in":"query","description":"Cloud Views environment","schema":{"enum":["bridge","nblocks"],"type":"string"}}],"responses":{"302":{"description":"Redirects to Cloud Views"}},"summary":"Redeem email entry link","tags":["auth"]}},"/auth/handover/code/{appId}":{"post":{"description":"Generate an authorization code for handover using an existing access token.","operationId":"HandoverCodeController_generateCode[0]","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Authorization code generated"},"401":{"description":"Invalid access token or mismatched app"}},"summary":"Generate auth code from access token","tags":["auth"]}},"/v1/auth/handover/code/{appId}":{"post":{"description":"Generate an authorization code for handover using an existing access token.","operationId":"HandoverCodeController_generateCode[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Authorization code generated"},"401":{"description":"Invalid access token or mismatched app"}},"summary":"Generate auth code from access token","tags":["auth"]}},"/auth/sign-in/start/{appId}":{"post":{"description":"Checks the address against the app's registered callback addresses and remembers it server-side for this browser.","operationId":"SignInReturnController_start[0]","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"204":{"description":"Recorded"},"400":{"description":"The address is not registered on the app"}},"summary":"Record the return address of a sign-in","tags":["auth"]}},"/v1/auth/sign-in/start/{appId}":{"post":{"description":"Checks the address against the app's registered callback addresses and remembers it server-side for this browser.","operationId":"SignInReturnController_start[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"204":{"description":"Recorded"},"400":{"description":"The address is not registered on the app"}},"summary":"Record the return address of a sign-in","tags":["auth"]}},"/auth/sign-in/code/{appId}":{"post":{"description":"Converts an access token into a login code for the address the server recorded for this sign-in, or the app's default callback.","operationId":"SignInReturnController_code[0]","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"{ code, redirectUri }"},"401":{"description":"Invalid access token or mismatched app"}},"summary":"Finish a sign-in","tags":["auth"]}},"/v1/auth/sign-in/code/{appId}":{"post":{"description":"Converts an access token into a login code for the address the server recorded for this sign-in, or the app's default callback.","operationId":"SignInReturnController_code[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"{ code, redirectUri }"},"401":{"description":"Invalid access token or mismatched app"}},"summary":"Finish a sign-in","tags":["auth"]}},"/auth/url/login/{appId}":{"get":{"description":"Redirect directly to the hosted login page (one hop). Federated flows still route via /auth/authorize.","operationId":"UrlController_login[0]","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to the hosted login page"}},"summary":"Login URL","tags":["auth"]}},"/v1/auth/url/login/{appId}":{"get":{"description":"Redirect directly to the hosted login page (one hop). Federated flows still route via /auth/authorize.","operationId":"UrlController_login[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to the hosted login page"}},"summary":"Login URL","tags":["auth"]}},"/auth/url/logout/{appId}":{"get":{"description":"Clear auth cookies and redirect to login.","operationId":"UrlController_logout[0]","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"cv_env","required":false,"in":"query","description":"Cloud Views environment","schema":{"type":"string"}},{"name":"redirect_uri","required":false,"in":"query","description":"Redirect URI after re-login","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to login URL"}},"summary":"Logout URL","tags":["auth"]}},"/v1/auth/url/logout/{appId}":{"get":{"description":"Clear auth cookies and redirect to login.","operationId":"UrlController_logout[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}},{"name":"cv_env","required":false,"in":"query","description":"Cloud Views environment","schema":{"type":"string"}},{"name":"redirect_uri","required":false,"in":"query","description":"Redirect URI after re-login","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to login URL"}},"summary":"Logout URL","tags":["auth"]}},"/auth/url/signup/{appId}":{"get":{"description":"Redirect directly to the hosted signup page (one hop). Federated flows still route via /auth/authorize.","operationId":"UrlController_signup[0]","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to the hosted signup page"}},"summary":"Signup URL","tags":["auth"]}},"/v1/auth/url/signup/{appId}":{"get":{"description":"Redirect directly to the hosted signup page (one hop). Federated flows still route via /auth/authorize.","operationId":"UrlController_signup[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","description":"Application ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to the hosted signup page"}},"summary":"Signup URL","tags":["auth"]}},"/auth/authorize":{"get":{"description":"Initiates the OAuth 2.0 authorization code flow. Redirects to Cloud Views login UI or directly to a federation provider.","operationId":"AuthorizeController_authorize[0]","parameters":[{"name":"cv_env","required":false,"in":"query","description":"Cloud Views environment","schema":{"enum":["bridge","nblocks"],"type":"string"}},{"name":"signup_recurrence_interval","required":false,"in":"query","description":"Recurrence interval for signup plan","schema":{}},{"name":"signup_currency","required":false,"in":"query","description":"Currency for signup plan","schema":{}},{"name":"signup_plan","required":false,"in":"query","description":"Pre-select a plan during signup","schema":{}},{"name":"signup","required":false,"in":"query","description":"Start signup flow instead of login","schema":{"type":"boolean"}},{"name":"federation_connection","required":false,"in":"query","description":"Specific federation connection ID","schema":{}},{"name":"force_federation","required":false,"in":"query","description":"Force a specific federation provider","schema":{}},{"name":"state","required":false,"in":"query","description":"Opaque state value passed back to redirect_uri","schema":{}},{"name":"scope","required":true,"in":"query","description":"OAuth scopes (space-separated)","schema":{}},{"name":"response_type","required":true,"in":"query","description":"OAuth response type","schema":{"enum":["code","id_token"],"type":"string"}},{"name":"redirect_uri","required":true,"in":"query","description":"Redirect URI after authorization","schema":{}},{"name":"client_id","required":true,"in":"query","description":"Application ID (OAuth client_id)","schema":{}}],"responses":{"302":{"description":"Redirects to login UI or federation provider"},"400":{"description":"Invalid response type or missing parameters"},"401":{"description":"Invalid client_id (app not found)"}},"summary":"OAuth 2.0 authorization","tags":["auth"]}},"/v1/auth/authorize":{"get":{"description":"Initiates the OAuth 2.0 authorization code flow. Redirects to Cloud Views login UI or directly to a federation provider.","operationId":"AuthorizeController_authorize[1]_v1","parameters":[{"name":"cv_env","required":false,"in":"query","description":"Cloud Views environment","schema":{"enum":["bridge","nblocks"],"type":"string"}},{"name":"signup_recurrence_interval","required":false,"in":"query","description":"Recurrence interval for signup plan","schema":{}},{"name":"signup_currency","required":false,"in":"query","description":"Currency for signup plan","schema":{}},{"name":"signup_plan","required":false,"in":"query","description":"Pre-select a plan during signup","schema":{}},{"name":"signup","required":false,"in":"query","description":"Start signup flow instead of login","schema":{"type":"boolean"}},{"name":"federation_connection","required":false,"in":"query","description":"Specific federation connection ID","schema":{}},{"name":"force_federation","required":false,"in":"query","description":"Force a specific federation provider","schema":{}},{"name":"state","required":false,"in":"query","description":"Opaque state value passed back to redirect_uri","schema":{}},{"name":"scope","required":true,"in":"query","description":"OAuth scopes (space-separated)","schema":{}},{"name":"response_type","required":true,"in":"query","description":"OAuth response type","schema":{"enum":["code","id_token"],"type":"string"}},{"name":"redirect_uri","required":true,"in":"query","description":"Redirect URI after authorization","schema":{}},{"name":"client_id","required":true,"in":"query","description":"Application ID (OAuth client_id)","schema":{}}],"responses":{"302":{"description":"Redirects to login UI or federation provider"},"400":{"description":"Invalid response type or missing parameters"},"401":{"description":"Invalid client_id (app not found)"}},"summary":"OAuth 2.0 authorization","tags":["auth"]}},"/auth/ui":{"get":{"description":"Entrypoint for Cloud Views login flow. Redirects based on OAuth context and session state.","operationId":"AuthUiController_uiEntrypoint[0]","parameters":[],"responses":{"302":{"description":"Redirects to Cloud Views login page"},"401":{"description":"Invalid OAuth context"}},"summary":"Auth UI entrypoint","tags":["auth"]}},"/auth/auth/ui":{"get":{"description":"Entrypoint for Cloud Views login flow. Redirects based on OAuth context and session state.","operationId":"AuthUiController_uiEntrypoint[1]","parameters":[],"responses":{"302":{"description":"Redirects to Cloud Views login page"},"401":{"description":"Invalid OAuth context"}},"summary":"Auth UI entrypoint","tags":["auth"]}},"/v1/auth/ui":{"get":{"description":"Entrypoint for Cloud Views login flow. Redirects based on OAuth context and session state.","operationId":"AuthUiController_uiEntrypoint[2]_v1","parameters":[],"responses":{"302":{"description":"Redirects to Cloud Views login page"},"401":{"description":"Invalid OAuth context"}},"summary":"Auth UI entrypoint","tags":["auth"]}},"/v1/auth/auth/ui":{"get":{"description":"Entrypoint for Cloud Views login flow. Redirects based on OAuth context and session state.","operationId":"AuthUiController_uiEntrypoint[3]_v1","parameters":[],"responses":{"302":{"description":"Redirects to Cloud Views login page"},"401":{"description":"Invalid OAuth context"}},"summary":"Auth UI entrypoint","tags":["auth"]}},"/auth/federated/google/login":{"get":{"description":"Initiate Google OAuth login flow.","operationId":"GoogleFederationController_login[0]","parameters":[],"responses":{"302":{"description":"Redirects to Google OAuth consent screen"}},"summary":"Google login","tags":["auth-federation"]}},"/v1/auth/federated/google/login":{"get":{"description":"Initiate Google OAuth login flow.","operationId":"GoogleFederationController_login[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to Google OAuth consent screen"}},"summary":"Google login","tags":["auth-federation"]}},"/auth/federated/google/signup":{"get":{"description":"Initiate Google OAuth signup flow.","operationId":"GoogleFederationController_signup[0]","parameters":[],"responses":{"302":{"description":"Redirects to Google OAuth consent screen"}},"summary":"Google signup","tags":["auth-federation"]}},"/v1/auth/federated/google/signup":{"get":{"description":"Initiate Google OAuth signup flow.","operationId":"GoogleFederationController_signup[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to Google OAuth consent screen"}},"summary":"Google signup","tags":["auth-federation"]}},"/auth/federated/google/return":{"get":{"description":"Handle return from Google OAuth flow. Authenticates or signs up the user.","operationId":"GoogleFederationController_handleReturn[0]","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Google OAuth callback","tags":["auth-federation"]}},"/v1/auth/federated/google/return":{"get":{"description":"Handle return from Google OAuth flow. Authenticates or signs up the user.","operationId":"GoogleFederationController_handleReturn[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Google OAuth callback","tags":["auth-federation"]}},"/auth/federated/google/error":{"get":{"description":"Handle errors from Google OAuth flow.","operationId":"GoogleFederationController_handleError[0]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Google error handler","tags":["auth-federation"]}},"/v1/auth/federated/google/error":{"get":{"description":"Handle errors from Google OAuth flow.","operationId":"GoogleFederationController_handleError[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Google error handler","tags":["auth-federation"]}},"/auth/federated/ms-azure-ad/login":{"get":{"description":"Initiate Azure AD OAuth login flow.","operationId":"AzureFederationController_login[0]","parameters":[],"responses":{"302":{"description":"Redirects to Azure AD OAuth consent screen"}},"summary":"Azure AD login","tags":["auth-federation"]}},"/v1/auth/federated/ms-azure-ad/login":{"get":{"description":"Initiate Azure AD OAuth login flow.","operationId":"AzureFederationController_login[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to Azure AD OAuth consent screen"}},"summary":"Azure AD login","tags":["auth-federation"]}},"/auth/federated/ms-azure-ad/signup":{"get":{"description":"Initiate Azure AD OAuth signup flow.","operationId":"AzureFederationController_signup[0]","parameters":[],"responses":{"302":{"description":"Redirects to Azure AD OAuth consent screen"}},"summary":"Azure AD signup","tags":["auth-federation"]}},"/v1/auth/federated/ms-azure-ad/signup":{"get":{"description":"Initiate Azure AD OAuth signup flow.","operationId":"AzureFederationController_signup[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to Azure AD OAuth consent screen"}},"summary":"Azure AD signup","tags":["auth-federation"]}},"/auth/federated/ms-azure-ad/return":{"get":{"description":"Handle return from Azure AD OAuth flow. Authenticates or signs up the user.","operationId":"AzureFederationController_handleReturn[0]","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Azure AD OAuth callback","tags":["auth-federation"]}},"/v1/auth/federated/ms-azure-ad/return":{"get":{"description":"Handle return from Azure AD OAuth flow. Authenticates or signs up the user.","operationId":"AzureFederationController_handleReturn[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Azure AD OAuth callback","tags":["auth-federation"]}},"/auth/federated/ms-azure-ad/error":{"get":{"description":"Handle errors from Azure AD OAuth flow.","operationId":"AzureFederationController_handleError[0]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Azure AD error handler","tags":["auth-federation"]}},"/v1/auth/federated/ms-azure-ad/error":{"get":{"description":"Handle errors from Azure AD OAuth flow.","operationId":"AzureFederationController_handleError[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Azure AD error handler","tags":["auth-federation"]}},"/auth/federated/linkedin/login":{"get":{"description":"Initiate LinkedIn OAuth login flow.","operationId":"LinkedInFederationController_login[0]","parameters":[],"responses":{"302":{"description":"Redirects to LinkedIn OAuth consent screen"}},"summary":"LinkedIn login","tags":["auth-federation"]}},"/v1/auth/federated/linkedin/login":{"get":{"description":"Initiate LinkedIn OAuth login flow.","operationId":"LinkedInFederationController_login[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to LinkedIn OAuth consent screen"}},"summary":"LinkedIn login","tags":["auth-federation"]}},"/auth/federated/linkedin/signup":{"get":{"description":"Initiate LinkedIn OAuth signup flow.","operationId":"LinkedInFederationController_signup[0]","parameters":[],"responses":{"302":{"description":"Redirects to LinkedIn OAuth consent screen"}},"summary":"LinkedIn signup","tags":["auth-federation"]}},"/v1/auth/federated/linkedin/signup":{"get":{"description":"Initiate LinkedIn OAuth signup flow.","operationId":"LinkedInFederationController_signup[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to LinkedIn OAuth consent screen"}},"summary":"LinkedIn signup","tags":["auth-federation"]}},"/auth/federated/linkedin/return":{"get":{"description":"Handle return from LinkedIn OAuth flow. Authenticates or signs up the user.","operationId":"LinkedInFederationController_handleReturn[0]","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"LinkedIn OAuth callback","tags":["auth-federation"]}},"/v1/auth/federated/linkedin/return":{"get":{"description":"Handle return from LinkedIn OAuth flow. Authenticates or signs up the user.","operationId":"LinkedInFederationController_handleReturn[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"LinkedIn OAuth callback","tags":["auth-federation"]}},"/auth/federated/linkedin/error":{"get":{"description":"Handle errors from LinkedIn OAuth flow.","operationId":"LinkedInFederationController_handleError[0]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"LinkedIn error handler","tags":["auth-federation"]}},"/v1/auth/federated/linkedin/error":{"get":{"description":"Handle errors from LinkedIn OAuth flow.","operationId":"LinkedInFederationController_handleError[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"LinkedIn error handler","tags":["auth-federation"]}},"/auth/federated/facebook/login":{"get":{"description":"Initiate Facebook OAuth login flow.","operationId":"FacebookFederationController_login[0]","parameters":[],"responses":{"302":{"description":"Redirects to Facebook OAuth consent screen"}},"summary":"Facebook login","tags":["auth-federation"]}},"/v1/auth/federated/facebook/login":{"get":{"description":"Initiate Facebook OAuth login flow.","operationId":"FacebookFederationController_login[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to Facebook OAuth consent screen"}},"summary":"Facebook login","tags":["auth-federation"]}},"/auth/federated/facebook/signup":{"get":{"description":"Initiate Facebook OAuth signup flow.","operationId":"FacebookFederationController_signup[0]","parameters":[],"responses":{"302":{"description":"Redirects to Facebook OAuth consent screen"}},"summary":"Facebook signup","tags":["auth-federation"]}},"/v1/auth/federated/facebook/signup":{"get":{"description":"Initiate Facebook OAuth signup flow.","operationId":"FacebookFederationController_signup[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to Facebook OAuth consent screen"}},"summary":"Facebook signup","tags":["auth-federation"]}},"/auth/federated/facebook/return":{"get":{"description":"Handle return from Facebook OAuth flow. Authenticates or signs up the user.","operationId":"FacebookFederationController_handleReturn[0]","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Facebook OAuth callback","tags":["auth-federation"]}},"/v1/auth/federated/facebook/return":{"get":{"description":"Handle return from Facebook OAuth flow. Authenticates or signs up the user.","operationId":"FacebookFederationController_handleReturn[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"Facebook OAuth callback","tags":["auth-federation"]}},"/auth/federated/facebook/tokenProxy":{"post":{"description":"Proxy token exchange request for Facebook OAuth (works around Facebook OIDC limitations).","operationId":"FacebookFederationController_tokenProxy[0]","parameters":[],"responses":{"200":{"description":"Returns token response from Facebook"}},"summary":"Facebook token proxy","tags":["auth-federation"]}},"/v1/auth/federated/facebook/tokenProxy":{"post":{"description":"Proxy token exchange request for Facebook OAuth (works around Facebook OIDC limitations).","operationId":"FacebookFederationController_tokenProxy[1]_v1","parameters":[],"responses":{"200":{"description":"Returns token response from Facebook"}},"summary":"Facebook token proxy","tags":["auth-federation"]}},"/auth/federated/facebook/error":{"get":{"description":"Handle errors from Facebook OAuth flow.","operationId":"FacebookFederationController_handleError[0]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Facebook error handler","tags":["auth-federation"]}},"/v1/auth/federated/facebook/error":{"get":{"description":"Handle errors from Facebook OAuth flow.","operationId":"FacebookFederationController_handleError[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"Facebook error handler","tags":["auth-federation"]}},"/auth/federated/github/login":{"get":{"description":"Initiate GitHub OAuth login flow.","operationId":"GitHubFederationController_login[0]","parameters":[],"responses":{"302":{"description":"Redirects to GitHub OAuth consent screen"}},"summary":"GitHub login","tags":["auth-federation"]}},"/v1/auth/federated/github/login":{"get":{"description":"Initiate GitHub OAuth login flow.","operationId":"GitHubFederationController_login[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to GitHub OAuth consent screen"}},"summary":"GitHub login","tags":["auth-federation"]}},"/auth/federated/github/signup":{"get":{"description":"Initiate GitHub OAuth signup flow.","operationId":"GitHubFederationController_signup[0]","parameters":[],"responses":{"302":{"description":"Redirects to GitHub OAuth consent screen"}},"summary":"GitHub signup","tags":["auth-federation"]}},"/v1/auth/federated/github/signup":{"get":{"description":"Initiate GitHub OAuth signup flow.","operationId":"GitHubFederationController_signup[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to GitHub OAuth consent screen"}},"summary":"GitHub signup","tags":["auth-federation"]}},"/auth/federated/github/return":{"get":{"description":"Handle return from GitHub OAuth flow. Authenticates or signs up the user.","operationId":"GitHubFederationController_handleReturn[0]","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"GitHub OAuth callback","tags":["auth-federation"]}},"/v1/auth/federated/github/return":{"get":{"description":"Handle return from GitHub OAuth flow. Authenticates or signs up the user.","operationId":"GitHubFederationController_handleReturn[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"GitHub OAuth callback","tags":["auth-federation"]}},"/auth/federated/github/error":{"get":{"description":"Handle errors from GitHub OAuth flow.","operationId":"GitHubFederationController_handleError[0]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"GitHub error handler","tags":["auth-federation"]}},"/v1/auth/federated/github/error":{"get":{"description":"Handle errors from GitHub OAuth flow.","operationId":"GitHubFederationController_handleError[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"GitHub error handler","tags":["auth-federation"]}},"/auth/federated/saml/login/{connectionId}":{"get":{"description":"Initiate SAML OAuth login flow.","operationId":"SamlFederationController_login[0]","parameters":[{"name":"connectionId","required":true,"in":"path","description":"Federation connection ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to SAML OAuth consent screen"}},"summary":"SAML login","tags":["auth-federation"]}},"/v1/auth/federated/saml/login/{connectionId}":{"get":{"description":"Initiate SAML OAuth login flow.","operationId":"SamlFederationController_login[1]_v1","parameters":[{"name":"connectionId","required":true,"in":"path","description":"Federation connection ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to SAML OAuth consent screen"}},"summary":"SAML login","tags":["auth-federation"]}},"/auth/federated/saml/return/{connectionId}":{"post":{"description":"Handle return from SAML OAuth flow. Authenticates or signs up the user.","operationId":"SamlFederationController_handleReturn[0]","parameters":[{"name":"connectionId","required":true,"in":"path","description":"Federation connection ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"SAML OAuth callback","tags":["auth-federation"]}},"/v1/auth/federated/saml/return/{connectionId}":{"post":{"description":"Handle return from SAML OAuth flow. Authenticates or signs up the user.","operationId":"SamlFederationController_handleReturn[1]_v1","parameters":[{"name":"connectionId","required":true,"in":"path","description":"Federation connection ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"SAML OAuth callback","tags":["auth-federation"]}},"/auth/federated/saml/error":{"get":{"description":"Handle errors from SAML OAuth flow.","operationId":"SamlFederationController_handleError[0]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"SAML error handler","tags":["auth-federation"]}},"/v1/auth/federated/saml/error":{"get":{"description":"Handle errors from SAML OAuth flow.","operationId":"SamlFederationController_handleError[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"SAML error handler","tags":["auth-federation"]}},"/auth/federated/oidc/login/{connectionId}":{"get":{"description":"Initiate OIDC OAuth login flow.","operationId":"OidcFederationController_login[0]","parameters":[{"name":"connectionId","required":true,"in":"path","description":"Federation connection ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to OIDC OAuth consent screen"}},"summary":"OIDC login","tags":["auth-federation"]}},"/v1/auth/federated/oidc/login/{connectionId}":{"get":{"description":"Initiate OIDC OAuth login flow.","operationId":"OidcFederationController_login[1]_v1","parameters":[{"name":"connectionId","required":true,"in":"path","description":"Federation connection ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to OIDC OAuth consent screen"}},"summary":"OIDC login","tags":["auth-federation"]}},"/auth/federated/oidc/return/{connectionId}":{"post":{"description":"Handle return from OIDC OAuth flow. Authenticates or signs up the user.","operationId":"OidcFederationController_handleReturn[0]","parameters":[{"name":"connectionId","required":true,"in":"path","description":"Federation connection ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"OIDC OAuth callback","tags":["auth-federation"]}},"/v1/auth/federated/oidc/return/{connectionId}":{"post":{"description":"Handle return from OIDC OAuth flow. Authenticates or signs up the user.","operationId":"OidcFederationController_handleReturn[1]_v1","parameters":[{"name":"connectionId","required":true,"in":"path","description":"Federation connection ID","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirects to next auth step or error page"}},"summary":"OIDC OAuth callback","tags":["auth-federation"]}},"/auth/federated/oidc/error":{"get":{"description":"Handle errors from OIDC OAuth flow.","operationId":"OidcFederationController_handleError[0]","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"OIDC error handler","tags":["auth-federation"]}},"/v1/auth/federated/oidc/error":{"get":{"description":"Handle errors from OIDC OAuth flow.","operationId":"OidcFederationController_handleError[1]_v1","parameters":[],"responses":{"302":{"description":"Redirects to error callback"}},"summary":"OIDC error handler","tags":["auth-federation"]}},"/auth/signup":{"post":{"description":"Create a new tenant with self-signup (SDK mode).","operationId":"SdkSignupController_signup[0]","parameters":[],"responses":{"200":{"description":"Signup successful — verification email sent"},"403":{"description":"Signup disabled or origin not allowed"}},"summary":"SDK signup","tags":["auth"]}},"/auth/auth/signup":{"post":{"description":"Create a new tenant with self-signup (SDK mode).","operationId":"SdkSignupController_signup[1]","parameters":[],"responses":{"200":{"description":"Signup successful — verification email sent"},"403":{"description":"Signup disabled or origin not allowed"}},"summary":"SDK signup","tags":["auth"]}},"/v1/auth/signup":{"post":{"description":"Create a new tenant with self-signup (SDK mode).","operationId":"SdkSignupController_signup[2]_v1","parameters":[],"responses":{"200":{"description":"Signup successful — verification email sent"},"403":{"description":"Signup disabled or origin not allowed"}},"summary":"SDK signup","tags":["auth"]}},"/v1/auth/auth/signup":{"post":{"description":"Create a new tenant with self-signup (SDK mode).","operationId":"SdkSignupController_signup[3]_v1","parameters":[],"responses":{"200":{"description":"Signup successful — verification email sent"},"403":{"description":"Signup disabled or origin not allowed"}},"summary":"SDK signup","tags":["auth"]}},"/auth/password/token/{token}":{"get":{"description":"Validate a password reset token and return the associated appId.","operationId":"SdkPasswordController_validatePasswordToken[0]","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Token valid"},"403":{"description":"Origin not allowed for this application"},"404":{"description":"Token not found or expired"}},"summary":"Validate password token","tags":["auth"]}},"/auth/auth/password/token/{token}":{"get":{"description":"Validate a password reset token and return the associated appId.","operationId":"SdkPasswordController_validatePasswordToken[1]","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Token valid"},"403":{"description":"Origin not allowed for this application"},"404":{"description":"Token not found or expired"}},"summary":"Validate password token","tags":["auth"]}},"/v1/auth/password/token/{token}":{"get":{"description":"Validate a password reset token and return the associated appId.","operationId":"SdkPasswordController_validatePasswordToken[2]_v1","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Token valid"},"403":{"description":"Origin not allowed for this application"},"404":{"description":"Token not found or expired"}},"summary":"Validate password token","tags":["auth"]}},"/v1/auth/auth/password/token/{token}":{"get":{"description":"Validate a password reset token and return the associated appId.","operationId":"SdkPasswordController_validatePasswordToken[3]_v1","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Token valid"},"403":{"description":"Origin not allowed for this application"},"404":{"description":"Token not found or expired"}},"summary":"Validate password token","tags":["auth"]}},"/auth/password":{"post":{"description":"Send a password reset link email (SDK mode).","operationId":"SdkPasswordController_forgotPassword[0]","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Reset email sent"}},"summary":"Forgot password","tags":["auth"]},"put":{"description":"Set a new password using the reset token (SDK mode).","operationId":"SdkPasswordController_updatePassword[0]","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Password updated"}},"summary":"Update password","tags":["auth"]}},"/auth/auth/password":{"post":{"description":"Send a password reset link email (SDK mode).","operationId":"SdkPasswordController_forgotPassword[1]","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Reset email sent"}},"summary":"Forgot password","tags":["auth"]},"put":{"description":"Set a new password using the reset token (SDK mode).","operationId":"SdkPasswordController_updatePassword[1]","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Password updated"}},"summary":"Update password","tags":["auth"]}},"/v1/auth/password":{"post":{"description":"Send a password reset link email (SDK mode).","operationId":"SdkPasswordController_forgotPassword[2]_v1","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Reset email sent"}},"summary":"Forgot password","tags":["auth"]},"put":{"description":"Set a new password using the reset token (SDK mode).","operationId":"SdkPasswordController_updatePassword[2]_v1","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Password updated"}},"summary":"Update password","tags":["auth"]}},"/v1/auth/auth/password":{"post":{"description":"Send a password reset link email (SDK mode).","operationId":"SdkPasswordController_forgotPassword[3]_v1","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}},{"name":"origin","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Reset email sent"}},"summary":"Forgot password","tags":["auth"]},"put":{"description":"Set a new password using the reset token (SDK mode).","operationId":"SdkPasswordController_updatePassword[3]_v1","parameters":[{"name":"x-app-id","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Password updated"}},"summary":"Update password","tags":["auth"]}},"/auth/test/playwright/magic-link":{"get":{"operationId":"AuthTestController_getMagicLink[0]","parameters":[{"name":"username","required":true,"in":"query","schema":{"type":"string"}},{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"originUrl","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Generates a magic link URL for a user without sending an email.\nMirrors the URL-building logic in requestMagicLink() so the returned link\nis identical to what would appear in the email.\n\nGET /auth/test/playwright/magic-link?username=...&appId=...&originUrl=...\nHeaders: x-playwright-api-key: <key>","tags":["auth"]}},"/v1/auth/test/playwright/magic-link":{"get":{"operationId":"AuthTestController_getMagicLink[1]_v1","parameters":[{"name":"username","required":true,"in":"query","schema":{"type":"string"}},{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"originUrl","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Generates a magic link URL for a user without sending an email.\nMirrors the URL-building logic in requestMagicLink() so the returned link\nis identical to what would appear in the email.\n\nGET /auth/test/playwright/magic-link?username=...&appId=...&originUrl=...\nHeaders: x-playwright-api-key: <key>","tags":["auth"]}},"/auth/test/playwright/mfa-code":{"get":{"operationId":"AuthTestController_getMfaCode[0]","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"username","required":true,"in":"query","schema":{"type":"string"}},{"name":"phoneNumber","required":true,"in":"query","schema":{"type":"string"}},{"name":"mfaState","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Generates a valid MFA code + LOGIN_SESSION JWT for Playwright tests.\nThis allows E2E tests to exercise MFA setup/challenge flows without SMS.\n\nGET /auth/test/playwright/mfa-code?appId=...&username=...&phoneNumber=...&mfaState=SETUP|REQUIRED\nHeaders: x-playwright-api-key: <key>","tags":["auth"]}},"/v1/auth/test/playwright/mfa-code":{"get":{"operationId":"AuthTestController_getMfaCode[1]_v1","parameters":[{"name":"appId","required":true,"in":"query","schema":{"type":"string"}},{"name":"username","required":true,"in":"query","schema":{"type":"string"}},{"name":"phoneNumber","required":true,"in":"query","schema":{"type":"string"}},{"name":"mfaState","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Generates a valid MFA code + LOGIN_SESSION JWT for Playwright tests.\nThis allows E2E tests to exercise MFA setup/challenge flows without SMS.\n\nGET /auth/test/playwright/mfa-code?appId=...&username=...&phoneNumber=...&mfaState=SETUP|REQUIRED\nHeaders: x-playwright-api-key: <key>","tags":["auth"]}},"/auth/cli/authorize":{"post":{"description":"Creates a 60-second single-use authorization code bound to a PKCE challenge. Authenticated via the user session (Authorization: Bearer).","operationId":"CliAuthController_authorize[0]","parameters":[],"responses":{"200":{"description":"Authorization code created"},"400":{"description":"Validation failure"},"401":{"description":"Missing/invalid user JWT"},"403":{"description":"app_id not owned by user"}},"summary":"Mint a CLI authorization code","tags":["auth"]}},"/v1/auth/cli/authorize":{"post":{"description":"Creates a 60-second single-use authorization code bound to a PKCE challenge. Authenticated via the user session (Authorization: Bearer).","operationId":"CliAuthController_authorize[1]_v1","parameters":[],"responses":{"200":{"description":"Authorization code created"},"400":{"description":"Validation failure"},"401":{"description":"Missing/invalid user JWT"},"403":{"description":"app_id not owned by user"}},"summary":"Mint a CLI authorization code","tags":["auth"]}},"/auth/cli/token":{"post":{"description":"PKCE-bound exchange. SHA256(code_verifier) must equal the challenge committed at /authorize.","operationId":"CliAuthController_token[0]","parameters":[],"responses":{"200":{"description":"CliToken issued"},"400":{"description":"invalid_request | invalid_grant | expired_grant"}},"summary":"Exchange CLI authorization code for token","tags":["auth"]}},"/v1/auth/cli/token":{"post":{"description":"PKCE-bound exchange. SHA256(code_verifier) must equal the challenge committed at /authorize.","operationId":"CliAuthController_token[1]_v1","parameters":[],"responses":{"200":{"description":"CliToken issued"},"400":{"description":"invalid_request | invalid_grant | expired_grant"}},"summary":"Exchange CLI authorization code for token","tags":["auth"]}},"/auth/cli/revoke":{"post":{"description":"Idempotent. Auth via user JWT (must own the token) OR the CliToken being revoked.","operationId":"CliAuthController_revoke[0]","parameters":[],"responses":{"200":{"description":"Token revoked (or already revoked)"},"401":{"description":"No valid auth credential"}},"summary":"Revoke a CLI token","tags":["auth"]}},"/v1/auth/cli/revoke":{"post":{"description":"Idempotent. Auth via user JWT (must own the token) OR the CliToken being revoked.","operationId":"CliAuthController_revoke[1]_v1","parameters":[],"responses":{"200":{"description":"Token revoked (or already revoked)"},"401":{"description":"No valid auth credential"}},"summary":"Revoke a CLI token","tags":["auth"]}},"/.well-known/oauth-protected-resource/mcp":{"get":{"description":"RFC 9728 document MCP clients use to locate the authorization server protecting the /mcp resource.","operationId":"McpWellKnownController_getProtectedResourceMetadata","parameters":[],"responses":{"200":{"description":"Protected-resource metadata"}},"summary":"OAuth protected-resource metadata for /mcp","tags":["mcp"]}},"/.well-known/oauth-authorization-server":{"get":{"description":"RFC 8414 metadata: authorization-code + PKCE (S256) and rotating refresh tokens, public clients (token_endpoint_auth_methods_supported: none), Client ID Metadata Documents, and an RFC 7591 registration_endpoint.","operationId":"McpWellKnownController_getAuthorizationServerMetadata","parameters":[],"responses":{"200":{"description":"Authorization-server metadata"}},"summary":"OAuth authorization-server metadata (MCP facade)","tags":["mcp"]}},"/mcp/oauth/register":{"post":{"description":"Open (anonymous) registration for MCP clients that are not in the static registry — local CLI/native hosts that bind a loopback callback. Issues a PUBLIC client only: no client_secret is ever created, token_endpoint_auth_method is always \"none\", and scope is always \"management\". Rejects http redirect_uris on non-loopback hosts, wildcards, fragments and userinfo.","operationId":"McpOauthController_register[0]","parameters":[],"responses":{"201":{"description":"Client registered"},"400":{"description":"invalid_redirect_uri | invalid_client_metadata"},"429":{"description":"temporarily_unavailable — per-IP registration rate limit"},"503":{"description":"temporarily_unavailable — registration store at capacity"}},"summary":"MCP OAuth dynamic client registration endpoint (RFC 7591)","tags":["mcp"]}},"/v1/mcp/oauth/register":{"post":{"description":"Open (anonymous) registration for MCP clients that are not in the static registry — local CLI/native hosts that bind a loopback callback. Issues a PUBLIC client only: no client_secret is ever created, token_endpoint_auth_method is always \"none\", and scope is always \"management\". Rejects http redirect_uris on non-loopback hosts, wildcards, fragments and userinfo.","operationId":"McpOauthController_register[1]_v1","parameters":[],"responses":{"201":{"description":"Client registered"},"400":{"description":"invalid_redirect_uri | invalid_client_metadata"},"429":{"description":"temporarily_unavailable — per-IP registration rate limit"},"503":{"description":"temporarily_unavailable — registration store at capacity"}},"summary":"MCP OAuth dynamic client registration endpoint (RFC 7591)","tags":["mcp"]}},"/mcp/oauth/clients":{"get":{"description":"Public, pre-registered client ids (e.g. claude, cursor) that an MCP client can be configured with instead of registering dynamically.","operationId":"McpOauthController_listClients[0]","parameters":[],"responses":{"200":{"description":"Pre-registered clients"}},"summary":"List the pre-registered MCP OAuth client ids","tags":["mcp"]}},"/v1/mcp/oauth/clients":{"get":{"description":"Public, pre-registered client ids (e.g. claude, cursor) that an MCP client can be configured with instead of registering dynamically.","operationId":"McpOauthController_listClients[1]_v1","parameters":[],"responses":{"200":{"description":"Pre-registered clients"}},"summary":"List the pre-registered MCP OAuth client ids","tags":["mcp"]}},"/mcp/oauth/authorize":{"get":{"description":"RFC 6749 authorization-code + PKCE (S256) entry point for registered MCP clients. Redirects to the cloud-views consent page on success. Unknown client_id or unregistered redirect_uri answer 400 JSON without redirecting.","operationId":"McpOauthController_authorize[0]","parameters":[],"responses":{"302":{"description":"Redirect to consent page (or error redirect to the validated client callback)"},"400":{"description":"Unknown client_id / unregistered redirect_uri"}},"summary":"MCP OAuth authorization endpoint","tags":["mcp"]}},"/v1/mcp/oauth/authorize":{"get":{"description":"RFC 6749 authorization-code + PKCE (S256) entry point for registered MCP clients. Redirects to the cloud-views consent page on success. Unknown client_id or unregistered redirect_uri answer 400 JSON without redirecting.","operationId":"McpOauthController_authorize[1]_v1","parameters":[],"responses":{"302":{"description":"Redirect to consent page (or error redirect to the validated client callback)"},"400":{"description":"Unknown client_id / unregistered redirect_uri"}},"summary":"MCP OAuth authorization endpoint","tags":["mcp"]}},"/mcp/oauth/token":{"post":{"description":"Exchanges an authorization code + PKCE verifier (grant_type=authorization_code), or a refresh token (grant_type=refresh_token, rotated on every use), for a Bearer ApiToken JWT (source: bridge-mcp) plus a refresh token. Accepts application/x-www-form-urlencoded (what MCP clients send) and application/json. Public clients — the code or refresh token is the auth.","operationId":"McpOauthController_token[0]","parameters":[],"responses":{"200":{"description":"Token issued"},"400":{"description":"invalid_request | invalid_grant | unsupported_grant_type"},"401":{"description":"invalid_client"}},"summary":"MCP OAuth token endpoint","tags":["mcp"]}},"/v1/mcp/oauth/token":{"post":{"description":"Exchanges an authorization code + PKCE verifier (grant_type=authorization_code), or a refresh token (grant_type=refresh_token, rotated on every use), for a Bearer ApiToken JWT (source: bridge-mcp) plus a refresh token. Accepts application/x-www-form-urlencoded (what MCP clients send) and application/json. Public clients — the code or refresh token is the auth.","operationId":"McpOauthController_token[1]_v1","parameters":[],"responses":{"200":{"description":"Token issued"},"400":{"description":"invalid_request | invalid_grant | unsupported_grant_type"},"401":{"description":"invalid_client"}},"summary":"MCP OAuth token endpoint","tags":["mcp"]}},"/auth/mcp/authorize":{"post":{"description":"Creates a 60-second single-use authorization code bound to a registered MCP client, its redirect_uri, and a PKCE S256 challenge. Authenticated via the user session (Authorization: Bearer).","operationId":"McpConsentController_authorize[0]","parameters":[],"responses":{"200":{"description":"Authorization code created"},"400":{"description":"Validation failure (unknown client, bad redirect_uri, bad challenge)"},"401":{"description":"Missing/invalid user JWT"},"403":{"description":"appId not owned by user"}},"summary":"Mint an MCP authorization code","tags":["auth"]}},"/v1/auth/mcp/authorize":{"post":{"description":"Creates a 60-second single-use authorization code bound to a registered MCP client, its redirect_uri, and a PKCE S256 challenge. Authenticated via the user session (Authorization: Bearer).","operationId":"McpConsentController_authorize[1]_v1","parameters":[],"responses":{"200":{"description":"Authorization code created"},"400":{"description":"Validation failure (unknown client, bad redirect_uri, bad challenge)"},"401":{"description":"Missing/invalid user JWT"},"403":{"description":"appId not owned by user"}},"summary":"Mint an MCP authorization code","tags":["auth"]}},"/cloud-views":{"get":{"operationId":"RootController_index[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/v1/cloud-views":{"get":{"operationId":"RootController_index[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/cloud-views/tick":{"get":{"operationId":"RootController_tick[0]","parameters":[{"name":"sleepMs","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/v1/cloud-views/tick":{"get":{"operationId":"RootController_tick[1]_v1","parameters":[{"name":"sleepMs","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/cloud-views/brand/translations":{"post":{"operationId":"BrandController_storeTranslations[0]","parameters":[],"responses":{"201":{"description":""}},"tags":["cloud-views"]},"get":{"operationId":"BrandController_getTranslations[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/v1/cloud-views/brand/translations":{"post":{"operationId":"BrandController_storeTranslations[1]_v1","parameters":[],"responses":{"201":{"description":""}},"tags":["cloud-views"]},"get":{"operationId":"BrandController_getTranslations[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/cloud-views/brand/branding":{"get":{"operationId":"BrandController_getBranding[0]","parameters":[{"name":"appId","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/v1/cloud-views/brand/branding":{"get":{"operationId":"BrandController_getBranding[1]_v1","parameters":[{"name":"appId","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/cloud-views/flags/evaluate/{appId}/{flagKey}":{"get":{"operationId":"FeatureFlagsController_getEvaluate[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"flagKey","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]},"post":{"operationId":"FeatureFlagsController_postEvaluate[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"flagKey","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BodyWithCtxAndToken"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/v1/cloud-views/flags/evaluate/{appId}/{flagKey}":{"get":{"operationId":"FeatureFlagsController_getEvaluate[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"flagKey","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]},"post":{"operationId":"FeatureFlagsController_postEvaluate[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}},{"name":"flagKey","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BodyWithCtxAndToken"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/cloud-views/flags/bulkEvaluate/{appId}":{"post":{"operationId":"FeatureFlagsController_bulkEvaluate[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BodyWithCtxAndToken"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/v1/cloud-views/flags/bulkEvaluate/{appId}":{"post":{"operationId":"FeatureFlagsController_bulkEvaluate[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BodyWithCtxAndToken"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["cloud-views"]}},"/v1/flags/eval-events":{"post":{"operationId":"EvalEventsController_ingest_v1","parameters":[],"responses":{"202":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["EvalEvents"]}},"/v1/flags/discover":{"post":{"operationId":"EvalEventsController_ingestDiscoveries_v1","parameters":[],"responses":{"202":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["EvalEvents"]}},"/v1/flags/call-sites":{"post":{"operationId":"EvalEventsController_ingestCallSites_v1","parameters":[],"responses":{"202":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["EvalEvents"]}},"/admin":{"get":{"operationId":"RootController_index[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["admin"]}},"/v1/admin":{"get":{"operationId":"RootController_index[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["admin"]}},"/admin/tick":{"get":{"operationId":"RootController_tick[0]","parameters":[{"name":"sleepMs","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["admin"]}},"/v1/admin/tick":{"get":{"operationId":"RootController_tick[1]_v1","parameters":[{"name":"sleepMs","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["admin"]}},"/admin/brand":{"get":{"operationId":"BrandingAdminController_getBranding[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingOutput"}}}}},"summary":"Read the branding applied to the Bridge-hosted auth pages.","tags":["admin"]},"put":{"operationId":"BrandingAdminController_updateBranding[0]","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBrandingRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingOutput"}}}}},"summary":"Update the branding of the Bridge-hosted auth pages. Partial update.","tags":["admin"]}},"/v1/admin/brand":{"get":{"operationId":"BrandingAdminController_getBranding[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingOutput"}}}}},"summary":"Read the branding applied to the Bridge-hosted auth pages.","tags":["admin"]},"put":{"operationId":"BrandingAdminController_updateBranding[1]_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBrandingRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingOutput"}}}}},"summary":"Update the branding of the Bridge-hosted auth pages. Partial update.","tags":["admin"]}},"/admin/brand/css":{"get":{"operationId":"BrandingAdminController_getCss[0]","parameters":[],"responses":{"200":{"description":""}},"tags":["admin"]},"post":{"operationId":"BrandingAdminController_upsertCSS[0]","parameters":[],"responses":{"201":{"description":""}},"tags":["admin"]},"delete":{"operationId":"BrandingAdminController_deleteCssFile[0]","parameters":[],"responses":{"200":{"description":""}},"summary":"Reset the app's custom CSS to the default (TBP-552).","tags":["admin"]}},"/v1/admin/brand/css":{"get":{"operationId":"BrandingAdminController_getCss[1]_v1","parameters":[],"responses":{"200":{"description":""}},"tags":["admin"]},"post":{"operationId":"BrandingAdminController_upsertCSS[1]_v1","parameters":[],"responses":{"201":{"description":""}},"tags":["admin"]},"delete":{"operationId":"BrandingAdminController_deleteCssFile[1]_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Reset the app's custom CSS to the default (TBP-552).","tags":["admin"]}},"/admin/brand-internal/css/{appId}":{"get":{"operationId":"BrandingInternalController_getCss[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}}},"tags":["internal"]}},"/v1/admin/brand-internal/css/{appId}":{"get":{"operationId":"BrandingInternalController_getCss[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}}},"tags":["internal"]}},"/admin/brand-internal/branding/{appId}":{"get":{"operationId":"BrandingInternalController_getBranding[0]","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingOutput"}}}}},"tags":["internal"]}},"/v1/admin/brand-internal/branding/{appId}":{"get":{"operationId":"BrandingInternalController_getBranding[1]_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingOutput"}}}}},"tags":["internal"]}},"/api/perf-log":{"post":{"operationId":"PerfLogController_log[0]","parameters":[],"responses":{"204":{"description":""}},"tags":["internal"]}},"/v1/api/perf-log":{"post":{"operationId":"PerfLogController_log[1]_v1","parameters":[],"responses":{"204":{"description":""}},"tags":["internal"]}},"/api/perf-log/cold-start":{"get":{"operationId":"PerfLogController_getColdStart[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["internal"]}},"/v1/api/perf-log/cold-start":{"get":{"operationId":"PerfLogController_getColdStart[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["internal"]}},"/session/init":{"get":{"operationId":"SessionController_getInit[0]","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Returns the same payload as the channel `session.snapshot.data` field.\nNon-channel consumers call this on bootstrap (and on reconnect if they\nchoose REST rather than channel).","tags":["session"]}},"/v1/session/init":{"get":{"operationId":"SessionController_getInit[1]_v1","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"summary":"Returns the same payload as the channel `session.snapshot.data` field.\nNon-channel consumers call this on bootstrap (and on reconnect if they\nchoose REST rather than channel).","tags":["session"]}}},"info":{"title":"Bridge API","description":"Bridge Platform REST API. GraphQL: see /graphql playground.","version":"1.0","contact":{}},"tags":[],"servers":[],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"},"x-api-key":{"type":"apiKey","in":"header","name":"x-api-key"},"x-app-id":{"type":"apiKey","in":"header","name":"x-app-id"}},"schemas":{"RedditCapiDebugFireRequestDto":{"type":"object","properties":{}},"CreatePlaywrightAccountRequestDto":{"type":"object","properties":{}},"RemovePlaywrightAccountRequestDto":{"type":"object","properties":{}},"PurgeTestAccountsRequestDto":{"type":"object","properties":{}},"GenerateJwtRequestDto":{"type":"object","properties":{}},"SetupAdminAppWithOwnerRequestDto":{"type":"object","properties":{}},"SetupTestAppRequestDto":{"type":"object","properties":{}},"DeleteTestAppRequestDto":{"type":"object","properties":{}},"SetupSdkAppRequestDto":{"type":"object","properties":{}},"CreateTenantUserRequestDto":{"type":"object","properties":{}},"AddTenantToUserRequestDto":{"type":"object","properties":{}},"AddUserToTenantRequestDto":{"type":"object","properties":{}},"UpdateTenantUserRoleRequestDto":{"type":"object","properties":{}},"ConfigureAppRequestDto":{"type":"object","properties":{}},"EnableTenantMfaRequestDto":{"type":"object","properties":{}},"ResetUserMfaRequestDto":{"type":"object","properties":{}},"CreatePlanRequestDto":{"type":"object","properties":{}},"ExpireTrialRequestDto":{"type":"object","properties":{}},"DeletePlanRequestDto":{"type":"object","properties":{}},"SweepPlansRequestDto":{"type":"object","properties":{}},"SetTenantPlanRequestDto":{"type":"object","properties":{}},"ClearTenantPlanRequestDto":{"type":"object","properties":{}},"GetAppResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique ID (Read only)"},"name":{"type":"string","description":"Name of the app"},"domain":{"type":"string","description":"Unique domain name of the app (Read only)"},"apiUrl":{"type":"string","description":"URL to your api (to receive webhooks etc). **Must be HTTPS**"},"uiUrl":{"type":"string","description":"URL to your frontend app (for onboarding redirects etc). **Must be HTTPS**"},"logo":{"type":"string","description":"URL to your logo"},"websiteUrl":{"type":"string","description":"URL to your website or landing page. E.g. Branded emails will link to this URL, checkout process will redirect to `/payment-success` and `/payment-cancel`"},"webhookUrl":{"type":"string","description":"Events like tenant and user updates will be sent to this webhook url"},"privacyPolicyUrl":{"type":"string","description":"URL to a page on your website containing a Privacy policy for your app users. E.g. checkout process will link to this url."},"termsOfServiceUrl":{"type":"string","description":"URL to a page on your website containing a Terms of service for your app users. E.g. checkout process will link to this url."},"emailSenderName":{"type":"string","description":"Emails sent from Nblocks will have this sender name"},"emailSenderEmail":{"type":"string","description":"Emails sent from Nblocks will have this sender email. You'll have to verify this email before"},"paymentsAutoRedirect":{"type":"boolean"},"stripeEnabled":{"type":"boolean","description":"Boolean value telling the user if Stripe is enabled"},"stripeSetupStatus":{"description":"Status of Stripe setup process","enum":["completed","pending","failed"],"type":"string"},"stripeSetupError":{"type":"string","nullable":true,"description":"Error message if Stripe setup failed"},"stripeLastWebhookAt":{"format":"date-time","type":"string","nullable":true,"description":"Last time a Stripe webhook event was received and verified. Null means none has been verified yet."},"stripeLastWebhookRejectedAt":{"format":"date-time","type":"string","nullable":true,"description":"Last time a Stripe webhook event was rejected"},"stripeLastWebhookRejectionReason":{"type":"string","nullable":true,"description":"Why the last Stripe webhook event was rejected: `no_signing_secret`, `signature_mismatch` or `raw_body_missing`"},"stripeWebhookRejectionStreak":{"type":"number","description":"Rejected Stripe webhook events since the last verified one, counted at most once per minute. 3 or more means events are being rejected persistently."},"allowedTokenPrivileges":{"nullable":true,"description":"Allowed privileges for API tokens","type":"array","items":{"type":"string"}},"passkeysEnabled":{"type":"boolean","description":"Boolean value telling the user if passkeys login is enabled"},"mfaEnabled":{"type":"boolean","description":"Boolean value telling the user if MFA is enabled"},"magicLinkEnabled":{"type":"boolean","description":"Boolean value telling the user if Login with Magic Link is enabled"},"googleSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Google Social login / SSO is enabled"},"linkedinSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if LinkedIn Social login / SSO is enabled"},"azureAdSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Azure AD SSO is enabled"},"azureMarketplaceEnabled":{"type":"boolean","description":"Boolean value telling the user if Azure marketplace is enabled"},"appleSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Apple Social login / SSO is enable"},"githubSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Github Social login / SSO is enable"},"facebookSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Facebook Social login / SSO is enable"},"onboardingFlow":{"description":"Configure how users will be onboarded","enum":["B2B","B2C"],"type":"string"},"tenantSelfSignup":{"type":"boolean","description":"Allow self signup (relates to cloud views, payment providers etc)"},"redirectUris":{"description":"Allowed redirect uris","type":"array","items":{"type":"string"}},"allowedOrigins":{"description":"Allowed origins for SDK mode (CORS + origin validation)","type":"array","items":{"type":"string"}},"defaultCallbackUri":{"type":"string","description":"Default handover/callback uri used by Nblocks"},"accessTokenTTL":{"type":"number","description":"TTL for access token, default 1 hour"},"refreshTokenTTL":{"type":"number","description":"TTL for refresh token, default 1 week"}},"required":["id","name","domain","apiUrl","uiUrl","logo","websiteUrl","webhookUrl","privacyPolicyUrl","termsOfServiceUrl","paymentsAutoRedirect","stripeEnabled","passkeysEnabled","mfaEnabled","magicLinkEnabled","googleSsoEnabled","linkedinSsoEnabled","azureAdSsoEnabled","azureMarketplaceEnabled","appleSsoEnabled","githubSsoEnabled","facebookSsoEnabled","onboardingFlow","tenantSelfSignup","redirectUris","allowedOrigins","defaultCallbackUri","accessTokenTTL","refreshTokenTTL"]},"UpdateAppRequestDto":{"type":"object","properties":{"name":{"type":"string"},"apiUrl":{"type":"string"},"uiUrl":{"type":"string"},"webhookUrl":{"type":"string"},"webhookEventFilter":{"type":"array","items":{"type":"string"}},"webhookEnabled":{"type":"boolean"},"logo":{"type":"string"},"tenantSelfSignup":{"type":"boolean","description":"Allow self signup (relates to cloud views, payment providers etc)"},"redirectUris":{"description":"Allowed redirect uris","type":"array","items":{"type":"string"}},"allowedOrigins":{"description":"Allowed origins for SDK mode (CORS + origin validation)","type":"array","items":{"type":"string"}},"defaultCallbackUri":{"type":"string","description":"Default handover/callback uri used by Nblocks"},"onboardingFlow":{"enum":["B2B","B2C"],"type":"string"},"websiteUrl":{"type":"string"},"privacyPolicyUrl":{"type":"string"},"termsOfServiceUrl":{"type":"string"},"emailSenderName":{"type":"string"},"emailSenderEmail":{"type":"string"},"paymentsAutoRedirect":{"type":"boolean"},"passkeysEnabled":{"type":"boolean"},"stripeEnabled":{"type":"boolean"},"currency":{"type":"string"},"mfaEnabled":{"type":"boolean"},"magicLinkEnabled":{"type":"boolean"},"googleSsoEnabled":{"type":"boolean"},"linkedinSsoEnabled":{"type":"boolean"},"azureAdSsoEnabled":{"type":"boolean"},"appleSsoEnabled":{"type":"boolean"},"githubSsoEnabled":{"type":"boolean"},"facebookSsoEnabled":{"type":"boolean"},"azureMarketplaceEnabled":{"type":"boolean"},"accessTokenTTL":{"type":"number"},"refreshTokenTTL":{"type":"number"},"allowedTokenPrivileges":{"nullable":true,"description":"Controls which privileges workspace users (OWNER/ADMIN) can grant on workspace-scoped API tokens.\nnull = flexible (no restriction). [] = disabled. ['USER_READ', ...] = restricted to list.","type":"array","items":{"type":"string"}}}},"GetCredentialsStateResponseDto":{"type":"object","properties":{"stripeCredentialsAdded":{"type":"boolean"},"stripeWebhookConfigured":{"type":"boolean","description":"True when Bridge holds the signing secret for the app's Stripe webhook endpoint. Without it Stripe events (subscription changes, payment failures, cancellations) are rejected and do not sync."},"stripeWebhookEventsStale":{"type":"boolean","description":"True when the app's Stripe webhook endpoint is subscribed to an event list older than the one Bridge acts on, so events added since it was created never arrive. Repairing the webhook resubscribes it. A derived boolean — never the endpoint id or the signing secret."},"stripeAccountId":{"type":"string","description":"The Stripe account this app is connected to, e.g. `acct_1A2b3C`. An identifier, not a secret. Absent until it has been resolved from Stripe."},"stripeMode":{"type":"string","description":"The Stripe mode the app's keys operate in: `test` or `live`. Absent when no Stripe key is stored."},"stripeAccountSharing":{"type":"object","description":"Set only when another Bridge app uses the same Stripe account and mode. Other apps are named only when they belong to the same owner; otherwise only a count is given."},"azureMarketplaceCredentialsAdded":{"type":"boolean"},"azureAdSsoCredentialsAdded":{"type":"boolean"},"googleSsoCredentialsAdded":{"type":"boolean"},"linkedinSsoCredentialsAdded":{"type":"boolean"},"appleSsoCredentialsAdded":{"type":"boolean"},"githubSsoCredentialsAdded":{"type":"boolean"},"facebookSsoCredentialsAdded":{"type":"boolean"}},"required":["stripeCredentialsAdded","stripeWebhookConfigured","stripeWebhookEventsStale","azureMarketplaceCredentialsAdded","azureAdSsoCredentialsAdded","googleSsoCredentialsAdded","linkedinSsoCredentialsAdded","appleSsoCredentialsAdded","githubSsoCredentialsAdded","facebookSsoCredentialsAdded"]},"UpdateCredentialsRequestDto":{"type":"object","properties":{"stripeSecretKey":{"type":"string","description":"Stripe integration"},"stripePublicKey":{"type":"string","description":"Stripe integration"},"microsoftAzureMarketplaceClientId":{"type":"string","description":"Microsoft Azure Marketplace integration App"},"microsoftAzureMarketplaceClientSecret":{"type":"string","description":"Microsoft Azure Marketplace integration App"},"microsoftAzureMarketplaceTenantId":{"type":"string","description":"Microsoft Azure Marketplace integration App"},"googleClientId":{"type":"string","description":"Google social login"},"googleClientSecret":{"type":"string","description":"Google social login"},"linkedinClientId":{"type":"string","description":"LinkedIn social login"},"linkedinClientSecret":{"type":"string","description":"linkedin social login"},"githubClientId":{"type":"string","description":"Gitlab social login"},"githubClientSecret":{"type":"string","description":"Gitlab social login"},"facebookClientId":{"type":"string","description":"Facebook social login"},"facebookClientSecret":{"type":"string","description":"Facebook social login"},"microsoftAzureADClientId":{"type":"string","description":"MS Azure AD SSO"},"microsoftAzureADClientSecret":{"type":"string","description":"MS Azure AD SSO"},"microsoftAzureADTenantId":{"type":"string","description":"MS Azure AD SSO"},"appleClientId":{"type":"string","description":"Apple social login"},"appleTeamId":{"type":"string","description":"Apple social login"},"appleKeyId":{"type":"string","description":"Apple social login"},"applePrivateKey":{"type":"string","description":"Apple social login"}}},"PlanResponse":{"type":"object","properties":{}},"CreatePlanRequest":{"type":"object","properties":{}},"UpdatePlanRequest":{"type":"object","properties":{}},"TaxResponse":{"type":"object","properties":{}},"CreateTaxRequest":{"type":"object","properties":{}},"UpdateTaxRequest":{"type":"object","properties":{}},"PriceOffer":{"type":"object","properties":{}},"CustomParam":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"userLabel":{"type":"string"},"type":{"type":"string","enum":["email","phone","number","integer","text","regex","boolean"]},"regex":{"type":"string"}},"required":["value","label","type","regex"]},"TenantOwnerRequestDto":{"type":"object","properties":{"email":{"type":"string","description":"Required","format":"email"},"firstName":{"type":"string","description":"The first name"},"lastName":{"type":"string","description":"The last name"},"muteNotifications":{"type":"boolean","description":"Set this variable to true if you don't wish to send out any notifications to the new user"},"customParams":{"type":"array","items":{"$ref":"#/components/schemas/CustomParam"}}},"required":["email"]},"CreateTenantRequestDto":{"type":"object","properties":{"plan":{"type":"string","description":"The plan must be present in the configured App business model"},"priceOffer":{"description":"If a specific pricing offer should be used. Use this if you offer the same plan in multiple periods or currencies. Otherwise the first price will be used","allOf":[{"$ref":"#/components/schemas/PriceOffer"}]},"owner":{"description":"A user will need to be assigned as an owner to this tenant. Either reused if the user already exist or a new user will be created","allOf":[{"$ref":"#/components/schemas/TenantOwnerRequestDto"}]},"name":{"type":"string","description":"Name of the new tenant. Can also be set by tenant owner during onboarding"},"onboarded":{"type":"boolean","description":"Is the tenant considered onboarded from start?"},"logo":{"type":"string","description":"A url to a logo. Can also be set by tenant owner during onboarding"},"locale":{"type":"string","description":"The default locale / lang code for all users in this tenant (`ISO_639-1` format).\nThis property will set the i18n for all platform emails and can be used to.\nDefaults to 'en'"},"metadata":{"type":"object","description":"Store metadata for your own business logic that will be returned in every Tenant response. This data will never be outputted to the end user"},"authOriginUrl":{"type":"string","description":"Origin URL of the caller — used to resolve where email links (e.g. password reset) should point"},"signupMethod":{"type":"string","description":"TBP-505 — how the tenant owner signed up (e.g. 'google', 'ms-azure-ad',\n'linkedin'). Set ONLY by the federation signup path so account can fire\nthe SignUp/Lead conversion tracking server-side — SSO signups never pass\nthrough the client-side signup page that fires them for email signups.\nDeliberately NOT in the import allowlist (TBP-43): imports must not fire\nconversion events.","maxLength":32}},"required":["owner"]},"TenantResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Logical id reference to this instance"},"plan":{"type":"string","description":"Name of the subscription plan. (Read only)\nUse `setPlanDetails` to change it\nAutomatically set by the payment service if tenant used the checkout process"},"mfa":{"type":"boolean","description":"MFA enabled"},"paymentStatus":{"type":"object","description":"Payment status"},"trial":{"type":"boolean","description":"Tenant is trialing (Read only)"},"locale":{"type":"string","description":"The default locale / lang code for all users in this tenant (`ISO_639-1` format).\nThis property will set the i18n for all platform emails and can be used to"},"name":{"type":"string","description":"Name of the tenant. Undefined from the begining until the Tenant owner complets tenant onboarding."},"logo":{"type":"string","description":"Url to a public accessible logo"},"metadata":{"type":"object","description":"Store app specific meta data for this tenant"},"onboarded":{"type":"boolean","description":"If this tenant is considered onboarded"},"federationConnection":{"type":"string","description":"Logins are made with this enterprise login connection"},"signupBy":{"type":"object","properties":{"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"}},"required":[]},"createdAt":{"format":"date-time","type":"string","description":"Timestamp when created"}},"required":["id","mfa","paymentStatus","trial","locale","metadata","onboarded","createdAt"]},"SetTenantPlanDetails":{"type":"object","properties":{}},"UpdateTenantRequestDto":{"type":"object","properties":{"name":{"type":"string"},"onboarded":{"type":"boolean"},"locale":{"type":"string"},"logo":{"type":"string"},"mfa":{"type":"boolean"},"federationConnection":{"type":"string"},"metadata":{"type":"object"}}},"TranslateTextRequest":{"type":"object","properties":{"sourceLanguage":{"type":"string","description":"The language of the original text, optional (Api will try to identify the language if not provided)"},"text":{"type":"string","description":"The text you wish to translate"}},"required":["text"]},"TranslateTextResponseDto":{"type":"object","properties":{"translatedText":{"type":"string","description":"The translated text."},"targetLanguageCode":{"type":"string","description":"Language translated into, echoed back."},"sourceLanguageCode":{"type":"string","description":"Language of the source text. When `sourceLanguage` was omitted this is the\nlanguage that was detected — the useful half of the answer when a reporter\nwrites in a language the reader does not know."}},"required":["translatedText","targetLanguageCode","sourceLanguageCode"]},"CustomerPortalResponseDto":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"PrepareUploadRequestDto":{"type":"object","properties":{"name":{"type":"string"},"contentType":{"type":"string"}},"required":["name","contentType"]},"CreatePresignedPostResponseDto":{"type":"object","properties":{"url":{"type":"string","description":"Upload to this url"},"fields":{"type":"object","description":"Attach these headers to the upload call. Keep order of headers"}},"required":["url","fields"]},"FinishUploadRequestDto":{"type":"object","properties":{"persist":{"type":"boolean"},"key":{"type":"string"}},"required":["key"]},"TenantUserResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Shared properties with AuthTenantUserResponseDto"},"role":{"type":"string","description":"Role of the user. Grants a set of privileges. Privileges are configured on the `App` model."},"email":{"type":"string","description":"Email address, same as username ATM"},"username":{"type":"string","description":"Username, same as Email address ATM"},"firstName":{"type":"string","description":"Users first name"},"lastName":{"type":"string","description":"Users last name"},"fullName":{"type":"string","description":"Users full name (first name and last name concatenated)"},"onboarded":{"type":"boolean","description":"If user is onboarded or not (should be put through app onboarding). If `firstname` and `lastname` are set on invitation `onboarded` is set to true"},"consentsToPrivacyPolicy":{"type":"boolean","description":"If user have left consent to the app privacy policy or not (should be set during app onboarding)"},"enabled":{"type":"boolean","description":"Custom properties different from AuthTenantUserResponseDto"},"teams":{"description":"Array of identifiers that can be used to group several users into teams or groups","type":"array","items":{"type":"string"}},"createdAt":{"format":"date-time","type":"string","description":"Date when the user was created"},"lastSeen":{"format":"date-time","type":"string","description":"Any account activity: sign-in, token refresh, email verification or a credentials change. NOT a sign-in timestamp — use `lastSignIn` for that. Undefined if never seen."},"lastSignIn":{"format":"date-time","type":"string","description":"When the user last signed in. Undefined if never signed in. Account-wide: a user who belongs to several workspaces has one value across all of them. Use `lastWorkspaceSignIn` to scope it to this workspace."},"lastWorkspaceSignIn":{"format":"date-time","type":"string","description":"When the user last signed in to THIS workspace. Undefined if they have not signed in here since 2026-09-08, when the field shipped — it is not backfilled, because the historical data does not exist. Unlike `lastSignIn`, a user who belongs to several workspaces has a separate value per workspace. Token refresh does not move it."},"customParams":{"type":"array","items":{"$ref":"#/components/schemas/CustomParam"}},"tenant":{"description":"Users tenant","allOf":[{"$ref":"#/components/schemas/TenantResponseDto"}]}},"required":["id","role","email","username","onboarded","consentsToPrivacyPolicy","enabled","teams","createdAt","lastSeen","customParams","tenant"]},"CreateUserRequestDto":{"type":"object","properties":{"muteNotifications":{"type":"boolean","description":"Set this variable to true if you don't wish to send out any notifications to the user"},"username":{"type":"string","description":"Email address to the new user"},"role":{"type":"string","description":"The role must be present in App.roles"},"firstName":{"type":"string","description":"User's first name"},"lastName":{"type":"string","description":"User's last name"},"phoneNumber":{"type":"string","description":"User's phone number"},"customParams":{"description":"User's custom params","type":"array","items":{"$ref":"#/components/schemas/CustomParam"}}},"required":["username"]},"UpdateUserRequestDto":{"type":"object","properties":{"role":{"type":"string"},"enabled":{"type":"boolean"},"teams":{"type":"array","items":{"type":"string"}},"firstName":{"type":"string"},"lastName":{"type":"string"},"phoneNumber":{"type":"string"},"onboarded":{"type":"boolean"},"consentsToPrivacyPolicy":{"type":"boolean"},"customParams":{"type":"array","items":{"$ref":"#/components/schemas/CustomParam"}}}},"EmailUserRequestDto":{"type":"object","properties":{"emailBody":{"type":"string"},"subject":{"type":"string"},"ctaUrl":{"type":"string"},"ctaTitle":{"type":"string"}},"required":["emailBody","subject"]},"PrivilegeResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Logical id reference to this instance"},"key":{"type":"string","description":"The key of the privilege, used for reference"},"description":{"type":"string","description":"An optional description of the privilege"}},"required":["id","key"]},"RoleResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Logical id reference to this instance"},"name":{"type":"string","description":"Name of the role"},"key":{"type":"string","description":"The key of the role, used for reference"},"description":{"type":"string","description":"An optional description of the role"},"privileges":{"description":"The collection of Privileges","type":"array","items":{"$ref":"#/components/schemas/PrivilegeResponseDto"}},"isDefault":{"type":"boolean","description":"Is this the default role"}},"required":["id","name","key","privileges","isDefault"]},"CreateRoleRequestDto":{"type":"object","properties":{"name":{"type":"string"},"key":{"type":"string"},"description":{"type":"string"},"privileges":{"type":"array","items":{"type":"string"}},"isDefault":{"type":"boolean"}},"required":["name","key","privileges","isDefault"]},"UpdateRoleRequestDto":{"type":"object","properties":{"name":{"type":"string"},"key":{"type":"string"},"description":{"type":"string"},"privileges":{"type":"array","items":{"type":"string"}},"isDefault":{"type":"boolean"}}},"CreatePrivilegeRequestDto":{"type":"object","properties":{"key":{"type":"string"},"description":{"type":"string"}},"required":["key"]},"UpdatePrivilegeRequestDto":{"type":"object","properties":{"key":{"type":"string"},"description":{"type":"string"}}},"CreateCanonicalSubscriptionDto":{"type":"object","properties":{"planSlug":{"type":"string"}}},"CanonicalSubscriptionDto":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"plan":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}},"required":["slug","name"]},"status":{"enum":["trial","active","past_due","cancel_at_period_end","canceled"],"type":"string"},"createdAt":{"format":"date-time","type":"string"},"endsAt":{"type":"string"},"gateEngaged":{"type":"boolean"}},"required":["id","workspaceId","plan","status","createdAt"]},"BillingStateDto":{"type":"object","properties":{"plan":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}},"required":["slug","name"]},"status":{"type":"string","enum":["trial","active","past_due","cancel_at_period_end","canceled"]},"renewsAt":{"type":"string"},"endsAt":{"type":"string"},"gateEngaged":{"type":"boolean"}},"required":["plan","status"]},"RealtimeDiagnoseRequestDto":{"type":"object","properties":{"channels":{"description":"Channels the client was refused on, e.g. `workspace:<id>` or `app:<id>`.","maxItems":50,"type":"array","items":{"type":"string","maxLength":256}}},"required":["channels"]},"GetAppConfigResponseDto":{"type":"object","properties":{"name":{"type":"string"},"passkeysEnabled":{"type":"boolean"},"magicLinkEnabled":{"type":"boolean"},"mfaEnabled":{"type":"boolean"},"tenantSelfSignup":{"type":"boolean"},"googleSsoEnabled":{"type":"boolean"},"linkedinSsoEnabled":{"type":"boolean"},"azureAdSsoEnabled":{"type":"boolean"},"facebookSsoEnabled":{"type":"boolean"},"githubSsoEnabled":{"type":"boolean"},"appleSsoEnabled":{"type":"boolean"},"allowedOrigins":{"description":"Public-safe list of origins permitted to talk to this app's SDK surfaces.\nConsumed by the AppSync Events Lambda authorizer to gate anonymous\n`app:<appId>` channel subscriptions (TBP-148.3).","type":"array","items":{"type":"string"}}},"required":["name","passkeysEnabled","magicLinkEnabled","mfaEnabled","tenantSelfSignup","googleSsoEnabled","linkedinSsoEnabled","azureAdSsoEnabled","facebookSsoEnabled","githubSsoEnabled","appleSsoEnabled","allowedOrigins"]},"RealtimeStatusRequestDto":{"type":"object","properties":{"state":{"type":"string","description":"Connection state being reported.","enum":["connecting","open","degraded","unauthorized","closed","idle"]},"reason":{"type":"string","description":"Machine-readable reason for a refused or degraded connection (lowercase, digits, underscores)."},"side":{"type":"string","description":"Whose move it is to fix a refusal.","enum":["app","bridge","config","network"]},"ref":{"type":"string","description":"Client-side correlation id of the connection episode.","maxLength":32}},"required":["state"]},"AuthenticateRequestDto":{"type":"object","properties":{"username":{"type":"string"},"password":{"type":"string"}},"required":["username","password"]},"AuthenticateResponseDto":{"type":"object","properties":{"token":{"type":"string","description":"Auth token to include in every call the user makes"},"mfaState":{"type":"string","description":"This property tells if user expects to authenticate with MFA or not. Possible values: DISABLED, REQUIRED, SETUP","enum":["DISABLED","REQUIRED","SETUP"]}},"required":["token","mfaState"]},"CommitMfaCodeRequestDto":{"type":"object","properties":{"authToken":{"type":"string"},"mfaCode":{"type":"string"}},"required":["authToken","mfaCode"]},"CommitMfaCodeResponseDto":{"type":"object","properties":{}},"StartUserMfaSetupRequestDto":{"type":"object","properties":{"authToken":{"type":"string"},"phoneNumber":{"type":"string"}},"required":["authToken","phoneNumber"]},"FinishUserMfaSetupRequestDto":{"type":"object","properties":{"authToken":{"type":"string"},"mfaCode":{"type":"string"}},"required":["authToken","mfaCode"]},"FinishUserMfaSetupResponseDto":{"type":"object","properties":{}},"ResetUserMfaSetupRequestDto":{"type":"object","properties":{"authToken":{"type":"string"},"backupCode":{"type":"string"}},"required":["authToken","backupCode"]},"AuthenticatedRequestDto":{"type":"object","properties":{"authToken":{"type":"string"}},"required":["authToken"]},"ForgotPasswordRequestDto":{"type":"object","properties":{"username":{"type":"string"},"redirectUri":{"type":"string","description":"Optional redirect_uri to preserve through the forgot password flow"}},"required":["username"]},"UpdatePasswordRequestDto":{"type":"object","properties":{"token":{"type":"string"},"password":{"type":"string","minLength":8}},"required":["token","password"]},"UpdateUserInfoRequestDto":{"type":"object","properties":{"authToken":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phoneNumber":{"type":"string"},"consentsToPrivacyPolicy":{"type":"boolean"}},"required":["authToken","firstName","lastName"]},"AuthListTenantUsersRequestDto":{"type":"object","properties":{"authToken":{"type":"string"}},"required":["authToken"]},"AuthTenantResponse":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"plan":{"type":"string"},"locale":{"type":"string"},"logo":{"type":"string"},"onboarded":{"type":"boolean"}},"required":["id","locale","onboarded"]},"AuthTenantUserResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique ID"},"role":{"type":"string","description":"Role of the user. Grants a set of privileges. Privileges are configured on the `App` model."},"email":{"type":"string","description":"Email address, same as username ATM"},"username":{"type":"string","description":"Username, same as Email address ATM"},"firstName":{"type":"string","description":"Users first name"},"lastName":{"type":"string","description":"Users last name"},"fullName":{"type":"string","description":"Users full name (first name and last name concatenated)"},"onboarded":{"type":"boolean","description":"If user is onboarded or not (should be put through app onboarding)"},"consentsToPrivacyPolicy":{"type":"boolean","description":"If user have left consent to the app privacy policy or not (should be set during app onboarding)"},"tenant":{"$ref":"#/components/schemas/AuthTenantResponse"}},"required":["id","role","email","username","firstName","lastName","fullName","onboarded","consentsToPrivacyPolicy","tenant"]},"AuthorizeRequestDto":{"type":"object","properties":{"authToken":{"type":"string"},"tenantUserId":{"type":"string"},"privilege":{"type":"string"}},"required":["authToken","tenantUserId","privilege"]},"AuthorizeResponseDto":{"type":"object","properties":{"granted":{"type":"boolean"},"user":{"$ref":"#/components/schemas/AuthTenantUserResponseDto"}},"required":["granted","user"]},"FederationConnectionResponse":{"type":"object","properties":{}},"CreateFederationConnectionRequest":{"type":"object","properties":{}},"UpdateFederationConnectionRequest":{"type":"object","properties":{}},"IngestUsageDto":{"type":"object","properties":{"metric":{"type":"string"},"value":{"type":"number","minimum":1},"idempotencyKey":{"type":"string"}},"required":["metric"]},"SetGaugeDto":{"type":"object","properties":{"value":{"type":"number","description":"The current absolute value (how many exist right now). Integer >= 0.","minimum":0}},"required":["value"]},"AuthApiAuthenticateResponseDto":{"type":"object","properties":{"appConfig":{"type":"object"},"userId":{"type":"string","description":"This is user.id not tenantUser.id"},"tenantUsers":{"type":"array","items":{"$ref":"#/components/schemas/AuthTenantUserResponseDto"}},"mfaState":{"enum":["DISABLED","REQUIRED","SETUP"],"type":"string"},"mfaChallengeId":{"type":"string","description":"TBP-775 — id of the server-side MFA challenge; the code itself never leaves the account service."},"devCode":{"type":"string"}},"required":["appConfig","userId","tenantUsers","mfaState"]},"AuthApiCredentialsResponseDto":{"type":"object","properties":{"appConfig":{"type":"object"}},"required":["appConfig"]},"CreateAppRequestDto":{"type":"object","properties":{"name":{"type":"string"},"domain":{"type":"string","description":"Just for internal use, should be left blank for auto generation"},"apiUrl":{"type":"string"},"uiUrl":{"type":"string"},"webhookUrl":{"type":"string"},"logo":{"type":"string"},"websiteUrl":{"type":"string"},"privacyPolicyUrl":{"type":"string"},"termsOfServiceUrl":{"type":"string"},"metaData":{"type":"object"},"defaultCallbackUri":{"type":"string","description":"TBP-764 — the app's sign-in callback address, optional. When given it is\nregistered as the only redirect URI and made the default callback; when\nomitted the app starts with none and sign-in fails with\nNBLOCKS_NO_CALLBACK_URI until one is added.","format":"uri"}},"required":["name"]},"CreateAppResponseDto":{"type":"object","properties":{"apiKey":{"type":"string","description":"Your unique api key to provide in future calls. Will never be revealed again"},"app":{"description":"App model via GetAppResponseDto","allOf":[{"$ref":"#/components/schemas/GetAppResponseDto"}]}},"required":["apiKey","app"]},"AppLightResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique ID"},"name":{"type":"string","description":"Name of the app"},"logo":{"type":"string","description":"URL to your logo"}},"required":["id","name","logo"]},"AppConfigResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique ID (Read only)"},"name":{"type":"string","description":"Name of the app"},"domain":{"type":"string","description":"Unique domain name of the app (Read only)"},"apiUrl":{"type":"string","description":"URL to your api (to receive webhooks etc). **Must be HTTPS**"},"uiUrl":{"type":"string","description":"URL to your frontend app (for onboarding redirects etc). **Must be HTTPS**"},"logo":{"type":"string","description":"URL to your logo"},"websiteUrl":{"type":"string","description":"URL to your website or landing page. E.g. Branded emails will link to this URL, checkout process will redirect to `/payment-success` and `/payment-cancel`"},"webhookUrl":{"type":"string","description":"Events like tenant and user updates will be sent to this webhook url"},"privacyPolicyUrl":{"type":"string","description":"URL to a page on your website containing a Privacy policy for your app users. E.g. checkout process will link to this url."},"termsOfServiceUrl":{"type":"string","description":"URL to a page on your website containing a Terms of service for your app users. E.g. checkout process will link to this url."},"emailSenderName":{"type":"string","description":"Emails sent from Nblocks will have this sender name"},"emailSenderEmail":{"type":"string","description":"Emails sent from Nblocks will have this sender email. You'll have to verify this email before"},"paymentsAutoRedirect":{"type":"boolean"},"stripeEnabled":{"type":"boolean","description":"Boolean value telling the user if Stripe is enabled"},"stripeSetupStatus":{"description":"Status of Stripe setup process","enum":["completed","pending","failed"],"type":"string"},"stripeSetupError":{"type":"string","nullable":true,"description":"Error message if Stripe setup failed"},"stripeLastWebhookAt":{"format":"date-time","type":"string","nullable":true,"description":"Last time a Stripe webhook event was received and verified. Null means none has been verified yet."},"stripeLastWebhookRejectedAt":{"format":"date-time","type":"string","nullable":true,"description":"Last time a Stripe webhook event was rejected"},"stripeLastWebhookRejectionReason":{"type":"string","nullable":true,"description":"Why the last Stripe webhook event was rejected: `no_signing_secret`, `signature_mismatch` or `raw_body_missing`"},"stripeWebhookRejectionStreak":{"type":"number","description":"Rejected Stripe webhook events since the last verified one, counted at most once per minute. 3 or more means events are being rejected persistently."},"allowedTokenPrivileges":{"nullable":true,"description":"Allowed privileges for API tokens","type":"array","items":{"type":"string"}},"passkeysEnabled":{"type":"boolean","description":"Boolean value telling the user if passkeys login is enabled"},"mfaEnabled":{"type":"boolean","description":"Boolean value telling the user if MFA is enabled"},"magicLinkEnabled":{"type":"boolean","description":"Boolean value telling the user if Login with Magic Link is enabled"},"googleSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Google Social login / SSO is enabled"},"linkedinSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if LinkedIn Social login / SSO is enabled"},"azureAdSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Azure AD SSO is enabled"},"azureMarketplaceEnabled":{"type":"boolean","description":"Boolean value telling the user if Azure marketplace is enabled"},"appleSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Apple Social login / SSO is enable"},"githubSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Github Social login / SSO is enable"},"facebookSsoEnabled":{"type":"boolean","description":"Boolean value telling the user if Facebook Social login / SSO is enable"},"onboardingFlow":{"description":"Configure how users will be onboarded","enum":["B2B","B2C"],"type":"string"},"tenantSelfSignup":{"type":"boolean","description":"Allow self signup (relates to cloud views, payment providers etc)"},"redirectUris":{"description":"Allowed redirect uris","type":"array","items":{"type":"string"}},"allowedOrigins":{"description":"Allowed origins for SDK mode (CORS + origin validation)","type":"array","items":{"type":"string"}},"defaultCallbackUri":{"type":"string","description":"Default handover/callback uri used by Nblocks"},"accessTokenTTL":{"type":"number","description":"TTL for access token, default 1 hour"},"refreshTokenTTL":{"type":"number","description":"TTL for refresh token, default 1 week"},"webhookSecretSet":{"type":"boolean","description":"Whether a webhook signing secret has been minted"},"webhookEventFilter":{"description":"Event types delivered to the webhook URL","type":"array","items":{"type":"string"}},"webhookEnabled":{"type":"boolean","description":"Whether webhook delivery is on"},"webhookConsecutiveFailures":{"type":"number","description":"Consecutive failed deliveries (auto-disable at 50)"}},"required":["id","name","domain","apiUrl","uiUrl","logo","websiteUrl","webhookUrl","privacyPolicyUrl","termsOfServiceUrl","paymentsAutoRedirect","stripeEnabled","passkeysEnabled","mfaEnabled","magicLinkEnabled","googleSsoEnabled","linkedinSsoEnabled","azureAdSsoEnabled","azureMarketplaceEnabled","appleSsoEnabled","githubSsoEnabled","facebookSsoEnabled","onboardingFlow","tenantSelfSignup","redirectUris","allowedOrigins","defaultCallbackUri","accessTokenTTL","refreshTokenTTL","webhookSecretSet","webhookEventFilter","webhookEnabled","webhookConsecutiveFailures"]},"StartStopAppTransactionRequestDto":{"type":"object","properties":{"requestId":{"type":"string","description":"(not in use) A unique id of this request for future tracking. If not provided API will create one  for you"},"apiKey":{"type":"string","description":"The api key of the authorized app"},"tenantId":{"type":"string","description":"(Optional) if tenant response is wished"},"tenantUserId":{"type":"string","description":"(Optional) if tenant user response is wished (Requires tenantId to be set aswell)"}},"required":["apiKey"]},"LightAppResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique ID"},"name":{"type":"string","description":"Name of the app"},"domain":{"type":"string","description":"Unique domain name of the app (Readonly)"},"logo":{"type":"string","description":"URL to your logo"},"websiteUrl":{"type":"string","description":"URL to your website or landing page. E.g. Branded emails will link to this URL, checkout process will redirect to `/payment-success` and `/payment-cancel`"},"emailSenderName":{"type":"string","description":"Useful for communication api"},"emailSenderEmail":{"type":"string","description":"Useful for communication api"}},"required":["id","name","domain","logo","websiteUrl"]},"LightTenantResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Logical id reference to this instance"},"locale":{"type":"string","description":"The default locale / lang code for all users in this tenant (`ISO_639-1` format).\nThis property will set the i18n for all platform emails and can be used to"},"name":{"type":"string","description":"Name of the tenant. Undefined from the begining until the Tenant owner complets tenant onboarding."},"logo":{"type":"string","description":"Useful for communication api"},"plan":{"type":"string"}},"required":["id","locale"]},"LightTenantUserResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"Logical id reference to this instance"},"email":{"type":"string","description":"Email address, same as username ATM"},"username":{"type":"string","description":"Username, same as Email address ATM"},"fullName":{"type":"string","description":"Users full name (first name and last name concatenated)"}},"required":["id","email","username","fullName"]},"StartAppTransactionResponseDto":{"type":"object","properties":{"requestId":{"type":"string","description":"A unique id identifying this request. Can be provided or otherwise set by API. Should be used when ending the transaction"},"app":{"$ref":"#/components/schemas/LightAppResponseDto"},"tenant":{"$ref":"#/components/schemas/LightTenantResponseDto"},"tenantUser":{"$ref":"#/components/schemas/LightTenantUserResponseDto"},"apiTokenPrivileges":{"type":"array","items":{"type":"string"}}},"required":["requestId","app"]},"CreateTestAppDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"}},"required":["email","name"]},"CreateAppDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"}},"required":["email","name"]},"StoreAttributionDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"capture":{"type":"string","description":"TBP-474 — how the client obtained this record.\n\n`direct` and `unknown` are NOT interchangeable. `direct` means capture ran\nand found no channel, which is a real answer. `unknown` means capture\ncould not run at all, which is a measurement failure. Collapsing them\nmakes `direct` absorb every failure and then look like the strongest\nchannel at exactly the moment a budget decision rests on it.","enum":["utm","referrer","direct","unknown"]},"marketing_consent":{"type":"boolean","description":"Whether the visitor granted marketing consent.\n\nGates the Reddit CAPI fire only — that sends a hashed email to a third\nparty for advertising. Writing the tenant's own attribution record is\nfirst-party processing and happens regardless, which is what keeps the\nmeasurement honest for people who refuse cookies."},"rdt_cid":{"type":"string"},"utm_source":{"type":"string"},"utm_medium":{"type":"string"},"utm_campaign":{"type":"string"},"utm_content":{"type":"string"},"utm_term":{"type":"string"},"gclid":{"type":"string"},"fbclid":{"type":"string"},"li_fat_id":{"type":"string"}},"required":["email"]},"ClearPendingPixelEventDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"event_type":{"type":"string","enum":["purchase","signup","lead"]}},"required":["email","event_type"]},"ParamConfigInputDto":{"type":"object","properties":{"label":{"type":"string"},"type":{"enum":["email","phone","number","integer","text","regex","boolean"],"type":"string"},"userLabel":{"type":"string"},"regex":{"type":"string"}},"required":["label","type","regex"]},"CustomParamsConfigInputDto":{"type":"object","properties":{"params":{"type":"array","items":{"$ref":"#/components/schemas/ParamConfigInputDto"}}},"required":["params"]},"IntrospectTokenDto":{"type":"object","properties":{}},"CreateWorkspaceTokenDto":{"type":"object","properties":{}},"CreateAppTokenDto":{"type":"object","properties":{}},"PrepareUploadResponseDto":{"type":"object","properties":{"url":{"type":"string"},"fields":{"type":"object"}},"required":["url","fields"]},"CreateEventDto":{"type":"object","properties":{"appId":{"type":"string"},"eventName":{"type":"string"},"timestamp":{"type":"string"},"parameters":{"type":"object"},"ingestId":{"type":"string"},"ingestSource":{"type":"string"}},"required":["appId","eventName","timestamp","parameters"]},"QueryEventsDto":{"type":"object","properties":{"appId":{"type":"string"},"eventName":{"type":"string"},"filters":{"type":"object"},"groupBy":{"type":"string","enum":["hour","day","week","month","none"]},"sumField":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"currency":{"type":"string"},"limit":{"type":"number"}},"required":["appId","eventName","from","to"]},"FlagOutput":{"type":"object","properties":{}},"FlagInput":{"type":"object","properties":{}},"SegmentOutput":{"type":"object","properties":{}},"SegmentInput":{"type":"object","properties":{}},"OnboardingSignalState":{"type":"object","properties":{"detected":{"type":"boolean","description":"True once the signal has been observed at least once for this app. Sticky — never flips back to false."},"lastSeenAt":{"type":"number","nullable":true,"description":"Most recent observation time in epoch milliseconds. Present when detected = true."},"count":{"type":"number","nullable":true,"description":"Total rows in the backing collection scoped to this app. Lets the UI render \"3 flags discovered\" / \"42 evals received\". Optional and signal-specific."}},"required":["detected"]},"OnboardingSignals":{"type":"object","properties":{"sdk_initialized":{"description":"True once the SDK has reported any liveness — either a recent flag_last_eval row or a recorded call-site for this app. Maps to \"✓ SDK pinged us\" in the wizard.","allOf":[{"$ref":"#/components/schemas/OnboardingSignalState"}]},"flag_discovered":{"description":"True once at least one flag has been auto-discovered via the discovery telemetry endpoint. `count` is the number of distinct discovered flag keys. Maps to \"✓ first flag discovered\" in the wizard.","allOf":[{"$ref":"#/components/schemas/OnboardingSignalState"}]},"eval_received":{"description":"True once any eval event has been ingested for this app. `count` is the total eval-events summed across all flags (from `flag_last_eval.totalEvals`). Maps to \"✓ first flag eval\" in the wizard.","allOf":[{"$ref":"#/components/schemas/OnboardingSignalState"}]},"attribute_seen":{"description":"True once at least one attribute key has been auto-discovered. `count` is the number of distinct discovered attribute keys. Maps to \"✓ attributes attached\" in the wizard.","allOf":[{"$ref":"#/components/schemas/OnboardingSignalState"}]},"flag_activated":{"description":"True once a flag has been toggled ON (state != off) AND re-evaluated since that toggle (an eval-rollup row whose server-side updatedAt is newer than the flag config's updatedAt). Proves the toggle propagated to the running app. Maps to the \"Turn it on\" onboarding step.","allOf":[{"$ref":"#/components/schemas/OnboardingSignalState"}]}},"required":["sdk_initialized","flag_discovered","eval_received","attribute_seen","flag_activated"]},"FlagOnboardingStatusDto":{"type":"object","properties":{"appId":{"type":"string","description":"The app this status snapshot belongs to."},"signals":{"description":"Per-signal detection state.","allOf":[{"$ref":"#/components/schemas/OnboardingSignals"}]}},"required":["appId","signals"]},"DiagnoseIntegrationRequestDto":{"type":"object","properties":{"env":{"type":"object","description":"The project's Bridge-related environment variables, name → value. Secret\nvariables (API keys, secrets) are checked for presence and placement only:\nsend any placeholder such as \"<set>\", never the real value."},"framework":{"type":"string","description":"The framework the project uses. Inferred from the variable names when omitted.","enum":["svelte","react","nextjs","angular","nestjs","express"]}},"required":["env"]},"CreateTestUserRequestDto":{"type":"object","properties":{"confirm":{"type":"string","description":"Required only when this Bridge environment is production or the app's\nStripe keys are live: the app's exact name, repeated as confirmation.","maxLength":200}}},"VerifyLoginRequestDto":{"type":"object","properties":{"email":{"type":"string","maxLength":320},"password":{"type":"string","description":"Used for this one sign-in and never stored, logged or returned.","maxLength":1000},"origin":{"type":"string","description":"The web origin to sign in from. Must be one of the app's allowed origins.\nDefaults to the app's UI URL when that is allowed, else the first allowed origin.","maxLength":500}},"required":["email","password"]},"BodyWithCtxAndToken":{"type":"object","properties":{}},"BrandingProps":{"type":"object","properties":{"bgColor":{"type":"string"},"fontFamily":{"type":"string"},"primaryButtonBgColor":{"type":"string"},"primaryButtonTextColor":{"type":"string"},"tertiaryButtonBgColor":{"type":"string"},"tertiaryButtonTextColor":{"type":"string"},"textColor":{"type":"string"},"linkColor":{"type":"string"},"borderRadius":{"type":"string"},"boxShadow":{"type":"string"}},"required":["bgColor","fontFamily","primaryButtonBgColor","primaryButtonTextColor","tertiaryButtonBgColor","tertiaryButtonTextColor","textColor","linkColor","borderRadius","boxShadow"]},"BrandingOutput":{"type":"object","properties":{"defaultValues":{"$ref":"#/components/schemas/BrandingProps"},"customCss":{"type":"boolean"},"bgColor":{"type":"string"},"fontFamily":{"type":"string"},"primaryButtonBgColor":{"type":"string"},"primaryButtonTextColor":{"type":"string"},"tertiaryButtonBgColor":{"type":"string"},"tertiaryButtonTextColor":{"type":"string"},"textColor":{"type":"string"},"linkColor":{"type":"string"},"borderRadius":{"type":"string"},"boxShadow":{"type":"string"}},"required":["defaultValues","customCss","bgColor","fontFamily","primaryButtonBgColor","primaryButtonTextColor","tertiaryButtonBgColor","tertiaryButtonTextColor","textColor","linkColor","borderRadius","boxShadow"]},"UpdateBrandingRequestDto":{"type":"object","properties":{"bgColor":{"type":"string"},"fontFamily":{"type":"string"},"primaryButtonBgColor":{"type":"string"},"primaryButtonTextColor":{"type":"string"},"tertiaryButtonBgColor":{"type":"string"},"tertiaryButtonTextColor":{"type":"string"},"textColor":{"type":"string"},"linkColor":{"type":"string"},"borderRadius":{"type":"string"},"boxShadow":{"type":"string"}}}}}}