{"openapi":"3.0.0","paths":{"/api/notifications/push/public-key":{"get":{"operationId":"NotificationsController_pushPublicKey","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the tenant VAPID public key for Web Push","tags":["Notifications"],"x-required-scope":["notifications:read"]}},"/api/notifications/push/subscribe":{"post":{"operationId":"NotificationsController_pushSubscribe","parameters":[{"name":"user-agent","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushSubscribeDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Register a browser Web Push subscription","tags":["Notifications"],"x-required-scope":["notifications:write"]}},"/api/notifications/push/unsubscribe":{"post":{"operationId":"NotificationsController_pushUnsubscribe","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushUnsubscribeDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove a browser Web Push subscription","tags":["Notifications"],"x-required-scope":["notifications:write"]}},"/api/notifications":{"get":{"operationId":"NotificationsController_findAll","parameters":[{"name":"dismissed","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List notifications for the current user","tags":["Notifications"]}},"/api/notifications/unread-count":{"get":{"operationId":"NotificationsController_unreadCount","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the unread notifications badge count","tags":["Notifications"],"x-required-scope":["notifications:read"]}},"/api/notifications/read-all":{"post":{"operationId":"NotificationsController_readAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Mark all unread notifications as read","tags":["Notifications"],"x-required-scope":["notifications:write"]}},"/api/notifications/{id}/read":{"post":{"operationId":"NotificationsController_markRead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Mark a notification as read","tags":["Notifications"]}},"/api/notifications/{id}/dismiss":{"post":{"operationId":"NotificationsController_dismiss","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Dismiss a notification (hide from widget)","tags":["Notifications"]}},"/api/notifications/dismiss-all":{"post":{"operationId":"NotificationsController_dismissAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Dismiss all notifications for the current user","tags":["Notifications"],"x-required-scope":["notifications:write"]}},"/api/notifications/self-note":{"post":{"operationId":"NotificationsController_createSelfNote","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSelfNoteDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create an agent self-note notification","tags":["Notifications"],"x-required-scope":["notifications:write"]}},"/api/auth/register":{"post":{"operationId":"AuthController_register","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Register a new account (self-service). Requires termsAccepted=true (user agreement: GET /api/legal/terms). channel=web needs a password; channel=mcp/a2a/form (bootstrap from an AI agent) makes the password optional and returns the key as flat api_key/scope/quota fields (agent signup is rate-limited per IP). Creates User+Tenant with status=PENDING and emails a confirmation link (valid 48h) to the address. After the email is confirmed the account auto-activates — at most 1 auto-activation per hour platform-wide; beyond that it stays PENDING until admin approval (the admin is notified by email at every step). Self-signup workspaces have a 50MB database quota: over quota, POST/PUT/PATCH return 403 while reads and DELETE keep working. The auto-issued ldm_* key has SAFE_AGENT_SCOPES (read-all + safe drafts; no email:send / mailing:write) — mint a wider key in Settings → API Keys after activation.","tags":["Authentication"]}},"/api/auth/verify-email":{"get":{"operationId":"AuthController_verifyEmail","parameters":[{"name":"token","required":true,"in":"query","schema":{"type":"string"}},{"name":"format","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Confirm email by the token from the signup email. Activates the account automatically (1 auto-activation per hour platform-wide; otherwise it stays PENDING for admin approval). Browsers are redirected to the login page with the result; API clients get JSON when ?format=json.","tags":["Authentication"]}},"/api/auth/signup-questionnaire":{"post":{"operationId":"AuthController_submitQuestionnaire","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupQuestionnaireDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Issue #322 — submit the signup questionnaire for accounts that did not qualify for automatic activation (free mailbox, or the website/MX checks did not line up). Authenticated by the signup_token from the verify-email redirect, not by an API key — the key issued at /auth/register stays inert until the account is ACTIVE. Calling this endpoint runs the automatic checks immediately (does the company domain resolve, does it answer over HTTP, does it match the contact mailbox) and saves the answers plus those results on the tenant record; it does NOT activate the account itself. The admin is emailed and approves the workspace as a separate, manual step (#1189: no ETA endpoint for that step). Until approval the account stays PENDING (read-only, cannot send email). Re-submitting overwrites the previous answers.","tags":["Authentication"]}},"/api/auth/otc":{"post":{"operationId":"AuthController_exchangeOtc","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Exchange the one-time sign-in code from the email-verification redirect for a session (same response as /auth/login). Codes are single-use and expire in 5 minutes.","tags":["Authentication"]}},"/api/auth/login":{"post":{"operationId":"AuthController_login","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Authenticate a user and issue access + refresh tokens. 401 = wrong email/password; 403 = credentials are correct but the account is not ACTIVE yet (email not confirmed / awaiting admin approval / blocked) — the error message says which.","tags":["Authentication"]}},"/api/auth/refresh":{"post":{"operationId":"AuthController_refresh","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Exchange a refresh token for a new access + refresh pair","tags":["Authentication"]}},"/api/auth/logout":{"post":{"operationId":"AuthController_logout","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Revoke a refresh token and end the session","tags":["Authentication"]}},"/api/auth/forgot-password":{"post":{"operationId":"AuthController_forgotPassword","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Request a password reset email (rate-limited per email and per IP)","tags":["Authentication"]}},"/api/auth/reset-password":{"post":{"operationId":"AuthController_resetPassword","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset password using a reset token","tags":["Authentication"]}},"/api/auth/profile":{"get":{"operationId":"AuthController_getProfile","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the current authenticated user profile","tags":["Authentication"]}},"/api/auth/me":{"get":{"operationId":"AuthController_getMe","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get current user profile (alias of /auth/profile)","tags":["Authentication"]}},"/api/auth/change-password":{"post":{"operationId":"AuthController_changePassword","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Change the password of the authenticated user (current required)","tags":["Authentication"]}},"/api/auth/impersonate/{userId}":{"post":{"operationId":"AuthController_impersonate","parameters":[{"name":"userId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Impersonate another user (SUPER role only)","tags":["Authentication"]}},"/api/api-keys":{"get":{"operationId":"ApiKeysController_list","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List tenant API keys (raw key value hidden)","tags":["API Keys (tenant-scoped)"]},"post":{"operationId":"ApiKeysController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new tenant API key. Pass `actAsCurrentUser: true` to bind the key to the calling user (required for compose/reply/forward and other user-context endpoints; sets `ownerUserId`). Optional `scopes` array gates which surfaces the key can hit; default `[\"*\"]`.","tags":["API Keys (tenant-scoped)"]}},"/api/api-keys/whoami":{"get":{"operationId":"ApiKeysController_whoami","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check that the current Bearer credentials (API key or JWT) are valid, and learn where this key is connected before hitting a wall. No scope required — any authenticated caller passes. Used by the MCP gateway to reject bad keys before building an MCP session, instead of after the first tool call. Beyond the original `{ ok, tenantId, scopes, authMode }`, also returns `baseUrl` (scheme+host the request actually arrived on, honoring x-forwarded-proto/x-forwarded-host behind the nginx edge), `apiPrefix` (the mandatory path prefix, taken from the same constant main.ts uses for setGlobalPrefix), and `closedCapabilityClasses` (LEGACY_CAPABILITIES id-prefix groups where NOT ONE operation is reachable with this key's granted scopes).","tags":["API Keys (tenant-scoped)"]}},"/api/api-keys/{id}/reveal":{"get":{"operationId":"ApiKeysController_reveal","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reveal the raw value of an existing API key. Only JWT-authenticated (browser) calls are allowed — an ApiKey cannot read another key's secret. Returns { id, name, key }.","tags":["API Keys (tenant-scoped)"]}},"/api/api-keys/scopes/structured":{"get":{"operationId":"ApiKeysController_structuredScopes","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Structured scope catalog for the API Keys UI wizard. Returns presets (AI Agent / Read-only) + grouped scope definitions with descriptions and dangerous-flag. Used by Settings → API Keys to render the scope picker.","tags":["API Keys (tenant-scoped)"],"x-required-scope":["keys:read"]}},"/api/api-keys/{id}":{"patch":{"operationId":"ApiKeysController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Upgrade an existing API key in-place: set/unset Act-as-me. Only JWT-authenticated calls are allowed (an ApiKey cannot upgrade another ApiKey). Key value is NOT changed — downstream clients keep working without re-configuration.","tags":["API Keys (tenant-scoped)"]},"delete":{"operationId":"ApiKeysController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Permanently delete a tenant API key","tags":["API Keys (tenant-scoped)"]}},"/api/api-keys/{id}/revoke":{"delete":{"operationId":"ApiKeysController_revoke","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Revoke (deactivate) a tenant API key without deleting it","tags":["API Keys (tenant-scoped)"]}},"/api/webhooks":{"get":{"operationId":"WebhooksController_list","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List webhook endpoints","tags":["Webhooks"]},"post":{"operationId":"WebhooksController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a webhook endpoint","tags":["Webhooks"]}},"/api/webhooks/{id}":{"patch":{"operationId":"WebhooksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a webhook endpoint","tags":["Webhooks"]},"delete":{"operationId":"WebhooksController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a webhook endpoint","tags":["Webhooks"]}},"/api/webhooks/{id}/deliveries":{"get":{"operationId":"WebhooksController_deliveries","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List delivery history for a webhook endpoint","tags":["Webhooks"]}},"/api/webhooks/deliveries/{id}/retry":{"post":{"operationId":"WebhooksController_retry","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Retry a single webhook delivery","tags":["Webhooks"]}},"/api/webhooks/{id}/retrigger":{"post":{"operationId":"WebhooksController_retrigger","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Retrigger the last N deliveries for a webhook endpoint","tags":["Webhooks"]}},"/api/users/me/accept-terms":{"post":{"operationId":"UsersController_acceptTerms","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Accept legal terms for the current user","tags":["Users"],"x-required-scope":["users:write"]}},"/api/users":{"get":{"operationId":"UsersController_findAll","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"number"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List users (SUPER/MANAGER)","tags":["Users"]},"post":{"operationId":"UsersController_createUser","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a user (SUPER only)","tags":["Users"]}},"/api/users/system/stats":{"get":{"operationId":"UsersController_systemStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get system stats (SUPER only)","tags":["Users"],"x-required-scope":["users:read"]}},"/api/users/system/kill-process/{pid}":{"post":{"operationId":"UsersController_killProcess","parameters":[{"name":"pid","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Kill a system process by pid (SUPER only)","tags":["Users"]}},"/api/users/system/cleanup-orphans":{"post":{"operationId":"UsersController_cleanupOrphans","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Cleanup orphan system resources (SUPER only)","tags":["Users"],"x-required-scope":["users:write"]}},"/api/users/{id}":{"get":{"operationId":"UsersController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a user by id (SUPER/MANAGER)","tags":["Users"]},"delete":{"operationId":"UsersController_deleteUser","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a user with tenant cleanup: sole-member tenants + their DBs are dropped (SUPER only)","tags":["Users"]}},"/api/users/{id}/role":{"patch":{"operationId":"UsersController_updateRole","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRoleDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a user role (SUPER/MANAGER)","tags":["Users"]}},"/api/users/{id}/status":{"patch":{"operationId":"UsersController_updateStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStatusDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a user status (SUPER/MANAGER)","tags":["Users"]}},"/api/users/{id}/password":{"patch":{"operationId":"UsersController_updatePassword","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePasswordDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a user password (SUPER only)","tags":["Users"]}},"/api/users/{id}/profile":{"patch":{"operationId":"UsersController_updateProfile","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProfileDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a user profile (SUPER only)","tags":["Users"]}},"/api/users/{id}/comments":{"get":{"operationId":"UsersController_listComments","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List admin comments on a user (SUPER/MANAGER)","tags":["Users"]},"post":{"operationId":"UsersController_addComment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCommentDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add an admin comment on a user (SUPER/MANAGER)","tags":["Users"]}},"/api/users/{id}/comments/{commentId}":{"delete":{"operationId":"UsersController_deleteComment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"commentId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an admin comment on a user (SUPER only)","tags":["Users"]}},"/api/companies/custom-fields":{"get":{"operationId":"CompanyCustomFieldController_getDefinitions","parameters":[{"name":"entity","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List custom field definitions for the given entity (company/contact/lead)","tags":["Companies / Custom Fields"]},"post":{"operationId":"CompanyCustomFieldController_createDefinition","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomFieldDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a custom field definition","tags":["Companies / Custom Fields"]}},"/api/companies/custom-fields/reorder":{"put":{"operationId":"CompanyCustomFieldController_reorder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder custom field definitions by id array","tags":["Companies / Custom Fields"],"x-required-scope":["crm:write"]}},"/api/companies/custom-fields/{companyId}/values":{"get":{"operationId":"CompanyCustomFieldController_getValues","parameters":[{"name":"companyId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get custom field values for a company","tags":["Companies / Custom Fields"]},"post":{"operationId":"CompanyCustomFieldController_setValues","parameters":[{"name":"companyId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetValuesDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Set custom field values for a company","tags":["Companies / Custom Fields"]}},"/api/companies/custom-fields/{id}":{"put":{"operationId":"CompanyCustomFieldController_updateDefinition","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomFieldDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a custom field definition","tags":["Companies / Custom Fields"]},"delete":{"operationId":"CompanyCustomFieldController_deleteDefinition","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"confirm","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a custom field definition (requires confirm=true)","tags":["Companies / Custom Fields"]}},"/api/companies/duplicates/fields":{"get":{"operationId":"DuplicatesController_getFields","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List fields available for duplicate-scan matching","tags":["Companies / Duplicates"],"x-required-scope":["crm:read"]}},"/api/companies/duplicates/scan":{"post":{"operationId":"DuplicatesController_scan","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Scan companies for duplicates by configured fields","tags":["Companies / Duplicates"],"x-required-scope":["crm:read"]}},"/api/companies/duplicates/merge":{"post":{"operationId":"DuplicatesController_merge","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Merge duplicate company records","tags":["Companies / Duplicates"],"x-required-scope":["crm:write"]}},"/api/companies/duplicates/delete":{"post":{"operationId":"DuplicatesController_deleteDuplicates","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete duplicate company records identified by scan","tags":["Companies / Duplicates"],"x-required-scope":["crm:write"]}},"/api/companies/duplicates/move-to-list":{"post":{"operationId":"DuplicatesController_moveToList","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Move duplicate companies into a target list","tags":["Companies / Duplicates"],"x-required-scope":["crm:write"]}},"/api/companies/stats":{"get":{"operationId":"CompaniesController_getStats","parameters":[{"name":"listId","required":false,"in":"query","description":"Restrict stats to a single list","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get company statistics, optionally scoped to a list","tags":["Companies"],"x-required-scope":["crm:read"]}},"/api/companies":{"get":{"operationId":"CompaniesController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"1-based page number","schema":{"example":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (default 25)","schema":{"example":25,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Full-text search across name/domain/description","schema":{"type":"string"}},{"name":"listId","required":false,"in":"query","description":"Filter to companies in this list","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Sort column (e.g. createdAt, name)","schema":{"type":"string"}},{"name":"sortDir","required":false,"in":"query","description":"Sort direction","schema":{"enum":["asc","desc"],"type":"string"}},{"name":"sort","required":false,"in":"query","description":"Combined sort token (alternative to sortBy/sortDir)","schema":{"type":"string"}},{"name":"quickFilter","required":false,"in":"query","description":"Named quick-filter preset","schema":{"type":"string"}},{"name":"filters","required":false,"in":"query","description":"JSON-stringified array of advanced filter rules","schema":{"type":"string"}},{"name":"includeDeleted","required":true,"in":"query","schema":{"type":"string"}},{"name":"onlyDeleted","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Cap the number of rows returned (overrides pageSize when set)","schema":{"type":"number"}},{"name":"ids","required":false,"in":"query","description":"Restrict to these company ids (repeat the param or send an array)","schema":{"type":"array","items":{"type":"string"}}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List companies with pagination, search, and filters","tags":["Companies"]},"post":{"operationId":"CompaniesController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCompanyDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new company. Note: `email` is NOT a Company field — emails live on linked contacts as Channels. Use POST /api/contacts to create the contact, then POST /api/contacts/:id/channels { type: \"EMAIL\", value } to attach an email channel. Passing `email` in this body returns 400.","tags":["Companies"]}},"/api/companies/duplicates":{"get":{"operationId":"CompaniesController_findDuplicates","parameters":[{"name":"page","required":false,"in":"query","description":"1-based page number","schema":{"example":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Groups per page (default 100, max 500)","schema":{"example":100,"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Find duplicate companies in the workspace. Groups are ordered by reliability: same_inn (strong) first, then same_domain (strong), then same_name (weak — different legal entities share names). Paginated: page (1-based), pageSize (default 100, max 500); `total` is the FULL number of groups, not the page length.","tags":["Companies"],"x-required-scope":["crm:read"]}},"/api/companies/{id}":{"get":{"operationId":"CompaniesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single company by ID","tags":["Companies"]},"patch":{"operationId":"CompaniesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCompanyDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an existing company","tags":["Companies"]},"delete":{"operationId":"CompaniesController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Soft-delete a company","tags":["Companies"]}},"/api/companies/{id}/timeline":{"get":{"operationId":"CompaniesController_getTimeline","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"1-based page number","schema":{"example":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (default 20)","schema":{"example":20,"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a paginated timeline of events for a company","tags":["Companies"]}},"/api/companies/bulk":{"post":{"operationId":"CompaniesController_bulk","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompaniesBulkDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Enqueue a bulk action on multiple companies (async)","tags":["Companies"],"x-required-scope":["crm:write"]}},"/api/companies/bulk/{jobId}":{"get":{"operationId":"CompaniesController_getBulkStatus","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the status of a bulk company job","tags":["Companies"]},"delete":{"operationId":"CompaniesController_cancelBulk","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel an in-progress bulk company job","tags":["Companies"]}},"/api/companies/export/columns":{"get":{"operationId":"CompaniesController_getExportColumns","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List exportable column definitions for companies","tags":["Companies"],"x-required-scope":["crm:read"]}},"/api/companies/export":{"post":{"operationId":"CompaniesController_exportCompanies","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportCompaniesDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Export companies to a downloadable file","tags":["Companies"],"x-required-scope":["crm:write"]}},"/api/companies/merge":{"post":{"operationId":"CompaniesController_mergeCompanies","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergeCompaniesDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Merge multiple companies into one keeper record","tags":["Companies"],"x-required-scope":["crm:write"]}},"/api/companies/import/google-sheets":{"post":{"operationId":"CompaniesController_importFromGoogleSheets","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportFromGoogleSheetsDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Fetch rows from a Google Sheets URL for import. Returns { headers, rows, suggestedMapping, unmapped } (#1058): suggestedMapping proposes a column -> field guess (incl. cf:/customField: when a known export template recognises the header) with a sample value per column; unmapped lists columns nobody could confidently guess — do not invent a field for those, ask the operator.","tags":["Companies"],"x-required-scope":["crm:write"]}},"/api/companies/import/preview":{"post":{"operationId":"CompaniesController_importPreview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompaniesImportPreviewDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview a companies import with proposed mapping","tags":["Companies"],"x-required-scope":["crm:write"]}},"/api/companies/import/start":{"post":{"operationId":"CompaniesController_importStart","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompaniesImportStartDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Start a companies import. Body: { rows: object[], mapping: {csvColumn -> field}, options }. Mappable fields: name (required), domain, inn, industry, size, country, city, address, state, phone, website, description, source, custom fields cf: → company.customFields. Deduplication is by DOMAIN or INN only (never by name — different legal entities share names): options.dedupeBy = \"auto\" (default: INN first, then domain) | \"inn\" | \"domain\"; options.duplicateHandling = \"skip\" (default) | \"update\" | \"enrich\" | \"create\". \"enrich\" (#1057) fills only EMPTY fields of the matched duplicate, never overwrites non-empty ones (customFields merge the same way). Also dedupes within the same batch. options.listId (#1057): adds EVERY row that matched a card — created, updated, or a found duplicate (skip/enrich) — to this list; must be an existing list id in this tenant or the call fails. Returns { batchId, created, updated, enriched, skipped, errors, total, createdIds, existingIds, listId }; roll back with DELETE /import/rollback/{batchId}.","tags":["Companies"],"x-required-scope":["crm:write"]}},"/api/companies/import/combined":{"post":{"operationId":"CompaniesController_importCombined","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompaniesImportCombinedDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Combined companies + contacts import. mapping fields: company (name, domain, inn, industry, size, country, city, address, state, phone, website, source), custom fields cf: → company.customFields (e.g. cf:Revenue, cf:CEO, cf:IndustryCode), contact c:firstName/c:lastName/c:email/c:phone/c:position/c:personalEmail/c:linkedin. Company dedup by DOMAIN/INN only (options.dedupeBy=auto|inn|domain). If c:email present without c:firstName → a generic company contact is created (options.genericContactName, default \"Generic contact\"). options.listId adds companies to a list. Returns {created,updated,skipped,errors,contactsCreated,createdIds,listId}.","tags":["Companies"],"x-required-scope":["crm:write"]}},"/api/companies/{id}/restore":{"post":{"operationId":"CompaniesController_restore","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Restore a soft-deleted company","tags":["Companies"]}},"/api/companies/{id}/purge":{"delete":{"operationId":"CompaniesController_purge","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"PERMANENTLY delete a trashed company (requires isDeleted). Irreversible.","tags":["Companies"]}},"/api/companies/import/rollback/{batchId}":{"delete":{"operationId":"CompaniesController_rollbackImport","parameters":[{"name":"batchId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Roll back a company import batch by ID","tags":["Companies"]}},"/api/companies/{id}/freeze":{"patch":{"operationId":"CompaniesController_freeze","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Freeze a company (set status FROZEN). Blocks campaign sending (#369)","tags":["Companies"]}},"/api/companies/{id}/unfreeze":{"patch":{"operationId":"CompaniesController_unfreeze","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Unfreeze a company (set status ACTIVE). Does NOT resume already-skipped rows (#369)","tags":["Companies"]}},"/api/rpa/v1/readiness":{"get":{"operationId":"RpaOutboxController_queueReadiness","parameters":[{"name":"cursor","required":false,"in":"query","description":"Use pagination.nextCursor from the preceding target page","schema":{"maxLength":512,"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":5,"default":1,"type":"number"}},{"name":"campaignAfter","required":false,"in":"query","description":"Use campaigns.nextCampaignAfter, keeping the same target cursor","schema":{"maxLength":128,"type":"string"}},{"name":"campaignLimit","required":false,"in":"query","schema":{"minimum":1,"maximum":20,"default":5,"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Read scoped queue and campaign metadata without claiming, preparing or authorizing sending; follow pagination for a complete snapshot","tags":["RPA service protocol"]}},"/api/rpa/v1/heartbeat":{"post":{"operationId":"RpaOutboxController_heartbeat","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaHeartbeatDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Service heartbeat; include the complete task lease identity to extend a live CLAIMED/STARTED/CONTROL_REPORTED/REAL_READY task by 60 minutes. Stop at the last acknowledged expiresAt.","tags":["RPA service protocol"]}},"/api/rpa/v1/claim":{"post":{"description":"Full tasks include context: durable businessTask UUID and dialog/history links, frozen-render creative/brief references and explicitly mutable source bindings. Links target current CRM resources and require an owner session. Unavailable metadata is explicit. context is not an envelope, send permission, or report input; signed taskId remains the protocol identity.","operationId":"RpaOutboxController_claim","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaWorkerDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Poll preparation: task:null while validating; placement-gated tasks begin CONTROL-only and receive REAL only after server evidence. Deduplicate by idempotencyKey.","tags":["RPA service protocol"]}},"/api/rpa/v1/start":{"post":{"description":"Includes compact businessTask owner-navigation references, not a second envelope. Read full context from current/refresh; never replace signed taskId with businessTask.id.","operationId":"RpaOutboxController_start","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaLeaseDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Revalidate canonical send gates for the claimed operationId; send only when sendEnabled=true. CONTROL and REAL use different operation idempotency keys on the same task.","tags":["RPA service protocol"]}},"/api/rpa/v1/current":{"post":{"description":"Includes the same context contract as claim. Frozen identities are tied to render.fingerprint/renderLeaseId; current names/URLs are not the frozen content. Metadata does not grant CRM access or permission to send.","operationId":"RpaOutboxController_current","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaLeaseDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Read the same task and lease after a CONTROL report or server placement poll; never creates a second claim.","tags":["RPA service protocol"]}},"/api/rpa/v1/renew":{"post":{"operationId":"RpaOutboxController_renew","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaLeaseDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Extend this worker’s live CLAIMED/STARTED/CONTROL_REPORTED/REAL_READY lease by 60 minutes; never revive an expired or terminal task","tags":["RPA service protocol"]}},"/api/rpa/v1/refresh":{"post":{"description":"Refreshes context/current-resource availability without substituting live campaign creatives or briefs for the matching frozen render. Does not extend the lease.","operationId":"RpaOutboxController_refresh","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaLeaseDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Refresh HTTPS attachment links and scoped relay context without changing canonical envelope bytes","tags":["RPA service protocol"]}},"/api/rpa/v1/report":{"post":{"description":"Acknowledgements include compact businessTask references only, never context in the receipt hash. A historical duplicate links its own archived execution/dialog or reports that link unavailable; it does not describe a new child. accepted is receipt acceptance, not proof of final accounting or recipient inbox delivery.","operationId":"RpaOutboxController_report","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaReportRequestDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Report one immutable CONTROL or REAL operation. Gated tasks must echo operationId, taskVersion and contentFingerprint; legacy three-field reports remain for one-step tasks.","tags":["RPA service protocol"]}},"/api/rpa/v1/profile-release":{"post":{"operationId":"RpaOutboxController_releaseProfile","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaProfileReleaseDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Optional terminal-task browser-close acknowledgement. CONTROL/placement/REAL continuation never releases the profile. Without this acknowledgement legacy reports remain valid and ownership lasts until the last issued expiresAt. Not permission to resend.","tags":["RPA service protocol"]}},"/api/rpa/v1/return":{"post":{"operationId":"RpaOutboxController_returnTask","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaReturnDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Return an execution known not to have sent. Keeps the same task, retries through canonical gates within its attempt budget.","tags":["RPA service protocol"]}},"/api/rpa/v1/reconciliation":{"post":{"operationId":"RpaOutboxController_reconciliation","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaReconciliationListDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Read this worker’s unresolved tasks, up to 20 per authorized target. Never permission to resend. Resolve items then read again.","tags":["RPA service protocol"]}},"/api/rpa/v1/reconcile":{"post":{"operationId":"RpaOutboxController_reconcile","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaReconcileDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Resolve an uncertain execution using positive sent evidence or retained executor proof of no send. Not a blind retry or a lease renewal.","tags":["RPA service protocol"]}},"/api/rpa/v1/error":{"post":{"operationId":"RpaOutboxController_error","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaExecutionErrorDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Report a deduplicated execution error; obey the returned action, never replay sending after an uncertain outcome","tags":["RPA service protocol"]}},"/api/rpa/v1/placement":{"post":{"operationId":"RpaOutboxController_placement","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaPlacementDto"}}}},"responses":{"201":{"description":""}},"security":[{"rpa-service":[]}],"summary":"Attach late seed-copy placement evidence; never evidence of recipient inbox placement","tags":["RPA service protocol"]}},"/api/rpa/v1/attachments/{token}/{filename}":{"get":{"operationId":"RpaOutboxAttachmentController_download[0]","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Download a lease-bound signed attachment with its original filename; legacy token-only URLs remain supported","tags":["RPA service protocol"]}},"/api/rpa/v1/attachments/{token}":{"get":{"operationId":"RpaOutboxAttachmentController_download[1]","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Download a lease-bound signed attachment with its original filename; legacy token-only URLs remain supported","tags":["RPA service protocol"]}},"/api/suppression":{"get":{"operationId":"SuppressionController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"reason","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List suppressed emails","tags":["Suppression"]},"post":{"operationId":"SuppressionController_add","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add an email to the suppression list","tags":["Suppression"]}},"/api/suppression/bulk":{"post":{"operationId":"SuppressionController_addBulk","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Bulk-add emails to the suppression list","tags":["Suppression"],"x-required-scope":["suppression:write"]}},"/api/suppression/check":{"post":{"operationId":"SuppressionController_check","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckEmailsDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check a batch of emails against the suppression list","tags":["Suppression"],"x-required-scope":["suppression:read"]}},"/api/suppression/{email}":{"delete":{"operationId":"SuppressionController_remove","parameters":[{"name":"email","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove an email from the suppression list","tags":["Suppression"]}},"/api/suppression/domains":{"get":{"operationId":"SuppressionController_listDomains","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List suppressed domains","tags":["Suppression"],"x-required-scope":["suppression:read"]},"post":{"operationId":"SuppressionController_addDomain","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a domain to the suppression list","tags":["Suppression"],"x-required-scope":["suppression:write"]}},"/api/suppression/domains/{domain}":{"delete":{"operationId":"SuppressionController_removeDomain","parameters":[{"name":"domain","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove a domain from the suppression list","tags":["Suppression"]}},"/api/stop-lists":{"get":{"operationId":"StopListController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List stop list entries (user scope)","tags":["Stop List"]},"post":{"operationId":"StopListController_add","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a stop list entry (user scope)","tags":["Stop List"]}},"/api/stop-lists/stats":{"get":{"operationId":"StopListController_stats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get stop list statistics (user scope)","tags":["Stop List"],"x-required-scope":["stoplist:read"]}},"/api/stop-lists/bulk":{"post":{"operationId":"StopListController_addBulk","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Bulk-add stop list entries (user scope)","tags":["Stop List"],"x-required-scope":["stoplist:write"]}},"/api/stop-lists/{id}":{"delete":{"operationId":"StopListController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove a stop list entry (user scope)","tags":["Stop List"]}},"/api/stop-lists/check":{"post":{"operationId":"StopListController_check","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckEmailsDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check a batch of emails against the stop list","tags":["Stop List"],"x-required-scope":["stoplist:read"]}},"/api/stop-lists/global":{"get":{"operationId":"StopListController_globalList","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List global stop list entries (SUPER only)","tags":["Stop List"],"x-required-scope":["stoplist:read"]},"post":{"operationId":"StopListController_globalAdd","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a global stop list entry (SUPER only)","tags":["Stop List"],"x-required-scope":["stoplist:write"]}},"/api/stop-lists/global/stats":{"get":{"operationId":"StopListController_globalStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get global stop list statistics (SUPER only)","tags":["Stop List"],"x-required-scope":["stoplist:read"]}},"/api/stop-lists/global/bulk":{"post":{"operationId":"StopListController_globalAddBulk","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Bulk-add global stop list entries (SUPER only)","tags":["Stop List"],"x-required-scope":["stoplist:write"]}},"/api/stop-lists/global/{id}":{"delete":{"operationId":"StopListController_globalRemove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove a global stop list entry (SUPER only)","tags":["Stop List"]}},"/api/reports":{"get":{"operationId":"ReportsController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"source","required":true,"in":"query","schema":{"type":"string"}},{"name":"q","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List tenant reports (paginated) + storage quota","tags":["Reports"]},"post":{"description":"JSON path for agents: pass fileName + contentBase64. description is REQUIRED — explain what is inside the file and where the data came from. Decoded size limit = REPORTS_MAX_FILE_BASE64_MB (default 30 MB).","operationId":"ReportsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReportDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a report from base64 content (agent/MCP path)","tags":["Reports"]}},"/api/reports/limits":{"get":{"operationId":"ReportsController_limits","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reports storage limits and current usage","tags":["Reports"],"x-required-scope":["reports:read"]}},"/api/reports/upload":{"post":{"operationId":"ReportsController_upload","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file","title","description"],"properties":{"file":{"type":"string","format":"binary"},"title":{"type":"string"},"description":{"type":"string"}}}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Upload a report file (multipart, UI path)","tags":["Reports"],"x-required-scope":["reports:write"]}},"/api/reports/from-export/{exportJobId}":{"post":{"description":"Moves the export file into reports storage and keeps /exports/:id/download working (file_path is updated).","operationId":"ReportsController_fromExport","parameters":[{"name":"exportJobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FromExportDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Register a completed export job as a report (idempotent)","tags":["Reports"]}},"/api/reports/{id}":{"get":{"operationId":"ReportsController_getOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get one report","tags":["Reports"]},"patch":{"operationId":"ReportsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReportDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update report title/description","tags":["Reports"]},"delete":{"operationId":"ReportsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a report (file + record)","tags":["Reports"]}},"/api/reports/{id}/publish":{"post":{"description":"DANGER: the link is downloadable by ANYONE on the internet. For source=EXPORT this is personal data — double-check before publishing. Returns publicUrl. Re-publish returns the SAME url (rotate-token to invalidate).","operationId":"ReportsController_publish","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Publish: open a direct public download link (no auth!)","tags":["Reports"]}},"/api/reports/{id}/unpublish":{"post":{"operationId":"ReportsController_unpublish","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Unpublish: close the public link (token kept — re-publish restores the same url)","tags":["Reports"]}},"/api/reports/{id}/rotate-token":{"post":{"operationId":"ReportsController_rotateToken","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Rotate the public token — old link dies immediately","tags":["Reports"]}},"/api/reports/{id}/download":{"get":{"operationId":"ReportsController_download","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download the report file (authorized)","tags":["Reports"]}},"/api/mail-agent/status":{"get":{"operationId":"MailAgentController_getStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the mail agent connection status and stats","tags":["Mail Agent"],"x-required-scope":["agent:read"]}},"/api/mail-agent/settings":{"get":{"operationId":"MailAgentController_getSettings","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get current mail agent settings","tags":["Mail Agent"],"x-required-scope":["agent:read"]},"post":{"operationId":"MailAgentController_toggleEnabled","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Toggle the mail agent enabled flag","tags":["Mail Agent"],"x-required-scope":["agent:write"]}},"/api/mail-agent/token/regenerate":{"post":{"operationId":"MailAgentController_regenerateToken","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Regenerate the mail agent auth token","tags":["Mail Agent"],"x-required-scope":["agent:write"]}},"/api/mail-agent/stats/reset":{"post":{"operationId":"MailAgentController_resetStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset mail agent statistics counters","tags":["Mail Agent"],"x-required-scope":["agent:write"]}},"/api/mail-agent/disconnect":{"post":{"operationId":"MailAgentController_disconnect","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Disconnect the mail agent session","tags":["Mail Agent"],"x-required-scope":["agent:write"]}},"/api/mail-agent/download/windows":{"get":{"operationId":"MailAgentController_downloadWindows","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download the Windows mail agent bundle with token pre-configured","tags":["Mail Agent"],"x-required-scope":["agent:write"]}},"/api/mail-agent/qr":{"get":{"operationId":"MailAgentController_getQr","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get an SVG QR code for pairing the Android mail agent","tags":["Mail Agent"],"x-required-scope":["agent:read"]}},"/api/mail-agent/update/check":{"get":{"operationId":"MailAgentUpdateController_check","parameters":[{"name":"platform","required":true,"in":"query","schema":{"type":"string"}},{"name":"current","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check for the latest mail agent version (public)","tags":["Mail Agent / Update"]}},"/api/ai/generate":{"post":{"operationId":"AiController_generate","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate AI completion via configured provider","tags":["AI"],"x-required-scope":["ai:generate"]}},"/api/ai/balance":{"get":{"operationId":"AiController_getBalance","parameters":[{"name":"provider","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get balance for current or specified AI provider","tags":["AI"],"x-required-scope":["ai:read"]}},"/api/ai/balances":{"get":{"operationId":"AiController_getAllBalances","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get balances for all configured AI providers","tags":["AI"],"x-required-scope":["ai:read"]}},"/api/ai/usage":{"get":{"operationId":"AiController_getUsage","parameters":[{"name":"days","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get AI usage statistics for the given window (days)","tags":["AI"],"x-required-scope":["ai:read"]}},"/api/ai/logs":{"get":{"operationId":"AiController_getLogs","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get recent AI usage logs","tags":["AI"],"x-required-scope":["ai:read"]}},"/api/ai/providers":{"get":{"operationId":"AiController_getProviders","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List available AI providers with status","tags":["AI"],"x-required-scope":["ai:read"]}},"/api/ai/models":{"get":{"operationId":"AiController_getModels","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List available AI models per provider (dynamic)","tags":["AI"],"x-required-scope":["ai:read"]}},"/api/ai/check-balance":{"post":{"operationId":"AiController_checkBalance","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Check AI balance against threshold (cron/monitoring hook)","tags":["AI"],"x-required-scope":["ai:write"]}},"/api/oauth/connect":{"get":{"operationId":"OAuthController_connectPage","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"tenant","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Public OAuth connect page for anti-detect browser flow","tags":["OAuth"]}},"/api/oauth/connect/{accountId}":{"get":{"operationId":"OAuthController_connectRedirect","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"tenant","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Public OAuth consent redirect for a specific account","tags":["OAuth"]}},"/api/oauth/auth-url/{accountId}":{"get":{"operationId":"OAuthController_getAuthUrl","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"provider","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the OAuth consent URL for an email account","tags":["OAuth"]}},"/api/oauth/callback":{"get":{"operationId":"OAuthController_callback","parameters":[{"name":"code","required":true,"in":"query","schema":{"type":"string"}},{"name":"state","required":true,"in":"query","schema":{"type":"string"}},{"name":"error","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"OAuth provider callback endpoint (public, used by provider redirect)","tags":["OAuth"]}},"/api/oauth/{accountId}/status":{"get":{"operationId":"OAuthController_getStatus","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get OAuth connection status for an account","tags":["OAuth"]}},"/api/oauth/{accountId}/revoke":{"post":{"operationId":"OAuthController_revoke","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Revoke OAuth tokens for an account","tags":["OAuth"]}},"/api/oauth/{accountId}/refresh":{"post":{"operationId":"OAuthController_refresh","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually refresh the OAuth access token for an account","tags":["OAuth"]}},"/api/creatives/{id}/rules":{"get":{"operationId":"CreativeRulesController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the creative rules document","tags":["Rules / Creative"]},"patch":{"operationId":"CreativeRulesController_patch","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Patch the creative rules document","tags":["Rules / Creative"]}},"/api/creatives/{id}/rules/schema":{"get":{"operationId":"CreativeRulesController_getSchema","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the JSON Schema for creative rules","tags":["Rules / Creative"]}},"/api/creatives/{id}/rules/context":{"get":{"operationId":"CreativeRulesController_context","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get supporting context used to evaluate creative rules","tags":["Rules / Creative"]}},"/api/creatives/{id}/rules/history":{"get":{"operationId":"CreativeRulesController_history","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get audit history of creative rule changes","tags":["Rules / Creative"]}},"/api/creatives/{id}/bootstrap":{"get":{"operationId":"CreativeBootstrapController_bootstrap","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get unified creative bootstrap snapshot for page render","tags":["Rules / Creative Bootstrap"]}},"/api/creatives/{id}/meta":{"patch":{"operationId":"CreativeBootstrapController_updateMeta","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update creative meta fields (non-rule)","tags":["Rules / Creative Bootstrap"]}},"/api/creatives/{id}/rules-sub":{"get":{"operationId":"SubResourceRulesController_listSubResources","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List available autopilot sub-resource keys","tags":["Rules / Sub-resource"]}},"/api/creatives/{id}/rules/{sub}":{"get":{"operationId":"SubResourceRulesController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"sub","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get an autopilot sub-resource rules document","tags":["Rules / Sub-resource"]},"patch":{"operationId":"SubResourceRulesController_patch","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"sub","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Patch an autopilot sub-resource rules document","tags":["Rules / Sub-resource"]}},"/api/creatives/{id}/rules/{sub}/schema":{"get":{"operationId":"SubResourceRulesController_getSchema","parameters":[{"name":"sub","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the JSON Schema for an autopilot sub-resource","tags":["Rules / Sub-resource"]}},"/api/creatives/{id}/rules/{sub}/history":{"get":{"operationId":"SubResourceRulesController_history","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"sub","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get audit history for an autopilot sub-resource","tags":["Rules / Sub-resource"]}},"/api/discovery":{"get":{"operationId":"DiscoveryController_discovery","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get agent discovery document with resources and endpoints","tags":["Rules / Discovery"]}},"/api/contract":{"get":{"operationId":"DiscoveryController_contract","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the agent contract version and core principles","tags":["Rules / Discovery"]}},"/api/nalog-id/lookup":{"post":{"operationId":"NalogIdController_lookup","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Look up Russian tax/company data (Nalog) by company info","tags":["Nalog ID"],"x-required-scope":["connectors:read"]}},"/api/nalog-id/test":{"get":{"operationId":"NalogIdController_test","parameters":[{"name":"q","required":true,"in":"query","schema":{"type":"string"}},{"name":"city","required":true,"in":"query","schema":{"type":"string"}},{"name":"domain","required":true,"in":"query","schema":{"type":"string"}},{"name":"debug","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Debug/test endpoint for Nalog lookup via query parameters","tags":["Nalog ID"],"x-required-scope":["connectors:read"]}},"/api/mail-transport/stats":{"get":{"operationId":"MailTransportController_stats","parameters":[{"name":"range","required":false,"in":"query","description":"Filter by `lastAttemptAt` within the last N period. Omit for all-time.","schema":{"enum":["24h","7d","30d"],"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Transport-usage breakdown from mail_outbox.sent_via. Useful for spotting unused or broken transports (e.g. relay=0 implies the option can be disabled).","tags":["Mail Transport"],"x-required-scope":["mailing:read"]}},"/api/verify":{"post":{"operationId":"EmailVerificationController_verifyOne","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyOneDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Verify a single email address synchronously","tags":["Email Verification"]}},"/api/verify/batch":{"post":{"operationId":"EmailVerificationController_verifyBatch","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyBatchDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Verify a batch of email addresses synchronously","tags":["Email Verification"],"x-required-scope":["email:send"]}},"/api/custom-fields":{"get":{"operationId":"CustomFieldsController_findAll","parameters":[{"name":"entity","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List custom field definitions, optionally filtered by entity","tags":["Custom Fields"]},"post":{"operationId":"CustomFieldsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDefinitionDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a custom field definition","tags":["Custom Fields"]}},"/api/custom-fields/inventory":{"get":{"operationId":"CustomFieldsController_inventory","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Read-only report: divergence between JSONB and table storage","tags":["Custom Fields"],"x-required-scope":["customfields:read"]}},"/api/custom-fields/{id}":{"patch":{"operationId":"CustomFieldsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDefinitionDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a custom field definition","tags":["Custom Fields"]},"delete":{"operationId":"CustomFieldsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a custom field definition","tags":["Custom Fields"]}},"/api/custom-fields/reorder":{"post":{"operationId":"CustomFieldsController_reorder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder custom field definitions","tags":["Custom Fields"],"x-required-scope":["customfields:write"]}},"/api/custom-fields/values/{entity}/{entityId}":{"get":{"operationId":"CustomFieldsController_getValues","parameters":[{"name":"entity","required":true,"in":"path","schema":{"type":"string"}},{"name":"entityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get all custom field values for an entity instance","tags":["Custom Fields"]},"post":{"operationId":"CustomFieldsController_setValue","parameters":[{"name":"entity","required":true,"in":"path","schema":{"type":"string"}},{"name":"entityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetValueDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Set a custom field value for an entity instance","tags":["Custom Fields"]}},"/api/custom-fields/params/{entity}/{entityId}":{"post":{"operationId":"CustomFieldsController_bulkSetParams","parameters":[{"name":"entity","required":true,"in":"path","schema":{"type":"string"}},{"name":"entityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Legacy bulk set of params as key-value pairs","tags":["Custom Fields"]},"get":{"operationId":"CustomFieldsController_getParams","parameters":[{"name":"entity","required":true,"in":"path","schema":{"type":"string"}},{"name":"entityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Legacy get of params as flat key-value object","tags":["Custom Fields"]}},"/api/contacts/stats":{"get":{"operationId":"ContactsController_getStats","parameters":[{"name":"listId","required":false,"in":"query","description":"Restrict stats to a single list","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get contact statistics, optionally scoped to a list","tags":["Contacts"],"x-required-scope":["crm:read"]}},"/api/contacts/duplicates":{"get":{"operationId":"ContactsController_findAllDuplicates","parameters":[{"name":"field","required":false,"in":"query","description":"Which field to detect duplicates by","schema":{"enum":["email","name","all"],"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Find duplicate contacts across the workspace","tags":["Contacts"],"x-required-scope":["crm:read"]}},"/api/contacts":{"get":{"operationId":"ContactsController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"1-based page number","schema":{"example":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (default 25)","schema":{"example":25,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Full-text search across name/position/channels","schema":{"type":"string"}},{"name":"companyId","required":false,"in":"query","description":"Filter to contacts of a single company","schema":{"type":"string"}},{"name":"listId","required":false,"in":"query","description":"Filter to contacts in a single list","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Sort column","schema":{"type":"string"}},{"name":"sortDir","required":false,"in":"query","description":"Sort direction","schema":{"enum":["asc","desc"],"type":"string"}},{"name":"sort","required":false,"in":"query","description":"Combined sort token (alternative to sortBy/sortDir)","schema":{"type":"string"}},{"name":"digProvider","required":false,"in":"query","description":"DIG: filter by MX provider (e.g. google, yandex)","schema":{"type":"string"}},{"name":"digDomainType","required":false,"in":"query","description":"DIG: filter by domain type","schema":{"type":"string"}},{"name":"digHasMx","required":false,"in":"query","description":"DIG: has MX records (true/false)","schema":{"type":"string"}},{"name":"digHasSpf","required":false,"in":"query","description":"DIG: has SPF record (true/false)","schema":{"type":"string"}},{"name":"digHasDmarc","required":false,"in":"query","description":"DIG: has DMARC record (true/false)","schema":{"type":"string"}},{"name":"digIsRoleBased","required":false,"in":"query","description":"DIG: role-based mailbox (true/false)","schema":{"type":"string"}},{"name":"digIsDisposable","required":false,"in":"query","description":"DIG: disposable address (true/false)","schema":{"type":"string"}},{"name":"digIsSuspicious","required":false,"in":"query","description":"DIG: suspicious heuristics (true/false)","schema":{"type":"string"}},{"name":"digAnalyzed","required":false,"in":"query","description":"DIG: enrichment completed (true/false)","schema":{"type":"string"}},{"name":"emailValidStatus","required":false,"in":"query","description":"Filter by email validation status","schema":{"type":"string"}},{"name":"taskId","required":false,"in":"query","description":"Filter to contacts attached to a task","schema":{"type":"string"}},{"name":"includeDeleted","required":true,"in":"query","schema":{"type":"string"}},{"name":"onlyDeleted","required":true,"in":"query","schema":{"type":"string"}},{"name":"filters","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List contacts with pagination, search, and filters","tags":["Contacts"]},"post":{"operationId":"ContactsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new contact. Note: `email`/`phone` are NOT direct Contact fields — they live as Channels. After creating the contact, attach the email/phone via POST /api/contacts/:id/channels { type: \"EMAIL\" | \"PHONE\", value }. Passing `email`/`phone` in this body returns 400.","tags":["Contacts"]}},"/api/contacts/{id}":{"get":{"operationId":"ContactsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single contact by ID","tags":["Contacts"]},"patch":{"operationId":"ContactsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an existing contact","tags":["Contacts"]},"delete":{"operationId":"ContactsController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Soft-delete a contact","tags":["Contacts"]}},"/api/contacts/{id}/timeline":{"get":{"operationId":"ContactsController_getTimeline","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"1-based page number","schema":{"example":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (default 20)","schema":{"example":20,"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a paginated timeline of events for a contact","tags":["Contacts"]}},"/api/contacts/bulk":{"post":{"operationId":"ContactsController_bulk","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactsBulkDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Bulk action on contacts (async, BullMQ). Pass either contactIds[] OR selectAll:true (the server resolves contacts by the search/emailValidStatus/dig* filter). Actions: delete | addTags | removeTags | addToList | removeFromList | updateField; the list target = the listId parameter. WARNING: for addToList the listId parameter serves BOTH as the target AND (with selectAll) as the source filter — so selectAll will NOT add \"everyone into a separate list\" (filtering by the target list returns that list's own members, 0 for an empty one). Flow for \"collect the whole base into a list for a mailing\": (1) list contactIds page by page (GET /contacts?hasEmail=true&page..) → addToList in batches (or contact-lists POST :id/contacts); (2) campaigns pour(listId). A contact in a list is a membership row, NOT a copy of the contact.","tags":["Contacts"],"x-required-scope":["crm:write"]}},"/api/contacts/bulk/{jobId}":{"get":{"operationId":"ContactsController_getBulkStatus","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the status of a bulk contact job","tags":["Contacts"]},"delete":{"operationId":"ContactsController_cancelBulk","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel an in-progress bulk contact job","tags":["Contacts"]}},"/api/contacts/export":{"post":{"operationId":"ContactsController_exportContacts","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportContactsDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Export contacts to a downloadable file","tags":["Contacts"],"x-required-scope":["crm:write"]}},"/api/contacts/import/preview":{"post":{"operationId":"ContactsController_importPreview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactsImportPreviewDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview a contacts import with proposed mapping","tags":["Contacts"],"x-required-scope":["crm:write"]}},"/api/contacts/import/start":{"post":{"operationId":"ContactsController_importStart","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactsImportStartDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Start a contacts import job","tags":["Contacts"],"x-required-scope":["crm:write"]}},"/api/contacts/{id}/restore":{"post":{"operationId":"ContactsController_restore","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Restore a soft-deleted contact","tags":["Contacts"]}},"/api/contacts/{id}/purge":{"delete":{"operationId":"ContactsController_purge","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"PERMANENTLY delete a trashed contact (requires isDeleted). Irreversible.","tags":["Contacts"]}},"/api/contacts/merge":{"post":{"operationId":"ContactsController_mergeContacts","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergeContactsDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Merge multiple contacts into one keeper record","tags":["Contacts"],"x-required-scope":["crm:write"]}},"/api/contacts/{id}/dig":{"post":{"operationId":"ContactsController_triggerDig","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually trigger DIG email enrichment for a contact","tags":["Contacts"]}},"/api/contacts/{id}/duplicates":{"get":{"operationId":"ContactsController_checkDuplicates","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check for duplicates of a specific contact","tags":["Contacts"]}},"/api/contacts/{id}/channels":{"post":{"operationId":"ContactsController_addChannel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddChannelDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a communication channel to a contact","tags":["Contacts"]}},"/api/contacts/{contactId}/channels/{channelId}":{"patch":{"operationId":"ContactsController_updateChannel","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}},{"name":"channelId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateChannelDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a contact channel","tags":["Contacts"]},"delete":{"operationId":"ContactsController_deleteChannel","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}},{"name":"channelId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a contact channel","tags":["Contacts"]}},"/api/contacts/import/rollback/{batchId}":{"delete":{"operationId":"ContactsController_rollbackImport","parameters":[{"name":"batchId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Roll back a contact import batch by ID","tags":["Contacts"]}},"/api/contacts/duplicates/by-email":{"get":{"operationId":"ContactsController_findDuplicates","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Find contacts that share duplicate email addresses","tags":["Contacts"],"x-required-scope":["crm:read"]}},"/api/pipelines":{"get":{"operationId":"PipelinesController_findAll","parameters":[{"name":"includeHidden","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all pipelines","tags":["Pipelines"]},"post":{"operationId":"PipelinesController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePipelineDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new pipeline","tags":["Pipelines"]}},"/api/pipelines/automation-logs":{"get":{"operationId":"PipelinesController_getAllAutomationLogs","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"leadId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get global automation logs across pipelines","tags":["Pipelines"],"x-required-scope":["pipelines:read"]}},"/api/pipelines/{id}":{"get":{"operationId":"PipelinesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single pipeline by ID","tags":["Pipelines"]},"patch":{"operationId":"PipelinesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePipelineDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an existing pipeline","tags":["Pipelines"]},"delete":{"operationId":"PipelinesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a pipeline","tags":["Pipelines"]}},"/api/pipelines/{id}/stages":{"post":{"operationId":"PipelinesController_createStage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateStageDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new stage in a pipeline","tags":["Pipelines"]}},"/api/pipelines/{pipelineId}/stages/reorder":{"patch":{"operationId":"PipelinesController_reorderStages","parameters":[{"name":"pipelineId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderStagesDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder pipeline stages","tags":["Pipelines"]}},"/api/pipelines/{pipelineId}/stages/{stageId}":{"patch":{"operationId":"PipelinesController_updateStage","parameters":[{"name":"pipelineId","required":true,"in":"path","schema":{"type":"string"}},{"name":"stageId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStageDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a pipeline stage","tags":["Pipelines"]},"delete":{"operationId":"PipelinesController_removeStage","parameters":[{"name":"pipelineId","required":true,"in":"path","schema":{"type":"string"}},{"name":"stageId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a pipeline stage","tags":["Pipelines"]}},"/api/pipelines/stages/{stageId}/automations":{"get":{"operationId":"PipelinesController_findAutomations","parameters":[{"name":"stageId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List automations attached to a stage","tags":["Pipelines"]},"post":{"operationId":"PipelinesController_createAutomation","parameters":[{"name":"stageId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAutomationDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create an automation on a stage","tags":["Pipelines"]}},"/api/pipelines/automations/{automationId}":{"patch":{"operationId":"PipelinesController_updateAutomation","parameters":[{"name":"automationId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAutomationDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a stage automation","tags":["Pipelines"]},"delete":{"operationId":"PipelinesController_removeAutomation","parameters":[{"name":"automationId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a stage automation","tags":["Pipelines"]}},"/api/pipelines/automations/{automationId}/logs":{"get":{"operationId":"PipelinesController_getAutomationLogs","parameters":[{"name":"automationId","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get execution logs for an automation","tags":["Pipelines"]}},"/api/pipelines/{id}/stats":{"get":{"operationId":"PipelinesController_getStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get stats and conversion metrics for a pipeline","tags":["Pipelines"]}},"/api/pipelines/{id}/migrate-legacy-stages":{"post":{"operationId":"PipelinesController_migrateLegacyStages","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Migrate legacy denormalized stage JSON into PipelineStage rows","tags":["Pipelines"]}},"/api/leads":{"get":{"operationId":"LeadsController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"1-based page number","schema":{"example":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (default 25)","schema":{"example":25,"type":"number"}},{"name":"pipelineId","required":false,"in":"query","description":"Filter by pipeline ID","schema":{"type":"string"}},{"name":"stageId","required":false,"in":"query","description":"Filter by stage ID within the pipeline","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Full-text search across title/description","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Sort column (e.g. createdAt, amount)","schema":{"type":"string"}},{"name":"sortDir","required":false,"in":"query","description":"Sort direction","schema":{"enum":["asc","desc"],"type":"string"}},{"name":"includeDeleted","required":true,"in":"query","schema":{"type":"string"}},{"name":"onlyDeleted","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List leads with pagination, search, and pipeline/stage filters","tags":["Leads"]},"post":{"operationId":"LeadsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLeadDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new lead","tags":["Leads"]}},"/api/leads/stats":{"get":{"operationId":"LeadsController_getStats","parameters":[{"name":"pipelineId","required":false,"in":"query","description":"Restrict stats to a single pipeline","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get lead statistics, optionally scoped to a pipeline","tags":["Leads"],"x-required-scope":["leads:read"]}},"/api/leads/kanban/{pipelineId}":{"get":{"operationId":"LeadsController_kanban","parameters":[{"name":"pipelineId","required":true,"in":"path","schema":{"type":"string"}},{"name":"perStage","required":false,"in":"query","description":"Max leads per stage (capped at 200)","schema":{"example":50,"type":"number"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the kanban board for a pipeline","tags":["Leads"]}},"/api/leads/kanban/{pipelineId}/stage/{stageId}":{"get":{"operationId":"LeadsController_kanbanStageMore","parameters":[{"name":"pipelineId","required":true,"in":"path","schema":{"type":"string"}},{"name":"stageId","required":true,"in":"path","schema":{"type":"string"}},{"name":"offset","required":false,"in":"query","description":"Number of items to skip","schema":{"example":0,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items to load (capped at 100)","schema":{"example":25,"type":"number"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Load more leads for a single kanban stage","tags":["Leads"]}},"/api/leads/stages/{pipelineId}":{"get":{"operationId":"LeadsController_stages","parameters":[{"name":"pipelineId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List stages of a pipeline (for lead filters)","tags":["Leads"]}},"/api/leads/duplicates":{"get":{"operationId":"LeadsController_findDuplicates","parameters":[{"name":"field","required":false,"in":"query","description":"Which signal to detect duplicates by (default all)","schema":{"enum":["title","contact","company","all"],"type":"string"}},{"name":"pipelineId","required":false,"in":"query","description":"Restrict scan to a single pipeline","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Find duplicate leads across the workspace (by title/contact/company within a pipeline)","tags":["Leads"],"x-required-scope":["leads:read"]}},"/api/leads/{id}":{"get":{"operationId":"LeadsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single lead by ID","tags":["Leads"]},"patch":{"operationId":"LeadsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLeadDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an existing lead","tags":["Leads"]},"delete":{"operationId":"LeadsController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Soft-delete a lead","tags":["Leads"]}},"/api/leads/{id}/duplicates":{"get":{"operationId":"LeadsController_checkDuplicates","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check for duplicates of a specific lead","tags":["Leads"]}},"/api/leads/{id}/dossier":{"get":{"operationId":"LeadsController_dossier","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the full dossier (company + contact + activity) for a lead","tags":["Leads"]}},"/api/leads/{id}/interest":{"get":{"operationId":"LeadsController_getInterest","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the AI interest classification for a lead","tags":["Leads"]},"patch":{"operationId":"LeadsController_setInterest","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetInterestDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually set the interest status of a lead","tags":["Leads"]}},"/api/leads/interest/breakdown":{"get":{"operationId":"LeadsController_interestBreakdown","parameters":[{"name":"pipelineId","required":false,"in":"query","description":"Restrict breakdown to a single pipeline","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the breakdown of leads by interest status","tags":["Leads"],"x-required-scope":["leads:read"]}},"/api/leads/{id}/deal":{"get":{"operationId":"LeadsController_getDeal","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the deal projection (amount/probability/weighted) for a lead","tags":["Leads"]},"patch":{"operationId":"LeadsController_updateDeal","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDealDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update deal fields (amount/currency/probability/close date)","tags":["Leads"]}},"/api/leads/deal/forecast":{"get":{"operationId":"LeadsController_forecast","parameters":[{"name":"pipelineId","required":false,"in":"query","description":"Restrict forecast to a single pipeline","schema":{"type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Lower bound on expectedCloseDate (ISO)","schema":{"example":"2026-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Upper bound on expectedCloseDate (ISO)","schema":{"example":"2026-12-31","type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Compute the weighted-amount forecast across leads in scope","tags":["Leads"],"x-required-scope":["leads:read"]}},"/api/leads/{id}/move":{"post":{"operationId":"LeadsController_move","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveLeadDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Move a lead to a different stage (and optionally pipeline)","tags":["Leads"]}},"/api/leads/bulk":{"post":{"operationId":"LeadsController_bulk","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadsBulkDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Enqueue a bulk action on multiple leads (async)","tags":["Leads"],"x-required-scope":["leads:write"]}},"/api/leads/bulk/{jobId}":{"get":{"operationId":"LeadsController_getBulkStatus","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the status of a bulk lead job","tags":["Leads"]},"delete":{"operationId":"LeadsController_cancelBulk","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel an in-progress bulk lead job","tags":["Leads"]}},"/api/leads/{id}/restore":{"post":{"operationId":"LeadsController_restore","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Restore a soft-deleted lead","tags":["Leads"]}},"/api/leads/{id}/purge":{"delete":{"operationId":"LeadsController_purge","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"PERMANENTLY delete a trashed lead (requires isDeleted). Irreversible.","tags":["Leads"]}},"/api/leads/export":{"post":{"operationId":"LeadsController_exportLeads","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportLeadsDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Export leads to a downloadable file","tags":["Leads"],"x-required-scope":["leads:write"]}},"/api/leads/import/preview":{"post":{"operationId":"LeadsController_importPreview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadsImportPreviewDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview a leads import with proposed mapping","tags":["Leads"],"x-required-scope":["leads:write"]}},"/api/leads/import/start":{"post":{"operationId":"LeadsController_importStart","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadsImportStartDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Start a leads import job","tags":["Leads"],"x-required-scope":["leads:write"]}},"/api/tags":{"get":{"operationId":"TagsController_findAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all tags in the workspace","tags":["Tags"]},"post":{"operationId":"TagsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTagDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new tag","tags":["Tags"]}},"/api/tags/{id}":{"patch":{"operationId":"TagsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTagDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an existing tag","tags":["Tags"]},"delete":{"operationId":"TagsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a tag","tags":["Tags"]}},"/api/tags/companies/{companyId}":{"post":{"operationId":"TagsController_attachToCompany","parameters":[{"name":"companyId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachTagDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Attach a tag to a company","tags":["Tags"]}},"/api/tags/companies/{companyId}/{tagId}":{"delete":{"operationId":"TagsController_detachFromCompany","parameters":[{"name":"companyId","required":true,"in":"path","schema":{"type":"string"}},{"name":"tagId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Detach a tag from a company","tags":["Tags"]}},"/api/tags/contacts/{contactId}":{"post":{"operationId":"TagsController_attachToContact","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachTagDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Attach a tag to a contact","tags":["Tags"]}},"/api/tags/contacts/{contactId}/{tagId}":{"delete":{"operationId":"TagsController_detachFromContact","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}},{"name":"tagId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Detach a tag from a contact","tags":["Tags"]}},"/api/tags/leads/{leadId}":{"post":{"operationId":"TagsController_attachToLead","parameters":[{"name":"leadId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachTagDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Attach a tag to a lead","tags":["Tags"]}},"/api/tags/leads/{leadId}/{tagId}":{"delete":{"operationId":"TagsController_detachFromLead","parameters":[{"name":"leadId","required":true,"in":"path","schema":{"type":"string"}},{"name":"tagId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Detach a tag from a lead","tags":["Tags"]}},"/api/contact-lists":{"get":{"operationId":"ContactListsController_findAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all contact lists for the tenant","tags":["Contact Lists"]},"post":{"operationId":"ContactListsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactListsCreateDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new contact list","tags":["Contact Lists"]}},"/api/contact-lists/{id}":{"patch":{"operationId":"ContactListsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactListsUpdateDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a contact list","tags":["Contact Lists"]},"delete":{"operationId":"ContactListsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a contact list","tags":["Contact Lists"]}},"/api/contact-lists/reorder":{"post":{"operationId":"ContactListsController_reorder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactListsReorderDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder contact lists by id/sortOrder array","tags":["Contact Lists"],"x-required-scope":["crm:write"]}},"/api/contact-lists/{id}/contacts":{"post":{"operationId":"ContactListsController_addContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactListsAddContactsDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add contacts to a list","tags":["Contact Lists"]},"delete":{"operationId":"ContactListsController_removeContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove contacts from a list","tags":["Contact Lists"]}},"/api/contact-lists/{id}/duplicate":{"post":{"operationId":"ContactListsController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Duplicate a contact list","tags":["Contact Lists"]}},"/api/contact-lists/all-statistics":{"get":{"operationId":"ContactListsController_allStatistics","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get statistics across all contact lists","tags":["Contact Lists"],"x-required-scope":["crm:read"]}},"/api/contact-lists/compare":{"get":{"operationId":"ContactListsController_compare","parameters":[{"name":"a","required":true,"in":"query","schema":{"type":"string"}},{"name":"b","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Compare statistics between two contact lists","tags":["Contact Lists"],"x-required-scope":["crm:read"]}},"/api/contact-lists/{id}/statistics":{"get":{"operationId":"ContactListsController_statistics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get statistics for a single contact list","tags":["Contact Lists"]}},"/api/contact-list-groups":{"get":{"operationId":"ContactListGroupsController_findAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List contact list groups (flat, with parentId for tree)","tags":["Contact List Groups"]},"post":{"operationId":"ContactListGroupsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a contact list group","tags":["Contact List Groups"]}},"/api/contact-list-groups/reorder":{"post":{"operationId":"ContactListGroupsController_reorder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder contact list groups by id/sortOrder array","tags":["Contact List Groups"],"x-required-scope":["crm:write"]}},"/api/contact-list-groups/{id}":{"patch":{"operationId":"ContactListGroupsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a contact list group (name/description/color/parent/sort)","tags":["Contact List Groups"]},"delete":{"operationId":"ContactListGroupsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a contact list group (children + lists are detached)","tags":["Contact List Groups"]}},"/api/company-lists":{"get":{"operationId":"CompanyListsController_findAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all company lists for the tenant","tags":["Company Lists"]},"post":{"operationId":"CompanyListsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyListsCreateDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new company list","tags":["Company Lists"]}},"/api/company-lists/contacts-counts":{"get":{"operationId":"CompanyListsController_contactsCounts","parameters":[{"name":"ids","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Sum of contacts of member companies, per list id (?ids=csv)","tags":["Company Lists"],"x-required-scope":["crm:read"]}},"/api/company-lists/{id}":{"patch":{"operationId":"CompanyListsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyListsUpdateDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a company list","tags":["Company Lists"]},"delete":{"operationId":"CompanyListsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a company list","tags":["Company Lists"]}},"/api/company-lists/reorder":{"post":{"operationId":"CompanyListsController_reorder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyListsReorderDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder company lists by id/sortOrder array","tags":["Company Lists"],"x-required-scope":["crm:write"]}},"/api/company-lists/{id}/companies":{"post":{"operationId":"CompanyListsController_addCompanies","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyListsAddCompaniesDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add companies to a list","tags":["Company Lists"]},"delete":{"operationId":"CompanyListsController_removeCompanies","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove companies from a list","tags":["Company Lists"]}},"/api/company-lists/{id}/merge":{"post":{"operationId":"CompanyListsController_merge","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyListsMergeDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Merge this list into another list: move or copy all member companies atomically, duplicates in the target are skipped","tags":["Company Lists"]}},"/api/company-lists/{id}/duplicate":{"post":{"operationId":"CompanyListsController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Duplicate a company list","tags":["Company Lists"]}},"/api/company-list-groups":{"get":{"operationId":"CompanyListGroupsController_findAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List company list groups (flat, with parentId for tree)","tags":["Company List Groups"]},"post":{"operationId":"CompanyListGroupsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a company list group","tags":["Company List Groups"]}},"/api/company-list-groups/reorder":{"post":{"operationId":"CompanyListGroupsController_reorder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder company list groups by id/sortOrder array","tags":["Company List Groups"],"x-required-scope":["crm:write"]}},"/api/company-list-groups/{id}":{"patch":{"operationId":"CompanyListGroupsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a company list group (name/description/color/parent/sort)","tags":["Company List Groups"]},"delete":{"operationId":"CompanyListGroupsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a company list group (children + lists are detached)","tags":["Company List Groups"]}},"/api/campaign-groups":{"get":{"operationId":"CampaignGroupsController_findAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List campaign groups (flat, with parentId for tree)","tags":["Campaign Groups"]},"post":{"operationId":"CampaignGroupsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a campaign group","tags":["Campaign Groups"]}},"/api/campaign-groups/reorder":{"post":{"operationId":"CampaignGroupsController_reorder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder campaign groups by id/sortOrder array","tags":["Campaign Groups"],"x-required-scope":["crm:write"]}},"/api/campaign-groups/{id}":{"patch":{"operationId":"CampaignGroupsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a campaign group (name/description/color/parent/sort)","tags":["Campaign Groups"]},"delete":{"operationId":"CampaignGroupsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a campaign group (children + campaigns are detached)","tags":["Campaign Groups"]}},"/api/settings":{"get":{"operationId":"SettingsController_getSettings","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the full workspace settings document","tags":["Settings"]}},"/api/settings/ai-providers":{"patch":{"operationId":"SettingsController_updateAiProviders","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiProvidersDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update AI provider keys and defaults","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/ldm-ai/request":{"post":{"operationId":"SettingsController_requestLdmAi","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestLdmAiDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Request LDM AI access / balance increase (tenant → admin)","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/notifications":{"patch":{"operationId":"SettingsController_updateNotifications","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateNotificationsDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update notification preferences (push and email)","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/workspace":{"patch":{"operationId":"SettingsController_updateWorkspace","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWorkspaceDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update workspace metadata (name, currency, language)","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/profile":{"get":{"operationId":"SettingsController_getProfile","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the current user profile","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateProfile","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProfileDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the current user profile","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/ui-preferences":{"get":{"operationId":"SettingsController_getUiPreferences","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get current user UI preferences (dashboard blocks, left menu)","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateUiPreferences","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Replace current user UI preferences","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/profile/avatar":{"post":{"operationId":"SettingsController_uploadAvatar","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Upload a new avatar for the current user","tags":["Settings"],"x-required-scope":["settings:write"]},"delete":{"operationId":"SettingsController_deleteAvatar","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete the current user avatar","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/security/change-password":{"post":{"operationId":"SettingsController_changePassword","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Change the current user password","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/security/sessions":{"get":{"operationId":"SettingsController_getSessions","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List active sessions for the current user","tags":["Settings"],"x-required-scope":["settings:read"]},"delete":{"operationId":"SettingsController_revokeAllSessions","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Revoke all active sessions for the current user","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/security/sessions/{sessionId}":{"delete":{"operationId":"SettingsController_revokeSession","parameters":[{"name":"sessionId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Revoke a single user session","tags":["Settings"]}},"/api/settings/integrations/bo-nalog":{"get":{"operationId":"SettingsController_getBoNalogIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get bo.nalog.gov.ru integration state: enabled, our rate limit, requests today, last error","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateBoNalogIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update bo.nalog.gov.ru integration: enable/disable, requests-per-minute cap","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/integrations/dadata":{"get":{"operationId":"SettingsController_getDadataIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get DaData integration configuration","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateDadataIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update DaData integration configuration","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/integrations/dadata/reset-counter":{"post":{"operationId":"SettingsController_resetDadataCounter","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset the DaData daily request counter","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/integrations/inbox-check":{"get":{"operationId":"SettingsController_getInboxCheckIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get Inbox Check integration configuration","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateInboxCheckIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update Inbox Check integration configuration","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/integrations/inbox-check/test":{"post":{"operationId":"SettingsController_testInboxCheckConnection","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Test the Inbox Check connection","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/integrations/smartlead":{"get":{"operationId":"SettingsController_getSmartleadIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get Smartlead integration configuration","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateSmartleadIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update Smartlead integration configuration","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/integrations/smartlead/test":{"post":{"operationId":"SettingsController_testSmartleadConnection","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Test the Smartlead connection","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/integrations/smartlead/placement-matrix":{"get":{"operationId":"SettingsController_getSmartleadPlacementMatrix","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Smartlead placement matrix — mailbox × provider (#1040)","tags":["Settings"],"x-required-scope":["settings:read"]}},"/api/settings/integrations/smartlead/placement-history":{"get":{"operationId":"SettingsController_getSmartleadPlacementHistory","parameters":[{"name":"mailbox","required":true,"in":"query","schema":{"type":"string"}},{"name":"provider","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Smartlead placement history for one mailbox × provider cell (#1040)","tags":["Settings"],"x-required-scope":["settings:read"]}},"/api/settings/transports":{"get":{"operationId":"SettingsController_getTransports","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get enabled mail transport flags","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateTransports","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update enabled mail transport flags","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/mailing-auto-approve":{"get":{"operationId":"SettingsController_listMailingAutoApprove","parameters":[{"name":"userId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List users with mailing auto-approve enabled (SUPER only). Pass userId to resolve the TARGET USER tenant instead of the calling SUPER session tenant.","tags":["Settings"],"x-required-scope":["settings:read"]}},"/api/settings/users/{userId}/mailing-auto-approve":{"patch":{"operationId":"SettingsController_setMailingAutoApprove","parameters":[{"name":"userId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Enable/disable mailing auto-approve for a user (SUPER only).","tags":["Settings"]}},"/api/settings/mailing-auto-approve-tenant":{"get":{"operationId":"SettingsController_getTenantMailingAutoApprove","parameters":[{"name":"tenantId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get tenant-level mailing auto-approve — whether the WHOLE workspace sends without manual approval (SUPER only).","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_setTenantMailingAutoApprove","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set tenant-level mailing auto-approve. enabled=true → the whole workspace sends immediately after QC, no manual admin approval (overrides per-user). enabled=false → manual approval (or per-user trusted senders). SUPER only.","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/auditor-rules":{"get":{"operationId":"SettingsController_getAuditorRules","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get workspace send window (#194): { enabled, workDays[1-7], startTime, endTime, timezone } or null (24/7)","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_setAuditorRules","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Partial PATCH of the tenant auditor canon (#100): { minScore?, tier2?: {enabled?, model?}, rules?: [{id,phrase,severity?,message?,weight?,scope?,enabled?}] }. rules — if sent, replaces the list ENTIRELY (send the whole list, not just the new item). Fields/groups not sent are left untouched — seeded from the current effective document, not the schema defaults. SUPER only.","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/send-window":{"get":{"operationId":"SettingsController_getSendWindow","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"tags":["Settings"]},"patch":{"operationId":"SettingsController_setSendWindow","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set workspace send window (#194). enabled=false → 24/7 (default). SUPER only.","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/relay-health":{"get":{"operationId":"SettingsController_getRelayHealth","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Relay health thresholds of the whole workspace (#337): block-guard, bounce auto-pause, relay cooldowns, limit policy and ERROR re-probe (#356: backoff and when a dead relay is escalated for manual review). These are the DEFAULTS every campaign inherits — a campaign senderConfig only overrides them. Returns effective values, stored overrides and code defaults","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_setRelayHealth","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set workspace relay health defaults (#337). Partial patch: send only the groups you change (blockGuard, bounce, cooldownSec, limits, probe, inbound). Values are clamped to safe bounds. inbound.requireChannel=true (#357) stops relays without a working receive channel from being picked for sending at all. SUPER only","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/min-send-interval":{"get":{"operationId":"SettingsController_getMinSendInterval","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get workspace default min send interval per account, seconds (#194). 0 = off","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_setMinSendInterval","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set workspace default min send interval per account, seconds 0..86400 (#194). Per-account override lives on emailAccount.minSendIntervalSeconds. SUPER only.","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/platform-tracking-allowed":{"get":{"operationId":"SettingsController_getPlatformTrackingAllowed","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get whether SUPER allowed this tenant to serve the open-pixel via the SHARED platform domain (pixelSource=ldm). SUPER only. (#237)","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_setPlatformTrackingAllowed","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Allow/deny this tenant to serve the open-pixel via the SHARED platform domain (pixelSource=ldm). Default false — anti-spam gate so an unapproved tenant cannot burn the shared domain. SUPER only. (#237)","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/notify-rules":{"get":{"operationId":"SettingsController_getNotifyRules","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the notification routing rules","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateNotifyRules","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the notification routing rules","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/crm-event-rules":{"get":{"operationId":"SettingsController_getCrmEventRules","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get CRM event → notification bridge rules","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateCrmEventRules","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update CRM event → notification bridge rules","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/memory-notes":{"get":{"operationId":"SettingsController_getMemoryNotes","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the current user memory notes for AI features","tags":["Settings"],"x-required-scope":["settings:read"]},"patch":{"operationId":"SettingsController_updateMemoryNotes","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the current user memory notes","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/trash":{"get":{"operationId":"SettingsController_getTrash","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Trash counters: soft-deleted dialogs/leads/contacts/companies awaiting restore or purge","tags":["Settings"],"x-required-scope":["settings:read"]}},"/api/settings/trash/empty":{"post":{"operationId":"SettingsController_emptyTrash","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Empty trash — PERMANENTLY delete soft-deleted records. Body: {confirmation:\"EMPTY TRASH\", entities?:[\"dialogs\"|\"leads\"|\"contacts\"|\"companies\"]} (default: all). Irreversible.","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/delete-data":{"delete":{"operationId":"SettingsController_deleteAllData","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete all tenant data (irreversible danger-zone action)","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/settings/account/deactivation-preview":{"get":{"operationId":"SettingsController_getAccountDeactivationPreview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview before account deactivation: confirmation phrase + blockers (active campaigns)","tags":["Settings"],"x-required-scope":["settings:read"]}},"/api/settings/account/deactivate":{"post":{"operationId":"SettingsController_deactivateAccount","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Deactivate the tenant account (irreversible self-service action). Confirmation = workspace name or the initiator's email, not a bare \"OK\". Data is retained; final purge stays admin-scheduled and out of scope here.","tags":["Settings"],"x-required-scope":["settings:write"]}},"/api/dialogs":{"get":{"operationId":"DialogsController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"1-based page number","schema":{"example":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page","schema":{"example":25,"type":"number"}},{"name":"channel","required":false,"in":"query","description":"Filter by channel (EMAIL/TELEGRAM/...)","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter by dialog status","schema":{"type":"string"}},{"name":"direction","required":false,"in":"query","description":"IN / OUT","schema":{"type":"string"}},{"name":"contactId","required":false,"in":"query","description":"Filter to dialogs linked to a contact","schema":{"type":"string"}},{"name":"companyId","required":false,"in":"query","description":"Filter to dialogs linked to a company","schema":{"type":"string"}},{"name":"leadId","required":false,"in":"query","description":"Filter to dialogs linked to a lead","schema":{"type":"string"}},{"name":"accountId","required":false,"in":"query","description":"Filter to dialogs on a single email account","schema":{"type":"string"}},{"name":"mailingId","required":false,"in":"query","description":"Filter to dialogs from a single mailing","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Full-text search across subject/body","schema":{"type":"string"}},{"name":"needsAttention","required":false,"in":"query","description":"true/false — only items flagged for review","schema":{"type":"string"}},{"name":"dateFrom","required":false,"in":"query","description":"Lower bound on createdAt (ISO)","schema":{"example":"2026-01-01","type":"string"}},{"name":"dateTo","required":false,"in":"query","description":"Upper bound on createdAt (ISO)","schema":{"example":"2026-12-31","type":"string"}},{"name":"sort","required":false,"in":"query","description":"Sort token","schema":{"type":"string"}},{"name":"marking","required":false,"in":"query","description":"Include only dialogs with this marking/messageType","schema":{"type":"string"}},{"name":"excludeMarking","required":false,"in":"query","description":"Exclude dialogs with this marking","schema":{"type":"string"}},{"name":"emailFolder","required":false,"in":"query","description":"IMAP folder path","schema":{"type":"string"}},{"name":"starred","required":false,"in":"query","description":"true/false — starred only","schema":{"type":"string"}},{"name":"includeDrafts","required":false,"in":"query","description":"true to include unsent drafts","schema":{"type":"string"}},{"name":"pendingSend","required":false,"in":"query","description":"true for queued-but-not-sent outbox items","schema":{"type":"string"}},{"name":"placement","required":false,"in":"query","description":"inbox-check placement bucket","schema":{"enum":["inbox","spam","unchecked"],"type":"string"}},{"name":"snoozed","required":false,"in":"query","description":"Snooze visibility filter","schema":{"enum":["hidden","only","all"],"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List dialogs with filters (channel, status, folder, etc.)","tags":["Dialogs"]}},"/api/dialogs/stats":{"get":{"operationId":"DialogsController_getStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregate dialog statistics","tags":["Dialogs"],"x-required-scope":["dialogs:read"]}},"/api/dialogs/badges":{"post":{"operationId":"DialogsController_getBadges","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Get bulk dialog badges for a set of leads","tags":["Dialogs"],"x-required-scope":["dialogs:read"]}},"/api/dialogs/accounts":{"get":{"operationId":"DialogsController_getAccounts","parameters":[{"name":"activeOnly","required":false,"in":"query","description":"true to return only active accounts","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List email accounts used in dialogs","tags":["Dialogs"],"x-required-scope":["dialogs:read"]}},"/api/dialogs/folders":{"get":{"operationId":"DialogsController_getFolders","parameters":[{"name":"accountId","required":false,"in":"query","description":"Restrict folders to one account","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List folders, optionally scoped to an account","tags":["Dialogs"],"x-required-scope":["dialogs:read"]}},"/api/dialogs/thread/{threadId}":{"get":{"operationId":"DialogsController_getThread","parameters":[{"name":"threadId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a full dialog thread by thread ID","tags":["Dialogs"]}},"/api/dialogs/bulk":{"post":{"operationId":"DialogsController_bulk","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Perform a bulk action on multiple dialogs","tags":["Dialogs"],"x-required-scope":["dialogs:write"]}},"/api/dialogs/imap/move":{"post":{"operationId":"DialogsController_imapMove","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Move dialogs to an IMAP folder","tags":["Dialogs"],"x-required-scope":["dialogs:write"]}},"/api/dialogs/imap/delete":{"post":{"operationId":"DialogsController_imapDelete","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Permanently delete dialogs from IMAP","tags":["Dialogs"],"x-required-scope":["dialogs:write"]}},"/api/dialogs/imap/folders":{"get":{"operationId":"DialogsController_imapListFolders","parameters":[{"name":"accountId","required":true,"in":"query","description":"Email account to query (required)","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List IMAP folders live from the mail server","tags":["Dialogs"],"x-required-scope":["dialogs:read"]},"post":{"operationId":"DialogsController_imapCreateFolder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create an IMAP folder","tags":["Dialogs"],"x-required-scope":["dialogs:write"]},"patch":{"operationId":"DialogsController_imapRenameFolder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Rename an IMAP folder","tags":["Dialogs"],"x-required-scope":["dialogs:write"]}},"/api/dialogs/imap/folders/delete":{"post":{"operationId":"DialogsController_imapDeleteFolder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an IMAP folder","tags":["Dialogs"],"x-required-scope":["dialogs:write"]}},"/api/dialogs/outbox":{"get":{"operationId":"DialogsController_getOutbox","parameters":[{"name":"status","required":false,"in":"query","description":"Filter by outbox status (queued/sent/failed/...)","schema":{"type":"string"}},{"name":"scheduled","required":false,"in":"query","description":"only=future-scheduled, none=immediate","schema":{"enum":["only","none"],"type":"string"}},{"name":"page","required":false,"in":"query","description":"1-based page number","schema":{"example":1,"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Items per page (default 20)","schema":{"example":20,"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List outbox entries with status and scheduling info","tags":["Dialogs"],"x-required-scope":["dialogs:read"]}},"/api/dialogs/outbox/{id}/history":{"get":{"operationId":"DialogsController_getOutboxHistory","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"maximum":200,"example":50,"type":"number"}},{"name":"cursor","required":false,"in":"query","schema":{"type":"string"}},{"name":"revisionId","required":false,"in":"query","description":"Read one archived pre-send revision with content detail","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Read safe, paginated history for one durable outbox task","tags":["Dialogs"]}},"/api/dialogs/outbox/{id}":{"patch":{"operationId":"DialogsController_rescheduleOutbox","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reschedule (or clear schedule on) a queued outbox send","tags":["Dialogs"]},"delete":{"operationId":"DialogsController_cancelOutbox","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel a queued or failed outbox entry","tags":["Dialogs"]}},"/api/dialogs/outbox/stats":{"get":{"operationId":"DialogsController_getOutboxStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get outbox queue statistics","tags":["Dialogs"],"x-required-scope":["dialogs:read"]}},"/api/dialogs/outbox/{id}/retry":{"post":{"operationId":"DialogsController_retryOutbox","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually retry a failed outbox entry","tags":["Dialogs"]}},"/api/dialogs/outbox/{id}/refresh-control":{"post":{"operationId":"DialogsController_refreshControlEmail","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Poll inbox-check for the placement status of a control email","tags":["Dialogs"]}},"/api/dialogs/outbox/{id}/resend-control":{"post":{"operationId":"DialogsController_resendControlEmail","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Re-enqueue the control-copy send for an outbox entry","tags":["Dialogs"]}},"/api/dialogs/{id}":{"get":{"operationId":"DialogsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single dialog by ID","tags":["Dialogs"]},"patch":{"operationId":"DialogsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update dialog metadata or edit a queued outbox message","tags":["Dialogs"]},"delete":{"operationId":"DialogsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/mark-read":{"post":{"operationId":"DialogsController_markRead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Mark a dialog as read","tags":["Dialogs"]}},"/api/dialogs/{id}/star":{"post":{"operationId":"DialogsController_toggleStar","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Toggle the starred flag on a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/snooze":{"post":{"operationId":"DialogsController_snooze","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Snooze a dialog until a future timestamp","tags":["Dialogs"]}},"/api/dialogs/{id}/unsnooze":{"post":{"operationId":"DialogsController_unsnooze","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Unsnooze a dialog immediately","tags":["Dialogs"]}},"/api/dialogs/{id}/reminder":{"post":{"operationId":"DialogsController_setReminder","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Set a reminder on a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/reminder/clear":{"post":{"operationId":"DialogsController_clearReminder","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Clear an existing reminder on a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/classify-reply":{"post":{"operationId":"DialogsController_classifyReply","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run AI reply classification on a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/mark-type":{"post":{"operationId":"DialogsController_markType","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually mark the message type / marking of a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/action/unsubscribe":{"post":{"operationId":"DialogsController_actionUnsubscribe","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Process an unsubscribe action triggered by a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/action/bounce":{"post":{"operationId":"DialogsController_actionBounce","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Process a bounce action (hard or soft) on a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/action/spam":{"post":{"operationId":"DialogsController_actionSpam","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Mark a dialog as spam and apply side effects","tags":["Dialogs"]}},"/api/dialogs/{id}/action/stop-list":{"post":{"operationId":"DialogsController_actionStopList","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add the dialog sender to the stop-list","tags":["Dialogs"]}},"/api/dialogs/{id}/generate-reply":{"post":{"operationId":"DialogsController_generateReply","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate an AI reply draft for a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/reply":{"post":{"operationId":"DialogsController_reply","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"bodyText":{"type":"string"},"bodyHtml":{"type":"string"},"subject":{"type":"string"},"accountId":{"type":"string"},"fromName":{"type":"string"},"sendSmtp":{"type":"string"},"attachments":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reply to a dialog (optionally send via SMTP with attachments). Attachments can be passed inline as `attachmentsJson: [{ filename, contentBase64, contentType }]` (base64-encoded, JSON body) or as multipart files. (#175 — parity with /compose)","tags":["Dialogs"]}},"/api/dialogs/{id}/forward":{"post":{"operationId":"DialogsController_forward","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["toEmail"],"properties":{"toEmail":{"type":"string"},"toName":{"type":"string"},"bodyText":{"type":"string"},"bodyHtml":{"type":"string"},"subject":{"type":"string"},"accountId":{"type":"string"},"fromName":{"type":"string"},"sendSmtp":{"type":"string"},"attachments":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Forward an existing dialog to a new recipient. Attachments can be passed inline as `attachmentsJson: [{ filename, contentBase64, contentType }]` (base64-encoded, JSON body) or as multipart files. (#175 — parity with /compose)","tags":["Dialogs"]}},"/api/dialogs/compose":{"post":{"operationId":"DialogsController_compose","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComposeDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Compose and send a new outbound email. Provide exactly one sender binding: `accountId` (a fixed relay) OR `accountListId` (a virtual-relay pool — the live relay is chosen from the pool at dispatch time, #40). Attachments are inline only: `attachmentsJson: [{ filename, contentBase64, contentType }]` (base64-encoded). No multipart upload on this endpoint — use `:id/reply` or `:id/forward` for that. (#3 Block 3 — inline attachments)","tags":["Dialogs"],"x-required-scope":["dialogs:write"]}},"/api/dialogs/{id}/auto-link":{"post":{"operationId":"DialogsController_autoLink","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Auto-link a dialog to matching contact/company/lead","tags":["Dialogs"]}},"/api/dialogs/{id}/create-lead":{"post":{"operationId":"DialogsController_createLead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new lead from a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/extract-entities":{"post":{"operationId":"DialogsController_extractEntities","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run AI entity extraction (company/contact) on a dialog","tags":["Dialogs"]}},"/api/dialogs/{id}/track/set-token":{"post":{"operationId":"DialogsController_setTrackingToken","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Set the tracking token on a dialog (internal use)","tags":["Dialogs"]}},"/api/dialogs/track/open":{"post":{"operationId":"DialogsController_trackOpen","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Record an email-open tracking event","tags":["Dialogs"],"x-required-scope":["dialogs:write"]}},"/api/dialogs/track/click":{"post":{"operationId":"DialogsController_trackClick","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Record an email-click tracking event","tags":["Dialogs"],"x-required-scope":["dialogs:write"]}},"/api/dialogs/{id}/restore":{"post":{"operationId":"DialogsController_restore","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Restore a deleted dialog (status DELETED → NEW)","tags":["Dialogs"]}},"/api/dialogs/{id}/purge":{"delete":{"operationId":"DialogsController_purge","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"PERMANENTLY delete a trashed dialog (requires status DELETED). Irreversible.","tags":["Dialogs"]}},"/api/dialogs/{id}/share":{"post":{"operationId":"DialogsController_shareDialog","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate a public share token for a dialog (30-day TTL)","tags":["Dialogs"]}},"/api/user-settings":{"get":{"operationId":"UserSettingsController_get","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get current user settings","tags":["User Settings"]},"patch":{"operationId":"UserSettingsController_update","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update current user settings","tags":["User Settings"]}},"/api/user-settings/available-transports":{"get":{"operationId":"UserSettingsController_availableTransports","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List available transports admin has enabled","tags":["User Settings"],"x-required-scope":["settings:read"]}},"/api/mailing/overview":{"get":{"operationId":"MailingController_getOverview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a global overview of all mailing campaigns (admin dashboard) — merges legacy mailing tasks AND the campaign conveyor (#539); each row is tagged source: legacy | campaign","tags":["Mailing"],"x-required-scope":["mailing:read"]}},"/api/mailing/bounce-overview":{"get":{"operationId":"MailingController_getBounceOverview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get global bounce statistics: legacy mailing tasks (per-task + per-domain) AND the campaign conveyor (#345) — campaignBounces.byNature splits bounces into hard/inactive (dead addresses), soft (retryable), policy/routing (route reputation, address alive), plus top bounced domains","tags":["Mailing"],"x-required-scope":["mailing:read"]}},"/api/mailing/warmup-overview":{"get":{"operationId":"MailingController_getWarmupOverview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get an overview of all email accounts currently in warmup mode","tags":["Mailing"],"x-required-scope":["mailing:read"]}},"/api/mailing/pending-approvals":{"get":{"operationId":"MailingController_getPendingApprovals","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List campaigns awaiting admin approval (cross-tenant for SUPER)","tags":["Mailing"],"x-required-scope":["mailing:read"]}},"/api/mailing/{taskId}/approve":{"post":{"operationId":"MailingController_approveCampaign","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Approve a pending mailing campaign (admin)","tags":["Mailing"]}},"/api/mailing/{taskId}/reject":{"post":{"operationId":"MailingController_rejectCampaign","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reject a pending mailing campaign (admin)","tags":["Mailing"]}},"/api/mailing/creative-preview/{creativeId}":{"get":{"operationId":"MailingController_getCreativePreview","parameters":[{"name":"creativeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"dbName","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview a creative for approval (cross-tenant for SUPER)","tags":["Mailing"]}},"/api/mailing/{taskId}/config":{"get":{"operationId":"MailingController_getConfig","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the mailing configuration for a campaign","tags":["Mailing"]},"patch":{"operationId":"MailingController_updateConfig","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the mailing configuration for a campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/start":{"post":{"operationId":"MailingController_startCampaign","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Start a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/start-sending":{"post":{"operationId":"MailingController_startSending","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Issue #180: start sending an APPROVED campaign (status=APPROVED). A separate step after approval — launches streams → ACTIVE. 400 if not approved or the creative changed after approval (needs re-approval).","tags":["Mailing"]}},"/api/mailing/batch-stats":{"post":{"operationId":"MailingController_getBatchStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Get stats for a batch of mailing tasks in one call","tags":["Mailing"],"x-required-scope":["mailing:write"]}},"/api/mailing/{taskId}/start-list-stats":{"get":{"operationId":"MailingController_getStartListStats","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get start-list statistics for a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/stats":{"get":{"operationId":"MailingController_getStats","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregate stats for a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/timeline":{"get":{"operationId":"MailingController_getTimeline","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the activity timeline for a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/speed":{"get":{"operationId":"MailingController_getSpeed","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get sending speed metrics for a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/streams":{"get":{"operationId":"MailingController_getStreams","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List sending streams for a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/streams/{streamId}/logs":{"get":{"operationId":"MailingController_getStreamLogs","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"streamId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get logs for a specific mailing stream","tags":["Mailing"]}},"/api/mailing/{taskId}/streams/{streamId}/detail":{"get":{"operationId":"MailingController_getStreamDetail","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"streamId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get detailed information for a specific mailing stream","tags":["Mailing"]}},"/api/mailing/{taskId}/streams/{streamId}/logs-filtered":{"get":{"operationId":"MailingController_getStreamLogsFiltered","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"streamId","required":true,"in":"path","schema":{"type":"string"}},{"name":"stage","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get filtered and paginated logs for a mailing stream","tags":["Mailing"]}},"/api/mailing/{taskId}/logs":{"delete":{"operationId":"MailingController_deleteTaskLogs","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete all logs for a mailing campaign (SUPER only)","tags":["Mailing"]}},"/api/mailing/{taskId}/items":{"get":{"operationId":"MailingController_getItems","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List mailing items (recipients) for a campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/items/{itemId}":{"get":{"operationId":"MailingController_getItem","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"itemId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single mailing item by id","tags":["Mailing"]},"patch":{"operationId":"MailingController_updateItem","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"itemId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update fields of a single mailing item","tags":["Mailing"]}},"/api/mailing/{taskId}/items/{itemId}/status":{"patch":{"operationId":"MailingController_updateItemStatus","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"itemId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the status of a single mailing item","tags":["Mailing"]}},"/api/mailing/{taskId}/reset-errors":{"post":{"operationId":"MailingController_resetErrors","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset all failed mailing items in a campaign back to pending","tags":["Mailing"]}},"/api/mailing/{taskId}/reset-status/{status}":{"post":{"operationId":"MailingController_resetByStatus","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"status","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset all items with a given status back to pending (admin recovery only)","tags":["Mailing"]}},"/api/mailing/{taskId}/stats/today":{"get":{"operationId":"MailingController_getStatsToday","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get today's stats for a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/ab-test":{"get":{"operationId":"MailingController_getAbTest","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get A/B test statistics for a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/analytics":{"get":{"operationId":"MailingController_getAnalytics","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get per-domain analytics for a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/control-email-stats":{"get":{"operationId":"MailingController_getControlEmailStats","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get control-email tracking stats for a mailing campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/control-email-autopause/evaluate":{"post":{"operationId":"MailingController_evaluateControlEmailAutoPause","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually evaluate control-email auto-pause rules for a campaign","tags":["Mailing"]}},"/api/mailing/{taskId}/export.csv":{"get":{"operationId":"MailingController_exportCsv","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Export a mailing campaign as CSV","tags":["Mailing"]}},"/api/mailing/{taskId}/report.pdf":{"get":{"operationId":"MailingController_exportReportPdf","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Export a client-ready PDF report for a mailing campaign","tags":["Mailing"]}},"/api/mailing/block-guard/dashboard":{"get":{"operationId":"MailingController_blockGuardDashboard","parameters":[{"name":"taskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the BlockGuard dashboard (blocks, barked templates, paused accounts)","tags":["Mailing"],"x-required-scope":["mailing:read"]}},"/api/mailing/block-guard/template/{templateId}":{"get":{"operationId":"MailingController_blockGuardTemplate","parameters":[{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get block-event history for a template","tags":["Mailing"]}},"/api/mailing/block-guard/template/{templateId}/unblock":{"post":{"operationId":"MailingController_blockGuardUnblock","parameters":[{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually unblock a previously barked template","tags":["Mailing"]}},"/api/mailing/block-guard/account/{accountId}/reset-limits":{"post":{"operationId":"MailingController_blockGuardResetAccount","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset limit counters for one account: clear auto-pause + zero working counters, KEEP stats (#289)","tags":["Mailing"]}},"/api/mailing/{taskId}/reset-limits":{"post":{"operationId":"MailingController_resetLimits","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset limit counters for a whole mailing: un-pause blocked accounts, KEEP block_events/stats (#289)","tags":["Mailing"]}},"/api/mailing/block-guard/account/{accountId}":{"get":{"operationId":"MailingController_blockGuardAccount","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get block-event history for an email account","tags":["Mailing"]}},"/api/mailing/block-guard/providers":{"get":{"operationId":"MailingController_blockGuardProviders","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get block statistics aggregated per email provider","tags":["Mailing"],"x-required-scope":["mailing:read"]}},"/api/t/o/{trackingId}.gif":{"get":{"operationId":"TrackingController_pixelOpen","parameters":[{"name":"trackingId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Serve a 1x1 tracking pixel GIF and log an OPEN event. Injected into campaign emails; drives open-rate analytics.","tags":["Tracking"]}},"/api/t/c/{trackingId}/{slug}":{"get":{"operationId":"TrackingController_clickRedirect","parameters":[{"name":"trackingId","required":true,"in":"path","schema":{"type":"string"}},{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Redirect a tracked click (/t/c/:trackingId/:slug) to target and log a CLICK. Cloaking: cloakMode=bot_split → bots go to botDecoyUrl (logs BOT_CLICK), humans to target; cloakMode=captcha → HTML interstitial unless a valid ?v token is present. This mapped path is produced by campaign sends and feeds analytics.","tags":["Tracking"]}},"/api/r/{slug}":{"get":{"operationId":"TrackingController_legacyRedirect","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Short redirect by slug (/r/:slug) — click path for directly-created links (createLink). Applies the same cloaking (bot_split / captcha via ?v) but does NOT log tracking events, so this path produces no analytics.","tags":["Tracking"]}},"/api/tracking/links":{"post":{"operationId":"TrackingController_createLink","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a tracking link. Optional cloakMode (off|bot_split|captcha) + botDecoyUrl enable cloaking immediately, no send required. Such links are clicked via /r/:slug (legacyRedirect) and do NOT log events — for open/click-rate analytics send links through a campaign (senderConfig.tracking).","tags":["Tracking"],"x-required-scope":["mailing:write"]}},"/api/tracking/links/{slug}":{"get":{"operationId":"TrackingController_getLinkInfo","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get tracking link info by slug","tags":["Tracking"]},"patch":{"operationId":"TrackingController_updateLink","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a tracking link: cloakMode (off|bot_split|captcha), botDecoyUrl and/or targetUrl. Only provided fields change.","tags":["Tracking"]},"delete":{"operationId":"TrackingController_deleteLink","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a tracking link by slug","tags":["Tracking"]}},"/api/tracking/simulate-click":{"post":{"operationId":"TrackingController_simulateClick","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Dry-run the cloaking decision for a link given userAgent/ip/v — returns target|decoy|captcha + bot verdict WITHOUT logging an event or moving counters. Lets an agent test cloakMode (off/bot_split/captcha) without spoofing HTTP headers.","tags":["Tracking"],"x-required-scope":["mailing:read"]}},"/api/tracking/events":{"get":{"operationId":"TrackingController_getEvents","parameters":[{"name":"mailingItemId","required":true,"in":"query","schema":{"type":"string"}},{"name":"dialogId","required":true,"in":"query","schema":{"type":"string"}},{"name":"contactId","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List raw tracking events (type filter: OPEN | CLICK | BOT_CLICK). Populated by campaign-sent links (mapped /t/c path + pixel); directly-created links clicked via /r do not appear here.","tags":["Tracking"],"x-required-scope":["mailing:read"]}},"/api/tracking/stats":{"get":{"operationId":"TrackingController_getStats","parameters":[{"name":"taskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregated tracking stats for a task","tags":["Tracking"],"x-required-scope":["mailing:read"]}},"/api/tracking/pixel-settings":{"get":{"operationId":"TrackingController_getPixelSettings","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get tenant pixel tracking settings","tags":["Tracking"],"x-required-scope":["mailing:read"]},"patch":{"operationId":"TrackingController_updatePixelSettings","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update tenant pixel tracking settings","tags":["Tracking"],"x-required-scope":["mailing:write"]}},"/api/tracking/analytics/stats":{"get":{"operationId":"TrackingController_getAnalyticsStats","parameters":[{"name":"taskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"dialogId","required":true,"in":"query","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Aggregated tracking analytics (open rate, click rate, unique opens/clicks). Populated only from campaign-sent tracking (pixel + mapped click path); directly-created createLink links produce no analytics.","tags":["Tracking"],"x-required-scope":["mailing:read"]}},"/api/tracking/analytics/timeline":{"get":{"operationId":"TrackingController_getTimeline","parameters":[{"name":"taskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"days","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get opens/clicks timeline","tags":["Tracking"],"x-required-scope":["mailing:read"]}},"/api/tracking/analytics/top-links":{"get":{"operationId":"TrackingController_getTopLinks","parameters":[{"name":"taskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Top clicked links with per-link click counts (from campaign-sent CLICK events).","tags":["Tracking"],"x-required-scope":["mailing:read"]}},"/api/tracking/analytics/email-clients":{"get":{"operationId":"TrackingController_getEmailClients","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get email client distribution from tracking events","tags":["Tracking"],"x-required-scope":["mailing:read"]}},"/api/tracking/analytics/devices":{"get":{"operationId":"TrackingController_getDevices","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get device type distribution from tracking events","tags":["Tracking"],"x-required-scope":["mailing:read"]}},"/api/tracking-domains":{"get":{"operationId":"TrackingDomainController_findAll","parameters":[{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List tracking domains","tags":["Tracking / Domain"]},"post":{"operationId":"TrackingDomainController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a tracking domain (starts as PENDING). External step: add a DNS CNAME → cnameTarget (default track.pixel.ldm-app.com) in the customer DNS zone, then run health-check/verify to make it ACTIVE. An ACTIVE domain is required for campaign link rewriting; set one as default for the open pixel.","tags":["Tracking / Domain"]}},"/api/tracking-domains/stats":{"get":{"operationId":"TrackingDomainController_getStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get tracking domain statistics","tags":["Tracking / Domain"],"x-required-scope":["mailing:read"]}},"/api/tracking-domains/{id}":{"get":{"operationId":"TrackingDomainController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a tracking domain by id","tags":["Tracking / Domain"]},"put":{"operationId":"TrackingDomainController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a tracking domain","tags":["Tracking / Domain"]},"delete":{"operationId":"TrackingDomainController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a tracking domain","tags":["Tracking / Domain"]}},"/api/tracking-domains/{id}/health-check":{"post":{"operationId":"TrackingDomainController_healthCheck","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run a health check for a tracking domain (verifies the DNS CNAME → cnameTarget and SSL). Passing DNS moves a PENDING domain toward ACTIVE.","tags":["Tracking / Domain"]}},"/api/tracking-domains/{id}/set-default":{"post":{"operationId":"TrackingDomainController_setDefault","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Set a tracking domain as the default (used for the open pixel; without a default the pixel falls back to APP_URL/api).","tags":["Tracking / Domain"]}},"/api/tracking-domains/monitoring":{"get":{"operationId":"TrackingDomainController_getMonitoring","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get tracking domain monitoring overview with click/send stats","tags":["Tracking / Domain"],"x-required-scope":["mailing:read"]}},"/api/tracking-domains/{id}/report-spam":{"post":{"operationId":"TrackingDomainController_reportSpam","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Report spam for a tracking domain (auto-pause at threshold)","tags":["Tracking / Domain"]}},"/api/redirect-sources":{"get":{"operationId":"RedirectSourceController_findAll","parameters":[{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"category","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List redirect sources","tags":["Tracking / Redirect Source"]},"post":{"operationId":"RedirectSourceController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a redirect source","tags":["Tracking / Redirect Source"]}},"/api/redirect-sources/stats":{"get":{"operationId":"RedirectSourceController_getStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get redirect source statistics","tags":["Tracking / Redirect Source"],"x-required-scope":["mailing:read"]}},"/api/redirect-sources/{id}":{"get":{"operationId":"RedirectSourceController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a redirect source by id","tags":["Tracking / Redirect Source"]},"put":{"operationId":"RedirectSourceController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a redirect source","tags":["Tracking / Redirect Source"]},"delete":{"operationId":"RedirectSourceController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a redirect source","tags":["Tracking / Redirect Source"]}},"/api/bot-list":{"get":{"operationId":"BotListController_stats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Bot-list stats (feed count, custom CIDR/UA, last refresh). GLOBAL cross-tenant list for the cloaking redirect layer (#214 phase 3, SUPER-only): matched entries mark a click as a bot on cloakMode=bot_split links (→ botDecoyUrl). Changes here affect bot detection for ALL tenants.","tags":["Tracking / Bot List"]}},"/api/bot-list/refresh":{"post":{"operationId":"BotListController_refresh","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reload external bot-feeds now (BOT_FEED_URLS) into the in-memory matcher. SUPER-only, global. Gated by BOT_FEED_ENABLED + RUN_CRON_JOBS; normally refreshed on a schedule.","tags":["Tracking / Bot List"],"x-required-scope":["admin:write"]}},"/api/bot-list/cidr":{"post":{"operationId":"BotListController_addCidr","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a custom bot CIDR to the GLOBAL bot-list (e.g. 203.0.113.0/24). Clicks from these IPs on cloakMode=bot_split links are deflected to botDecoyUrl (+BOT_CLICK). SUPER-only; affects all tenants — use narrow ranges.","tags":["Tracking / Bot List"],"x-required-scope":["admin:write"]},"delete":{"operationId":"BotListController_removeCidr","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove a custom bot CIDR from the GLOBAL bot-list. SUPER-only.","tags":["Tracking / Bot List"],"x-required-scope":["admin:write"]}},"/api/bot-list/ua":{"post":{"operationId":"BotListController_addUa","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a custom bot User-Agent regex to the GLOBAL bot-list (e.g. MyScanner). UA match → bot → deflect to botDecoyUrl on cloakMode=bot_split links. SUPER-only; affects all tenants.","tags":["Tracking / Bot List"],"x-required-scope":["admin:write"]},"delete":{"operationId":"BotListController_removeUa","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove a custom bot User-Agent regex from the GLOBAL bot-list. SUPER-only.","tags":["Tracking / Bot List"],"x-required-scope":["admin:write"]}},"/api/admin/browser-queue":{"get":{"operationId":"BrowserQueueController_getStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get browser queue stats and fair-share view","tags":["Browser Queue"]}},"/api/admin/browser-queue/jobs":{"get":{"operationId":"BrowserQueueController_getJobs","parameters":[{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"start","required":true,"in":"query","schema":{"type":"string"}},{"name":"end","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List browser queue jobs by status with pagination","tags":["Browser Queue"],"x-required-scope":["admin:read"]}},"/api/admin/browser-queue/{id}/cancel":{"post":{"operationId":"BrowserQueueController_cancelJob","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel a browser queue job by id","tags":["Browser Queue"]}},"/api/admin/browser-queue/{id}/retry":{"post":{"operationId":"BrowserQueueController_retryJob","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Retry a failed browser queue job","tags":["Browser Queue"]}},"/api/admin/browser-queue/pause":{"post":{"operationId":"BrowserQueueController_pause","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Pause the browser queue","tags":["Browser Queue"],"x-required-scope":["admin:write"]}},"/api/admin/browser-queue/resume":{"post":{"operationId":"BrowserQueueController_resume","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Resume the browser queue","tags":["Browser Queue"],"x-required-scope":["admin:write"]}},"/api/files/images/import":{"post":{"operationId":"FilesController_importImages","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageImportDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Import images from a source attachment into tenant storage","tags":["Files"],"x-required-scope":["files:write"]}},"/api/files/upload":{"post":{"operationId":"FilesController_uploadImage","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Upload an image for creatives (max 5 MB)","tags":["Files"],"x-required-scope":["files:write"]}},"/api/files/images":{"get":{"operationId":"FilesController_listImages","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List uploaded creative images for the tenant","tags":["Files"],"x-required-scope":["files:read"]}},"/api/files/images/{filename}":{"delete":{"operationId":"FilesController_deleteImage","parameters":[{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a tenant-scoped creative image","tags":["Files"]}},"/api/files/assets":{"post":{"operationId":"FilesController_uploadAsset","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Upload a tenant asset (signature, PDF photo, max 30 MB)","tags":["Files"],"x-required-scope":["files:write"]},"get":{"operationId":"FilesController_listAssets","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List tenant assets","tags":["Files"],"x-required-scope":["files:read"]}},"/api/files/assets/quota":{"get":{"operationId":"FilesController_getAssetsQuota","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get tenant asset storage usage and quota","tags":["Files"],"x-required-scope":["files:read"]}},"/api/files/assets/{filename}":{"delete":{"operationId":"FilesController_deleteAsset","parameters":[{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a tenant asset","tags":["Files"]}},"/api/files":{"get":{"operationId":"FilesController_findAll","parameters":[{"name":"contactId","required":true,"in":"query","schema":{"type":"string"}},{"name":"companyId","required":true,"in":"query","schema":{"type":"string"}},{"name":"leadId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List file attachments for a contact, company or lead","tags":["Files"]},"post":{"operationId":"FilesController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachEntityFileDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Upload a file attachment for a contact, company or lead (max 30 MB)","tags":["Files"]}},"/api/files/{id}/download":{"get":{"operationId":"FilesController_download","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download a file attachment (authorized, streams real bytes)","tags":["Files"]}},"/api/files/{id}":{"delete":{"operationId":"FilesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a file attachment record","tags":["Files"]}},"/api/files/library/quota":{"get":{"operationId":"FilesController_getLibraryQuota","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Library storage usage and quota (500 MB, purpose=LIBRARY, separate from the 30 MB branding quota)","tags":["Files"],"x-required-scope":["files:read"]}},"/api/files/library":{"get":{"operationId":"FilesController_listLibrary","parameters":[{"name":"briefId","required":true,"in":"query","schema":{"type":"string"}},{"name":"leadId","required":true,"in":"query","schema":{"type":"string"}},{"name":"contactId","required":true,"in":"query","schema":{"type":"string"}},{"name":"companyId","required":true,"in":"query","schema":{"type":"string"}},{"name":"purpose","required":true,"in":"query","schema":{}},{"name":"kind","required":true,"in":"query","schema":{}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List the unified files-and-links library, optionally filtered by brief/lead/contact/company/purpose/kind/search","tags":["Files"],"x-required-scope":["files:read"]},"post":{"operationId":"FilesController_uploadLibraryItem","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Omit + kind=LINK to add a link instead of a file"},"kind":{"type":"string","enum":["FILE","LINK"],"description":"Defaults to FILE when a file is supplied"},"url":{"type":"string","description":"Required when kind=LINK — http(s) only"},"title":{"type":"string"},"description":{"type":"string"},"briefId":{"type":"string"},"leadId":{"type":"string"},"contactId":{"type":"string"},"companyId":{"type":"string"}}}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a library item: EITHER a file (multipart form field \"file\", max 100 MiB, whitelist pdf/doc(x)/xls(x)/ppt(x)/csv/txt/md/rtf/odt/ods/jpg/jpeg/png/webp/gif/svg/zip) OR a link (no file — send {\"kind\":\"LINK\",\"url\":\"https://...\"}). Optional {title, description, briefId, leadId, contactId, companyId} attach it right away. MCP callers: this route is multipart-declared — pass {\"file\":{\"filename\",\"contentBase64\",\"mimeType\"}} to upload bytes, or omit \"file\" and pass \"body\":{\"kind\":\"LINK\",\"url\":...} for a link.","tags":["Files"],"x-required-scope":["files:write"]}},"/api/files/library/{id}/download":{"get":{"operationId":"FilesController_downloadLibraryItem","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download a library file with authorization (never public — Content-Disposition: attachment)","tags":["Files"]}},"/api/files/library/{id}/content":{"get":{"operationId":"FilesController_readLibraryContent","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"resource","required":false,"in":"query","schema":{"enum":["text","sections","tableRows","hyperlinks","images","embeddedObjects","parts"],"type":"string"}},{"name":"cursor","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"integer","minimum":1,"maximum":10,"default":3}},{"name":"imageRef","required":false,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Read a library document as bounded source-backed text/structure/image pages; imageRef yields a real MCP image block (#768)","tags":["Files"]}},"/api/files/library/{id}":{"patch":{"operationId":"FilesController_updateLibraryItem","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLibraryItemDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Rename / reattach / detach a library item (title, description, briefId/leadId/contactId/companyId; null = detach, keeps it in the library)","tags":["Files"]},"delete":{"operationId":"FilesController_removeLibraryItem","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a library item — removes the DB row AND the bytes on disk (link: DB row only)","tags":["Files"]}},"/api/uploads/images/{tenantDbName}/{filename}":{"get":{"operationId":"FileServeController_serveImage","parameters":[{"name":"tenantDbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Serve a tenant-scoped uploaded image","tags":["Files / Serve"]}},"/api/uploads/tenant-assets/{tenantDbName}/{filename}":{"get":{"operationId":"FileServeController_serveTenantAsset","parameters":[{"name":"tenantDbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Serve a tenant-scoped asset (signature, PDF photo)","tags":["Files / Serve"]}},"/api/uploads/dialog-attachments/{tenantDbName}/{filename}":{"get":{"operationId":"FileServeController_serveDialogAttachment","parameters":[{"name":"tenantDbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download an inbound dialog attachment (#176)","tags":["Files / Serve"]}},"/api/uploads/avatars/{filename}":{"get":{"operationId":"FileServeController_serveAvatar","parameters":[{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Serve a user avatar image","tags":["Files / Serve"]}},"/api/content-analyzer/check":{"post":{"operationId":"ContentAnalyzerController_check","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckContentDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Analyze email subject/body for spam triggers and return score 0..100. customRules (#100) lets a caller preview the effect of a not-yet-saved global/campaign Tier-1 rule before writing it via /settings/auditor-rules or campaign auditorConfig.extraRules.","tags":["Content Analyzer"],"x-required-scope":["mailing:read"]}},"/api/tasks":{"get":{"operationId":"TasksController_findAll","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"methodId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List tasks with pagination and status/method filters","tags":["Tasks"]},"post":{"operationId":"TasksController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTaskDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a task. SITE SCORING (lead gen): methodId=22 + methodName=\"scoring\" + companyListId (items are populated from the company list on start) → POST /tasks/:id/steps (SITE_AVAILABILITY, then AI_CONTENT) → POST /tasks/:id/start. Other methodId values: 11=email validation, 14=ICP review, 15=DIG, 12=mailing (legacy — prefer /campaigns).","tags":["Tasks"]}},"/api/tasks/{id}":{"get":{"operationId":"TasksController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single task by ID","tags":["Tasks"]},"patch":{"operationId":"TasksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTaskDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update task description, configuration, or schedule","tags":["Tasks"]},"delete":{"operationId":"TasksController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a task","tags":["Tasks"]}},"/api/tasks/{id}/branches":{"get":{"operationId":"TasksController_listBranches","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List sub-sequence branches of a task","tags":["Tasks"]},"post":{"operationId":"TasksController_createBranch","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBranchDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a sub-sequence branch off a task","tags":["Tasks"]}},"/api/tasks/{id}/branches/{branchId}/enroll":{"post":{"operationId":"TasksController_enrollInBranch","parameters":[{"name":"branchId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollInBranchDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Enroll contacts into a task branch","tags":["Tasks"]}},"/api/tasks/{id}/items":{"get":{"operationId":"TasksController_getItems","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List items processed by a task with pagination","tags":["Tasks"]}},"/api/tasks/{id}/items/{itemId}":{"get":{"operationId":"TasksController_getItem","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"itemId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single task item by ID","tags":["Tasks"]}},"/api/tasks/{id}/stats":{"get":{"operationId":"TasksController_getStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregate stats for a task","tags":["Tasks"]}},"/api/tasks/{id}/errors":{"get":{"operationId":"TasksController_getErrors","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List errors encountered during a task run","tags":["Tasks"]}},"/api/tasks/{id}/start":{"post":{"operationId":"TasksController_start","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartTaskDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Start (or resume) a task. If items are empty, they are populated from the task's contactListId/companyListId. Progress: GET /tasks/:id (processedItems/totalItems); for scoring: GET /tasks/:id/scoring-stats and /tasks/:id/scoring-results?status=ACTIVE (score, companyType, contacts found on the site).","tags":["Tasks"]}},"/api/tasks/{id}/pause":{"post":{"operationId":"TasksController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Pause a running task","tags":["Tasks"]}},"/api/tasks/{id}/stop":{"post":{"operationId":"TasksController_stop","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Stop a task (mark as DONE)","tags":["Tasks"]}},"/api/tasks/{id}/restart":{"post":{"operationId":"TasksController_restart","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Resume a task: resets ERROR items to PENDING and sets status=ACTIVE. Does NOT re-process already-scored items — response names preservedItems (untouched) and resetToRetryCount. For a targeted re-score of e.g. SCORED_BELOW_THRESHOLD, use POST :id/scoring-results/retry instead (#1099).","tags":["Tasks"]}},"/api/tasks/{id}/analytics":{"get":{"operationId":"TasksController_getAnalytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get analytics for a task (open/click/reply rates)","tags":["Tasks"]}},"/api/tasks/{id}/monitor":{"get":{"operationId":"TasksController_getMonitor","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get real-time monitor data for a running task","tags":["Tasks"]}},"/api/tasks/{id}/report.csv":{"get":{"operationId":"TasksController_getReportCsv","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download a CSV report of all task items","tags":["Tasks"]}},"/api/tasks/{id}/circuit-breaker":{"get":{"operationId":"TasksController_getCircuitBreaker","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the circuit-breaker state for a task","tags":["Tasks"]}},"/api/tasks/{id}/circuit-breaker/reset":{"post":{"operationId":"TasksController_resetCircuitBreaker","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset a tripped circuit breaker for a task","tags":["Tasks"]}},"/api/tasks/{id}/steps":{"get":{"operationId":"TasksController_getPipelineSteps","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List pipeline steps configured on a task","tags":["Tasks"]},"post":{"operationId":"TasksController_addPipelineStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddPipelineStepDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a pipeline step to a task. Types: SITE_AVAILABILITY, AI_CONTENT, KEYWORDS, EMAIL_EXTRACT, PHONE_EXTRACT, SOCIAL_LINKS, TECH_DETECT, GEO_FILTER, NALOG_LOOKUP, AI_CARD_FIELD, and others. For AI_CONTENT: config.messages=[{role:system,...},{role:user,...}] with placeholders {-Variable.page_text-}/{-Variable.domain-}, config.min_score (success when score>=min_score). For AI_CARD_FIELD (#1035, requires item.contactId; or item.companyId when config.targetEntity=COMPANY — a company with no single contact is covered too): config.promptTemplate with the resolver's canonical variables ({{firstName}}, {company.name}, ccf_...), config.targetEntity=CONTACT|COMPANY|LEAD (LEAD requires item.contactId — TaskItem does not store leadId, the target becomes that contact's single lead; 0 leads → no_lead, more than one → ambiguous_lead, the step does not guess), config.targetFieldId=id of an existing CustomFieldDefinition, config.fallback — writes the result to that custom field WITHOUT hitting the site; a repeat on an already-computed entity×field pair does not invoke AI again (dedup by non-empty field value). Routing: onSuccess/onFail/onError = CONTINUE|STOP|MOVE_TO_LIST (+onSuccessTarget=list id)|DELETE. Typical scoring: step 1 SITE_AVAILABILITY (onFail=STOP), step 2 AI_CONTENT (onSuccess=MOVE_TO_LIST into the target list).","tags":["Tasks"]}},"/api/tasks/{id}/steps/reorder":{"put":{"operationId":"TasksController_reorderPipelineSteps","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderStepsDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder pipeline steps in a task","tags":["Tasks"]}},"/api/tasks/{id}/steps/{stepId}":{"patch":{"operationId":"TasksController_updatePipelineStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePipelineStepDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a single pipeline step","tags":["Tasks"]},"delete":{"operationId":"TasksController_removePipelineStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a pipeline step from a task","tags":["Tasks"]}},"/api/tasks/{id}/scoring-results":{"get":{"operationId":"TasksController_getScoringResults","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":false,"in":"query","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","schema":{"type":"string"}},{"name":"contradictory","required":false,"in":"query","description":"narrows the result set to records flagged with a contradiction, the same selection as contradictoryOnly on retry","schema":{"type":"string"}},{"name":"reasonCode","required":false,"in":"query","description":"Canonical reason or unclassified; shared with CSV and scoped retry","schema":{"type":"string"}},{"name":"unique","required":false,"in":"query","description":"true: latest result per input entity, same population as scoring-stats","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List scoring results for a task with pagination. contradictory=true narrows to results whose stepResults carry a contradiction flag (data.contradictoryFields non-empty on any step) — same detection as POST :id/scoring-results/retry contradictoryOnly (#1113).","tags":["Tasks"]}},"/api/tasks/{id}/scoring-stats":{"get":{"operationId":"TasksController_getScoringStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregate scoring statistics for a task","tags":["Tasks"]}},"/api/tasks/{id}/scoring-results/{resultId}":{"delete":{"operationId":"TasksController_deleteScoringResult","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"resultId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a single scoring result","tags":["Tasks"]}},"/api/tasks/{id}/scoring-results/retry":{"post":{"operationId":"TasksController_retryScoringResults","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryScoringResultsDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#1099: retry SELECTION of scoring results — by statuses (ERROR|UNAVAILABLE|NO_WWW|SCORED_BELOW_THRESHOLD|SKIPPED|STUB_MATERIAL, #1146) and/or the processedAfter/processedBefore window. UNAVAILABLE (dead domains) is excluded by default — includeUnavailable=true to explicitly include it. No body — ERROR only. WARNING: behavior change — a call without a body used to take ERROR+UNAVAILABLE (hard-coded); now dead domains require an explicit includeUnavailable=true. #1128: OR a targeted selection by resultIds/companyIds (specific record ids, regardless of status) — the only way to recompute chosen cards without re-evaluating the rest via the window. ACTIVE (an already-accepted honest verdict) in this list is unreachable without includeActive=true — the same device as includeUnavailable for statuses; without the flag such a record is silently skipped. Records with a foreign taskId in resultIds/companyIds are silently ignored. Statuses/window are not used in selection when resultIds/companyIds are passed. includeActive=true writes a persistent journal event for EVERY reset ACTIVE record (who/when/how many) — see GET /tasks/:id/scoring-results/:resultId/events, kind=active_reset_by_retry. #1128 round 3: preview=true — a read-only preview of the SAME selection: returns wouldRetryCount/resultIds WITHOUT mutating ScoringResult/TaskItem and without a journal entry; the retry does not run. #1113 goal 2: contradictoryOnly=true narrows the selection to cards where a contradiction flag fired (data.contradictoryFields at any step) — an additional AND condition on top of the other filters.","tags":["Tasks"]}},"/api/tasks/{id}/scoring-results/{resultId}/events":{"get":{"operationId":"TasksController_getScoringStepEvents","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"resultId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#975: paginated step journal for a single scoring card (requested/success/fail/error/interrupted/resumed_after_restart, seq by time)","tags":["Tasks"]}},"/api/tasks/{id}/scoring-results.csv":{"get":{"operationId":"TasksController_getScoringResultsCsv","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"reasonCode","required":false,"in":"query","description":"Canonical reason or unclassified, same filter as scoring-results","schema":{"type":"string"}},{"name":"unique","required":false,"in":"query","description":"true: latest result per input entity","schema":{"type":"string"}},{"name":"contradictory","required":false,"in":"query","description":"true: only results flagged with a contradiction","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download a CSV of scoring results","tags":["Tasks"]}},"/api/tasks/{id}/error-settings":{"get":{"operationId":"TasksController_getErrorSettings","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the error-handling settings for a task","tags":["Tasks"]},"patch":{"operationId":"TasksController_updateErrorSettings","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateErrorSettingsDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update error-handling settings for a task","tags":["Tasks"]}},"/api/tasks/{id}/memory":{"get":{"operationId":"TasksController_getMemory","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get AI memory instructions for a task","tags":["Tasks"]},"patch":{"operationId":"TasksController_updateMemory","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTaskMemoryDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update AI memory instructions for a task","tags":["Tasks"]}},"/api/tasks/{id}/ai-settings":{"get":{"operationId":"TasksController_getAiSettings","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the AI provider/model settings for a task","tags":["Tasks"]},"patch":{"operationId":"TasksController_updateAiSettings","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiSettingsDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the AI provider/model settings for a task","tags":["Tasks"]}},"/api/tasks/{id}/cron":{"get":{"operationId":"TasksController_getCronSettings","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the cron scheduling settings for a task","tags":["Tasks"]},"patch":{"operationId":"TasksController_updateCronSettings","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCronSettingsDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the cron scheduling settings for a task","tags":["Tasks"]}},"/api/tasks/{id}/cron/trigger":{"post":{"operationId":"TasksController_triggerCron","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually trigger a task cron run","tags":["Tasks"]}},"/api/creatives":{"get":{"operationId":"CreativesController_findAll","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List creatives with pagination and search","tags":["Creatives"]},"post":{"operationId":"CreativesController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCreativeDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new creative","tags":["Creatives"]}},"/api/creatives/ai-generate":{"post":{"operationId":"CreativesController_aiGenerate","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiGenerateCreativeDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate a creative draft via AI","tags":["Creatives"],"x-required-scope":["creatives:write"]}},"/api/creatives/autopilot-v2":{"post":{"operationId":"CreativesController_createAutopilotV2","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new Autopilot v2 creative","tags":["Creatives"],"x-required-scope":["creatives:write"]}},"/api/creatives/pdf-status":{"get":{"operationId":"CreativesController_pdfStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the PDF generation queue status","tags":["Creatives"],"x-required-scope":["creatives:read"]}},"/api/creatives/pdf/{filename}":{"get":{"operationId":"CreativesController_servePdf","parameters":[{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download a generated PDF by filename","tags":["Creatives"]}},"/api/creatives/variables/available":{"get":{"operationId":"CreativesController_getAvailableVariables","parameters":[{"name":"source","required":false,"in":"query","description":"Legacy single-source filter (use `sources` instead)","schema":{"type":"string"}},{"name":"sources","required":false,"in":"query","description":"CSV of contactList,company,pipeline","schema":{"type":"string"}},{"name":"contactListId","required":false,"in":"query","schema":{"type":"string"}},{"name":"companyId","required":false,"in":"query","schema":{"type":"string"}},{"name":"pipelineId","required":false,"in":"query","schema":{"type":"string"}},{"name":"stageId","required":false,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List available template variables","tags":["Creatives"],"x-required-scope":["creatives:read"]}},"/api/creatives/{id}":{"get":{"operationId":"CreativesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single creative by ID","tags":["Creatives"]},"patch":{"operationId":"CreativesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCreativeDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a creative","tags":["Creatives"]},"delete":{"operationId":"CreativesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a creative","tags":["Creatives"]}},"/api/creatives/{id}/brief-intake":{"get":{"operationId":"CreativesController_briefIntake","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"locale","required":false,"in":"query","schema":{"enum":["ru","en"],"type":"string"}},{"name":"accept-language","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Canonical brief intake email and localized help for customer materials linked to this creative","tags":["Creatives"]}},"/api/creatives/{id}/stats":{"get":{"operationId":"CreativesController_getStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get stats for a creative","tags":["Creatives"]}},"/api/creatives/{id}/preview":{"post":{"operationId":"CreativesController_preview","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewCreativeDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Render a preview of a creative for a sample contact","tags":["Creatives"]}},"/api/creatives/{id}/inbox-placement-test":{"post":{"operationId":"CreativesController_startInboxPlacementTest","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartInboxPlacementTestDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Start an inbox placement test for a creative","tags":["Creatives"]}},"/api/creatives/{id}/inbox-placement-test/{token}":{"get":{"operationId":"CreativesController_getInboxPlacementTest","parameters":[{"name":"token","required":true,"in":"path","description":"Token returned by startInboxPlacementTest","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","description":"Creative id the placement test belongs to","schema":{}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the result of an inbox placement test","tags":["Creatives"]}},"/api/creatives/{id}/variables":{"get":{"operationId":"CreativesController_getVariables","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get template variables used in a creative","tags":["Creatives"]}},"/api/creatives/{id}/spintax":{"get":{"operationId":"CreativesController_analyzeSpintax","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Analyze spintax patterns in a creative","tags":["Creatives"]}},"/api/creatives/{id}/copy":{"post":{"operationId":"CreativesController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Duplicate a creative","tags":["Creatives"]}},"/api/creatives/{id}/versions":{"get":{"operationId":"CreativesController_getVersions","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List versions of a creative","tags":["Creatives"]},"post":{"operationId":"CreativesController_createVersion","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new version of a creative","tags":["Creatives"]}},"/api/creatives/{id}/versions/{versionId}/restore":{"post":{"operationId":"CreativesController_restoreVersion","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"versionId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Restore a creative to a prior version","tags":["Creatives"]}},"/api/creatives/{id}/test-sends":{"get":{"operationId":"CreativesController_getTestSends","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List test sends of a creative","tags":["Creatives"]}},"/api/creatives/{id}/test-send":{"post":{"operationId":"CreativesController_createTestSend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSendDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Send a test copy of this creative. sender=\"account\" (default, unchanged behaviour) needs a connected email account: pass accountId AND toEmail. sender=\"platform\" needs NO connected account and NO toEmail at all — omit toEmail and it sends from the LDM platform mailbox (same transport as signup email) straight to the address the TENANT OWNER registered with; this is the intended zero-config call. If you DO pass toEmail with sender=\"platform\" it must equal that same registration address exactly or the call is refused (not an open relay, #801) — passing any other address never sends anywhere else, it just fails closed. Use \"platform\" the moment a creative exists, before any mailbox is connected, to see the rendered email + attachment land for real. Rate-limited to 5 platform sends/hour per tenant. The response carries a disclaimer: placement via the platform mailbox says NOTHING about the client's own sending domain reputation — it only proves the creative renders and the attachment attaches; re-test with sender=\"account\" before trusting placement for a real campaign. Zero connected accounts AND no sender given → the 400 body lists BOTH ways forward (connect one, or use sender=\"platform\" with no toEmail).","tags":["Creatives"]}},"/api/creatives/moderation/pending":{"get":{"operationId":"CreativesController_listPendingChannelCreatives","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List channel creatives pending moderation (SUPER)","tags":["Creatives"],"x-required-scope":["creatives:read"]}},"/api/creatives/{id}/moderate":{"post":{"operationId":"CreativesController_moderateChannelCreative","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Approve/reject a channel creative (SUPER)","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/generate-prompt":{"post":{"operationId":"CreativesController_autopilotGeneratePrompt","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate an Autopilot meta-prompt for a creative","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/v2/generate-prompt":{"post":{"operationId":"CreativesController_autopilotGeneratePromptV2","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate an Autopilot v2 meta-prompt","tags":["Creatives"]}},"/api/creatives/{id}/rules/bank/generate":{"post":{"operationId":"CreativesController_bankV2Generate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Enqueue a bank-generation job for a creative","tags":["Creatives"]}},"/api/creatives/{id}/rules/bank/jobs/{jobId}":{"get":{"operationId":"CreativesController_bankGenGet","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the status of a bank-generation job","tags":["Creatives"]}},"/api/creatives/{id}/rules/bank/jobs":{"get":{"operationId":"CreativesController_bankGenList","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List bank-generation jobs for a creative","tags":["Creatives"]}},"/api/creatives/{id}/rules/bank/jobs/{jobId}/cancel":{"post":{"operationId":"CreativesController_bankGenCancel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel a bank-generation job","tags":["Creatives"]}},"/api/creatives/{id}/rules/bank/{tid}":{"patch":{"operationId":"CreativesController_bankV2Edit","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"tid","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a single bank template (rules v2)","tags":["Creatives"]}},"/api/creatives/{id}/rules/bank/{tid}/action":{"post":{"operationId":"CreativesController_bankV2Action","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"tid","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run an action on a bank template (approve/reject/etc.)","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/preview-meta-prompt":{"post":{"operationId":"CreativesController_autopilotPreviewMetaPrompt","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview the meta-prompt for a creative","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/segment/{segmentId}/meta-prompt":{"patch":{"operationId":"CreativesController_autopilotSegmentMetaPrompt","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"segmentId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the meta-prompt of a segment","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/test-batch":{"post":{"operationId":"CreativesController_autopilotTestBatch","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run a test batch through Autopilot","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/generate":{"post":{"operationId":"CreativesController_bankGenerate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Trigger Autopilot bank generation","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/pipeline/{jobId}":{"get":{"operationId":"CreativesController_bankPipelineStatus","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the status of an Autopilot bank pipeline job","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank":{"get":{"operationId":"CreativesController_bankGet","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"segmentId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List Autopilot bank templates","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/templates/{templateId}":{"patch":{"operationId":"CreativesController_bankTemplateAction","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an Autopilot bank template","tags":["Creatives"]},"delete":{"operationId":"CreativesController_bankDeleteTemplate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a single Autopilot bank template","tags":["Creatives"]},"get":{"operationId":"CreativesController_bankGetTemplate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}},{"name":"segmentId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single Autopilot bank template","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/approve-all":{"post":{"operationId":"CreativesController_bankApproveAll","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Approve all pending Autopilot bank templates","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/templates":{"delete":{"operationId":"CreativesController_bankDeleteAll","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete all Autopilot bank templates","tags":["Creatives"]},"post":{"operationId":"CreativesController_bankCreateTemplate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new Autopilot bank template","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/regenerate":{"post":{"operationId":"CreativesController_bankRegenerate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Regenerate Autopilot bank templates","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/config":{"patch":{"operationId":"CreativesController_bankUpdateConfig","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update Autopilot bank configuration","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/preview":{"post":{"operationId":"CreativesController_bankPreview","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview Autopilot bank output","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/preview-with-qc":{"post":{"operationId":"CreativesController_bankPreviewWithQc","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview Autopilot bank output with QC checks","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/usage":{"get":{"operationId":"CreativesController_bankUsage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get Autopilot bank usage stats","tags":["Creatives"]}},"/api/creatives/{id}/generate-for-contact":{"post":{"operationId":"CreativesController_generateForContact","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate a creative for a specific contact","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/dashboard":{"get":{"operationId":"CreativesController_autopilotDashboard","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"verdict","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the Autopilot dashboard for a creative","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/dashboard/backfill-t2":{"post":{"operationId":"CreativesController_backfillTier2","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Backfill Tier-2 QC results on the Autopilot dashboard","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/auditor":{"get":{"operationId":"CreativesController_auditorGet","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the Autopilot auditor configuration","tags":["Creatives"]},"patch":{"operationId":"CreativesController_auditorUpdate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the Autopilot auditor configuration (proxies `enabled` to canon; see AuditorService JSDoc for the rest)","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/auditor/start":{"post":{"operationId":"CreativesController_auditorStart","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Start the Autopilot auditor","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/auditor/pause":{"post":{"operationId":"CreativesController_auditorPause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Pause the Autopilot auditor","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/auditor/stop":{"post":{"operationId":"CreativesController_auditorStop","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Stop the Autopilot auditor","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/auditor/run":{"post":{"operationId":"CreativesController_auditorRun","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run the Autopilot auditor once","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/auditor/logs":{"get":{"operationId":"CreativesController_auditorLogs","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get logs for the Autopilot auditor","tags":["Creatives"]},"delete":{"operationId":"CreativesController_auditorClearLogs","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Clear logs for the Autopilot auditor","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/checklist":{"get":{"operationId":"CreativesController_checklistGet","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the Autopilot launch checklist","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/checklist/sandbox":{"post":{"operationId":"CreativesController_checklistSandbox","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run the sandbox step of the Autopilot checklist","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/checklist/qc":{"post":{"operationId":"CreativesController_checklistQC","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run the QC step of the Autopilot checklist","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/checklist/test-send":{"post":{"operationId":"CreativesController_checklistTestSend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run the test-send step of the Autopilot checklist","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/checklist/cost-estimate":{"post":{"operationId":"CreativesController_checklistCostEstimate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Estimate cost for the Autopilot launch","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/checklist/lock":{"post":{"operationId":"CreativesController_checklistLock","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Lock the Autopilot checklist before launch","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/checklist/unlock":{"post":{"operationId":"CreativesController_checklistUnlock","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Unlock the Autopilot checklist","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/qc/config":{"get":{"operationId":"CreativesController_qcConfig","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the Autopilot QC configuration","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/qc/rules":{"patch":{"operationId":"CreativesController_qcUpdateRules","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update Autopilot QC Tier-1 rules","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/qc/tier2":{"patch":{"operationId":"CreativesController_qcUpdateTier2","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update Autopilot QC Tier-2 configuration (proxies enabled/threshold/samplingRate/model to canon; see JSDoc for the `checks` exception)","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/qc/test":{"post":{"operationId":"CreativesController_qcTest","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run a QC test on sample content","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/run-observable":{"post":{"operationId":"CreativesController_sandboxRunObservable","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Start an observable Autopilot sandbox run","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/observable-status":{"get":{"operationId":"CreativesController_sandboxObservableStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the status of an observable sandbox run","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/cancel-observable":{"post":{"operationId":"CreativesController_sandboxCancelObservable","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel an observable sandbox run","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/observable":{"delete":{"operationId":"CreativesController_sandboxClearObservable","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete the observable sandbox state","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/run":{"post":{"operationId":"CreativesController_sandboxRun","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run the Autopilot sandbox pipeline","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/available-vars":{"get":{"operationId":"CreativesController_sandboxAvailableVars","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"source","required":false,"in":"query","description":"Legacy single-source filter (use `sources` instead)","schema":{"type":"string"}},{"name":"sources","required":false,"in":"query","description":"CSV of contactList,company,pipeline","schema":{"type":"string"}},{"name":"contactListId","required":false,"in":"query","schema":{"type":"string"}},{"name":"companyId","required":false,"in":"query","schema":{"type":"string"}},{"name":"pipelineId","required":false,"in":"query","schema":{"type":"string"}},{"name":"stageId","required":false,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List variables available to the sandbox","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/variable-values":{"get":{"operationId":"CreativesController_variableValues","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"sources","required":true,"in":"query","schema":{"type":"string"}},{"name":"contactListId","required":true,"in":"query","schema":{"type":"string"}},{"name":"companyId","required":true,"in":"query","schema":{"type":"string"}},{"name":"pipelineId","required":true,"in":"query","schema":{"type":"string"}},{"name":"stageId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get computed variable values for a creative","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/segment-count":{"post":{"operationId":"CreativesController_segmentCount","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Count contacts matching a sandbox segment","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/all-field-definitions":{"get":{"operationId":"CreativesController_allFieldDefinitions","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get all field definitions available to Autopilot","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/match-contacts":{"post":{"operationId":"CreativesController_sandboxMatchContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Match contacts against a sandbox segment definition","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/test-selection":{"post":{"operationId":"CreativesController_sandboxTestSelection","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run a test selection against the sandbox","tags":["Creatives"]},"get":{"operationId":"CreativesController_sandboxGetTestSelection","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the cached test selection result","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/history":{"get":{"operationId":"CreativesController_sandboxHistory","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the sandbox run history","tags":["Creatives"]},"delete":{"operationId":"CreativesController_sandboxHistoryClearAll","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Clear the sandbox run history","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/history/{idx}":{"delete":{"operationId":"CreativesController_sandboxHistoryDeleteOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"idx","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete one entry from the sandbox history","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/status":{"get":{"operationId":"CreativesController_sandboxStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the current sandbox status","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/cancel":{"post":{"operationId":"CreativesController_sandboxCancel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel a running sandbox run","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/sandbox/apply":{"post":{"operationId":"CreativesController_sandboxApply","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Apply the sandbox result to the creative","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/variable-rules":{"patch":{"operationId":"CreativesController_saveVariableRules","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveVariableRulesDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the Autopilot variable rules","tags":["Creatives"]},"get":{"operationId":"CreativesController_getVariableRules","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the Autopilot variable rules","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/variable-rules/preview":{"post":{"operationId":"CreativesController_previewVariableRules","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview the effect of variable rules","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/pipeline/run":{"post":{"operationId":"CreativesController_runPipeline","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run the full Autopilot generation pipeline","tags":["Creatives"]}},"/api/creatives/{id}/pdf-generations/{generationId}":{"get":{"operationId":"CreativesController_getPdfGenerationStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"generationId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the status of an asynchronous PDF generation","tags":["Creatives"]}},"/api/creatives/{id}/generate-pdf":{"post":{"operationId":"CreativesController_generatePdf","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneratePdfDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate a PDF from a creative","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/v2/meta-prompt-base":{"get":{"operationId":"CreativesController_getMetaPromptBaseV2","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the base meta-prompt for Autopilot v2","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/meta-prompt":{"get":{"operationId":"CreativesController_getMetaPrompt","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"segmentId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the meta-prompt for a creative","tags":["Creatives"]},"put":{"operationId":"CreativesController_putMetaPrompt","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"segmentId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Replace the meta-prompt for a creative","tags":["Creatives"]},"delete":{"operationId":"CreativesController_deleteMetaPrompt","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"segmentId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete the meta-prompt of a creative","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/templates/{templateId}/stats":{"get":{"operationId":"CreativesController_bankGetTemplateStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}},{"name":"segmentId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get stats for a single Autopilot bank template","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/templates/generate-one":{"post":{"operationId":"CreativesController_bankGenerateOneTemplate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate a single Autopilot bank template","tags":["Creatives"]}},"/api/creatives/{id}/autopilot/bank/templates/{templateId}/content":{"put":{"operationId":"CreativesController_bankUpdateTemplateContent","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Replace the content of a bank template","tags":["Creatives"]}},"/api/creatives/pdf-link/{token}":{"get":{"operationId":"CreativePdfLinkController_servePdfByToken","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Download a generated PDF via a signed, tenant-bound, time-limited link (#1015, no auth headers needed)","tags":["Creatives"]}},"/api/variable-resolver/resolve":{"post":{"operationId":"VariableResolverController_resolve","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveVariablesDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Resolve contact context and variable map for templates","tags":["Variable Resolver"]}},"/api/variable-resolver/available-variables":{"get":{"operationId":"VariableResolverController_getAvailableVariables","parameters":[{"name":"source","required":false,"in":"query","description":"Legacy single-source filter (use `sources` instead)","schema":{"type":"string"}},{"name":"sources","required":false,"in":"query","description":"CSV of contactList,company,pipeline","schema":{"type":"string"}},{"name":"contactListId","required":false,"in":"query","schema":{"type":"string"}},{"name":"companyId","required":false,"in":"query","schema":{"type":"string"}},{"name":"pipelineId","required":false,"in":"query","schema":{"type":"string"}},{"name":"stageId","required":false,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all available template variables (canonical — same source as /creatives/variables/available)","tags":["Variable Resolver"]}},"/api/briefs/schemas":{"get":{"operationId":"BriefsController_getSchemas","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get available brief JSON schemas","tags":["Briefs"],"x-required-scope":["briefs:read"]}},"/api/briefs/intake":{"get":{"operationId":"BriefsController_intake","parameters":[{"name":"briefId","required":false,"in":"query","description":"Existing Brief id. Pass this (or briefUrl) to get scope=brief_direct and the same intakeEmail as Brief UI/expert. Omit only when no Brief exists.","schema":{"type":"string"}},{"name":"briefUrl","required":false,"in":"query","description":"Existing Brief UI URL shaped as /crm/briefs/{briefId}. Pass this (or briefId) for scope=brief_direct; never use workspace intake for an existing Brief.","schema":{"type":"string"}},{"name":"locale","required":false,"in":"query","schema":{"enum":["ru","en"],"type":"string"}},{"name":"accept-language","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Existing Brief intake address by briefId/briefUrl; omit both only before a Brief exists for workspace unassigned intake (#755)","tags":["Briefs"],"x-required-scope":["briefs:read"]}},"/api/briefs/intake/items":{"get":{"operationId":"BriefsController_listIntakeItems","parameters":[{"name":"paged","required":false,"in":"query","description":"Return {items,hasMore,nextCursor,limit}; legacy false keeps the historical array response.","schema":{"default":false,"type":"boolean"}},{"name":"status","required":false,"in":"query","schema":{"enum":["NEW","IN_REVIEW","LINKED_TO_BRIEF","IGNORED","REJECTED"],"type":"string"}},{"name":"briefId","required":false,"in":"query","description":"Exact Brief id.","schema":{"maxLength":128,"type":"string"}},{"name":"sender","required":false,"in":"query","description":"Exact canonical sender email (case-insensitive).","schema":{"maxLength":320,"format":"email","type":"string"}},{"name":"threadId","required":false,"in":"query","description":"Stable threadId returned by this endpoint.","schema":{"maxLength":128,"type":"string"}},{"name":"receivedFrom","required":false,"in":"query","description":"Inclusive server-receipt lower bound (ISO-8601).","schema":{"format":"date-time","type":"string"}},{"name":"receivedTo","required":false,"in":"query","description":"Inclusive server-receipt upper bound (ISO-8601).","schema":{"format":"date-time","type":"string"}},{"name":"search","required":false,"in":"query","description":"Fuzzy sender/subject search.","schema":{"maxLength":500,"type":"string"}},{"name":"cursor","required":false,"in":"query","description":"Opaque nextCursor returned by the previous page.","schema":{"maxLength":128,"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"integer"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List system intake messages for MCP/UI (#750)","tags":["Briefs"],"x-required-scope":["briefs:read"]}},"/api/briefs/intake/items/{itemId}":{"get":{"operationId":"BriefsController_getIntakeItem","parameters":[{"name":"itemId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Read one lossless system intake item with provenance, attachments and work log (#750)","tags":["Briefs"]}},"/api/briefs/intake/items/{itemId}/status":{"patch":{"operationId":"BriefsController_transitionIntakeItem","parameters":[{"name":"itemId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransitionBriefIntakeItemDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Transition an intake item to IN_REVIEW, IGNORED or REJECTED with an audited reason (#750)","tags":["Briefs"]}},"/api/briefs/intake/items/{itemId}/link":{"post":{"operationId":"BriefsController_linkIntakeItem","parameters":[{"name":"itemId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkBriefIntakeItemDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Link an intake item/files to a Brief idempotently (#750)","tags":["Briefs"]}},"/api/briefs/intake/items/{itemId}/log":{"post":{"operationId":"BriefsController_logIntakeWork","parameters":[{"name":"itemId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogBriefIntakeWorkDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Append an agent work-log event with intake provenance (#750)","tags":["Briefs"]}},"/api/briefs":{"get":{"operationId":"BriefsController_findAll","parameters":[{"name":"page","required":false,"in":"query","schema":{"type":"integer","example":1,"minimum":1}},{"name":"pageSize","required":false,"in":"query","schema":{"type":"integer","example":50,"minimum":1,"maximum":200}},{"name":"search","required":false,"in":"query","schema":{"example":"outreach","type":"string"}},{"name":"isActive","required":false,"in":"query","schema":{"example":true,"type":"boolean"}},{"name":"includeDeleted","required":false,"in":"query","schema":{"example":false,"type":"boolean"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List briefs with pagination, search and active/deleted filters","tags":["Briefs"]},"post":{"operationId":"BriefsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBriefDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new brief","tags":["Briefs"]}},"/api/briefs/{id}/attachments/content":{"get":{"operationId":"BriefsController_attachmentContent","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"attachmentRef","required":true,"in":"query","schema":{"example":"dialog-attachment:uuid","type":"string"}},{"name":"resource","required":false,"in":"query","schema":{"enum":["text","sections","tableRows","hyperlinks","images","embeddedObjects","parts"],"type":"string"}},{"name":"cursor","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"integer","minimum":1,"maximum":10,"default":3}},{"name":"imageRef","required":false,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Read one Brief attachment as bounded source-backed text/structure/image pages; imageRef yields a real MCP image block (#768)","tags":["Briefs"]}},"/api/briefs/{id}":{"get":{"operationId":"BriefsController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single brief by id","tags":["Briefs"]},"patch":{"operationId":"BriefsController_updateMeta","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBriefMetaDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update brief metadata (name, description, status)","tags":["Briefs"]},"delete":{"operationId":"BriefsController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"reason","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Soft-delete a brief with optional reason","tags":["Briefs"]}},"/api/briefs/{id}/content":{"patch":{"operationId":"BriefsController_updateContent","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBriefContentDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update brief content body (JSON-merge patch). personas[]/examples[] merge by item id when every item has a stable id -- give a NEW item a UUID id and keep reusing it, or the whole array is replaced (legacy behavior, unsafe under concurrent edits, #782); customFields[] has no id yet and always replaces whole","tags":["Briefs"]}},"/api/briefs/{id}/variables":{"patch":{"operationId":"BriefsController_updateVariables","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBriefVariablesDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update brief template variables","tags":["Briefs"]}},"/api/briefs/{id}/locks":{"patch":{"operationId":"BriefsController_updateLocks","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update brief section locks","tags":["Briefs"]}},"/api/briefs/{id}/restore":{"post":{"operationId":"BriefsController_restore","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Restore a soft-deleted brief","tags":["Briefs"]}},"/api/briefs/{id}/copy":{"post":{"operationId":"BriefsController_copy","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Duplicate an existing brief","tags":["Briefs"]}},"/api/briefs/{id}/audit":{"get":{"operationId":"BriefsController_audit","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List audit entries for a brief","tags":["Briefs"]}},"/api/briefs/{id}/mail":{"get":{"operationId":"BriefsController_mail","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"integer","example":50,"minimum":1,"maximum":200}},{"name":"locale","required":false,"in":"query","schema":{"example":"ru","type":"string"}},{"name":"accept-language","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Brief intake email address and mail feed (#744)","tags":["Briefs"]}},"/api/briefs/{id}/mail/attachments/{attachmentId}/download":{"get":{"operationId":"BriefsController_downloadMailAttachment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"attachmentId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download a brief mail attachment (#780) — same tenant guard as the rest of the brief","tags":["Briefs"]}},"/api/briefs/{id}/intake-alias":{"patch":{"operationId":"BriefsController_updateIntakeAlias","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"locale","required":true,"in":"query","schema":{"type":"string"}},{"name":"accept-language","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBriefIntakeAliasDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Change the stable human-readable system intake alias (#756)","tags":["Briefs"]}},"/api/briefs/{id}/expert":{"get":{"operationId":"BriefsController_expert","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"since","required":false,"in":"query","schema":{"type":"string","format":"date-time"}},{"name":"query","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200}},{"name":"locale","required":false,"in":"query","schema":{"enum":["ru","en"],"type":"string"}},{"name":"include","required":false,"in":"query","description":"Comma-separated: liveSchema, sdrRecommendations, or all. Omit for a compact delta of both.","schema":{"type":"string"}},{"name":"accept-language","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Operation-level SDR expert flow: intake provenance → live schema → gaps → recommendations → save/validate","tags":["Briefs"]}},"/api/briefs/{briefId}/memory":{"get":{"operationId":"BriefMemoryController_list","parameters":[{"name":"briefId","required":true,"in":"path","schema":{"type":"string"}},{"name":"kind","required":false,"in":"query","schema":{"enum":["DECISION","OBSERVATION","QUESTION","REJECTED","NOISE"],"type":"string"}},{"name":"path","required":false,"in":"query","description":"Filter by a content path this entry references, e.g. offer.positioning","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"enum":["ACTIVE","SUPERSEDED","RESOLVED"],"type":"string"}},{"name":"includeAllStatuses","required":false,"in":"query","description":"Without this, only ACTIVE entries are returned regardless of `status`","schema":{"type":"boolean"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List brief memory entries (decisions, observations, questions, rejected proposals, migrated noise). Default: only ACTIVE.","tags":["Briefs"]},"post":{"operationId":"BriefMemoryController_create","parameters":[{"name":"briefId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Record a memory entry: a decision, an observation, an open question, a REJECTED proposal (why is required — an unexplained rejection cannot stop the next agent from repeating it), or migrated NOISE. Does NOT touch Brief.content — use PATCH content for that.","tags":["Briefs"]}},"/api/briefs/{briefId}/memory/{entryId}/resolve":{"post":{"operationId":"BriefMemoryController_resolve","parameters":[{"name":"briefId","required":true,"in":"path","schema":{"type":"string"}},{"name":"entryId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Mark a memory entry RESOLVED — leaves the default feed and stops being sent to the expert flow.","tags":["Briefs"]}},"/api/briefs/{briefId}/memory/migrate-content-review":{"post":{"operationId":"BriefMemoryController_migrateContentReview","parameters":[{"name":"briefId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#790: one-time migration of the temporary content.review block into memory entries (NOISE from redundant[], DECISION from keep[]), then removes review from content. Idempotent no-op if review is already gone.","tags":["Briefs"]}},"/api/names/decline":{"post":{"operationId":"NamesController_decline","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Decline a Russian full name (FIO) by grammatical case","tags":["Names"],"x-required-scope":["utils:read"]}},"/api/names/ping":{"get":{"operationId":"NamesController_ping","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Ping the names service (health check)","tags":["Names"],"x-required-scope":["utils:read"]}},"/api/email-accounts/lookup":{"get":{"operationId":"EmailAccountsController_lookupProvider","parameters":[{"name":"email","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Look up provider SMTP/IMAP settings for an email address","tags":["Email Accounts"],"x-required-scope":["accounts:read"]}},"/api/email-accounts/test-unsaved":{"post":{"operationId":"EmailAccountsController_testUnsaved","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Test SMTP/IMAP credentials without saving the account","tags":["Email Accounts"],"x-required-scope":["accounts:write"]}},"/api/email-accounts":{"get":{"operationId":"EmailAccountsController_findAll","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"listId","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"service","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"sendMethod","required":true,"in":"query","schema":{"type":"string"}},{"name":"imapMode","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List email accounts with filters and pagination","tags":["Email Accounts"],"x-required-scope":["accounts:read"]},"post":{"operationId":"EmailAccountsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailAccountDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new email account. Lookup is advisory and client-invoked: POST does not auto-detect transport. Call GET /email-accounts/lookup first for the email address, then pass the returned SMTP/IMAP/service fields explicitly. Override host/port/credentials for custom domains. The legacy `provider` field is normalized to the `service` enum (no separate column).","tags":["Email Accounts"],"x-required-scope":["accounts:write"]}},"/api/email-accounts/stats":{"get":{"operationId":"EmailAccountsController_getStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregated stats across all email accounts","tags":["Email Accounts"],"x-required-scope":["accounts:read"]}},"/api/email-accounts/check-duplicate":{"get":{"operationId":"EmailAccountsController_checkDuplicate","parameters":[{"name":"email","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check if an email address is already registered","tags":["Email Accounts"],"x-required-scope":["accounts:read"]}},"/api/email-accounts/relay-health-summary":{"get":{"operationId":"EmailAccountsController_relayHealthSummary","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Relay health across the whole tenant (#337): how many relays are sending right now, how many dropped out and why (AUTH_ERROR, BOUNCE_LIMIT, RATE_LIMITED, SEND_LIMIT, SPAM_PLACEMENT, PROVIDER_BLOCK), per-relay counters, daily limit usage and inbound freshness. Per-relay provider breakdown (#345, #507): rejectsByProvider (policy/routing rejects from CampaignRecipient.bounceNature, tenant-wide, windowed by the blockGuard.windowDays tenant setting — same source as campaign policyRejectedByProvider/policyRejectedByRelay, not a second aggregation), campaignBounceNatures (hard/inactive = dead addresses, policy/routing = route reputation; durable (#546, same predicate as campaign metrics #396): finalStatus=BOUNCED UNION rows currently awaiting soft-bounce retry (finalStatus reset, bounceNature/bounceRetries are not), windowed by the same blockGuard.windowDays as rejectsByProvider — see bounceNaturesWindowDays (null means the aggregate failed to compute, fail-soft)), plus tenant-wide pausedDirections — relay→provider pairs closed by TTL block rules (relay alive, direction paused). Read-only, no pool id needed — use it to answer \"is sending healthy right now\"","tags":["Email Accounts"],"x-required-scope":["accounts:read"]}},"/api/email-accounts/relay-health/attention":{"get":{"operationId":"EmailAccountsController_relayAttention","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Relays that automation can no longer recover (#356): status=ERROR relays where re-probing kept failing, so a human has to look. Returns probeFailures, lastErrorClass, when the relay was escalated and staleDays — how long it has been waiting. This is the \"what do I have to fix myself\" list, as opposed to relay-health-summary (\"what is broken right now\")","tags":["Email Accounts"],"x-required-scope":["accounts:read"]}},"/api/email-accounts/relay-health/probe":{"post":{"operationId":"EmailAccountsController_relayProbe","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Re-probe ERROR relays of this tenant right now (#356) instead of waiting for the 10-min cron. Probes SMTP with verify() (no test mail is sent), returns how many recovered into the pool and how many were escalated for manual review. Safe to call repeatedly","tags":["Email Accounts"],"x-required-scope":["accounts:write"]}},"/api/email-accounts/{id}/stats":{"get":{"operationId":"EmailAccountsController_getAccountStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get per-account email statistics","tags":["Email Accounts"]}},"/api/email-accounts/{id}":{"get":{"operationId":"EmailAccountsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get an email account by id","tags":["Email Accounts"]},"patch":{"operationId":"EmailAccountsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an email account. Note on status (#558): an account already stopped by a diagnosis (ERROR / AUTO_PAUSED / RATE_LIMITED / SUSPENDED) cannot be moved to PAUSED — that would hide the reason and drop it out of automatic recovery (ERROR re-probing, auto-resume cron), and it is rejected with code PAUSE_WOULD_MASK_DIAGNOSIS. Fix the account and set ACTIVE, or stop it deliberately with POST /email-accounts/:id/suspend, which records a reason. Read handles return stopKind/stopReason/pauseAllowed so you can tell in advance","tags":["Email Accounts"]},"delete":{"operationId":"EmailAccountsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an email account","tags":["Email Accounts"]}},"/api/email-accounts/import-oauth":{"post":{"operationId":"EmailAccountsController_importOauth","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOauthDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Import an Outlook/Hotmail account from an OAuth combo (email:password:refresh_token:client_id). The platform mints and auto-refreshes the access token itself (public-client refresh, no secret). Probes IMAP receive + SMTP send and reports capability; receive-only when the mailbox has SMTP disabled.","tags":["Email Accounts"],"x-required-scope":["accounts:write"]}},"/api/email-accounts/import-oauth/bulk":{"post":{"operationId":"EmailAccountsController_importOauthBulk","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOauthBulkDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Bulk-import Outlook/Hotmail accounts from OAuth combo strings (one per array item).","tags":["Email Accounts"],"x-required-scope":["accounts:write"]}},"/api/email-accounts/{id}/fetch-imap":{"post":{"operationId":"EmailAccountsController_fetchImap","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Trigger an IMAP fetch for an account (queue or fast-lane)","tags":["Email Accounts"]}},"/api/email-accounts/{id}/test":{"post":{"operationId":"EmailAccountsController_testConnection","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Test SMTP and/or IMAP connectivity for an account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/test-receive":{"post":{"operationId":"EmailAccountsController_testReceive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Universal Receive Test (#4). Probes the real receive transport for this account — Microsoft Graph, Gmail API (planned), IMAP direct, IMAP via Agent, or GAS WebApp — and returns a single honest result with transport label, per-step log, and (when available) inbox counts. Rate-limited per account (1 per 5s).","tags":["Email Accounts"]}},"/api/email-accounts/{id}/test-send":{"post":{"operationId":"EmailAccountsController_testSend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Universal Send Test (#5). Dry-run probe of the real send transport — Microsoft Graph sendMail (planned), Gmail API drafts (planned), SMTP XOAUTH2 verify (planned), SMTP password, SMTP via Agent, or GAS WebApp health (planned). Never sends a real message. Rate-limited per account (1 per 5s).","tags":["Email Accounts"]}},"/api/email-accounts/{id}/dns-check":{"get":{"operationId":"EmailAccountsController_checkDns","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Run DNS health check for the account domain","tags":["Email Accounts"]}},"/api/email-accounts/{id}/reset-counters":{"post":{"operationId":"EmailAccountsController_resetCounters","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset daily send counters for an account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/warmup/start":{"post":{"operationId":"EmailAccountsController_warmupStart","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Start mailbox warm-up for an account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/warmup/stop":{"post":{"operationId":"EmailAccountsController_warmupStop","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Stop mailbox warm-up for an account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/warmup":{"get":{"operationId":"EmailAccountsController_warmupStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get mailbox warm-up stats for an account","tags":["Email Accounts"]},"patch":{"operationId":"EmailAccountsController_warmupConfigure","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Configure mailbox warm-up parameters","tags":["Email Accounts"]}},"/api/email-accounts/{id}/suspend":{"post":{"operationId":"EmailAccountsController_suspend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Suspend an email account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/unsuspend":{"post":{"operationId":"EmailAccountsController_unsuspend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Unsuspend an email account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/work-status":{"patch":{"operationId":"EmailAccountsController_updateWorkStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the work status (IDLE / IN_PROGRESS) of an account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/gas/setup":{"post":{"operationId":"EmailAccountsController_gasSetup","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate GAS setup instructions for the account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/gas/verify":{"post":{"operationId":"EmailAccountsController_gasVerify","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Verify a deployed GAS web app URL for the account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/gas/ping":{"post":{"operationId":"EmailAccountsController_gasPing","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Ping the GAS web app to verify connectivity","tags":["Email Accounts"]}},"/api/email-accounts/{id}/gas/test-send":{"post":{"operationId":"EmailAccountsController_gasTestSend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Send a test email via GAS","tags":["Email Accounts"]}},"/api/email-accounts/{id}/gas/test-fetch":{"post":{"operationId":"EmailAccountsController_gasTestFetch","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run a test fetch via GAS","tags":["Email Accounts"]}},"/api/email-accounts/{id}/gas/disable":{"patch":{"operationId":"EmailAccountsController_gasDisable","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Disable GAS integration for an account","tags":["Email Accounts"]}},"/api/email-accounts/{id}/gas/labels":{"get":{"operationId":"EmailAccountsController_gasLabels","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List Gmail labels available via GAS","tags":["Email Accounts"]}},"/api/email-account-lists":{"get":{"operationId":"EmailAccountsController_findAllLists","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List email account lists","tags":["Email Accounts"],"x-required-scope":["accounts:read"]},"post":{"operationId":"EmailAccountsController_createList","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create an email account list","tags":["Email Accounts"],"x-required-scope":["accounts:write"]}},"/api/email-account-lists/{id}":{"patch":{"operationId":"EmailAccountsController_updateList","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an email account list","tags":["Email Accounts"]},"delete":{"operationId":"EmailAccountsController_removeList","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an email account list","tags":["Email Accounts"]}},"/api/email-account-lists/{id}/relay-health":{"get":{"operationId":"EmailAccountsController_relayHealth","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Relay pool health (#40) for an email-account-list / relay-pool id (not an individual account id): live eligibility of each account in the pool, next relay, starving flag, recent dispatches and sticky bindings","tags":["Email Accounts"]}},"/api/gas/webhook":{"post":{"description":"PUBLIC endpoint, NOT protected by JWT. Authenticated via `body.secret` — a per-account UUID v4 (`EmailAccount.gasSecret`) generated when the user connects a Google Apps Script mailbox, compared constant-time against the value the user's own Apps Script sends. Unknown accountId / missing or wrong secret → 403.","operationId":"GasWebhookController_handleWebhook","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Receive a GAS push notification and trigger IMAP fetch","tags":["Email Accounts / GAS Webhook"]}},"/api/internal/mail-arrived":{"post":{"operationId":"InboxIngestController_mailArrived","parameters":[{"name":"x-internal-key","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"summary":"Internal: notify that new mail arrived and trigger immediate IMAP fetch","tags":["Email Accounts / Inbox Ingest"]}},"/api/internal/brief-intake/limits":{"get":{"operationId":"SystemBriefIntakeController_limits","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"tags":["SystemBriefIntake"]}},"/api/internal/brief-intake":{"post":{"operationId":"SystemBriefIntakeController_receive","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Buffer"}}}},"responses":{"200":{"description":""}},"tags":["SystemBriefIntake"]}},"/api/imap-orchestrator/stats":{"get":{"operationId":"ImapOrchestratorController_getStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get IMAP orchestrator dashboard stats","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]}},"/api/imap-orchestrator/jobs":{"get":{"operationId":"ImapOrchestratorController_getJobs","parameters":[{"name":"accountId","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List recent IMAP orchestrator jobs","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]}},"/api/imap-orchestrator/fetch/{accountId}":{"post":{"operationId":"ImapOrchestratorController_fetchAccount","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually trigger an IMAP fetch for a specific account","tags":["IMAP Orchestrator"]}},"/api/imap-orchestrator/attention":{"get":{"operationId":"ImapOrchestratorController_getAttention","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List email accounts needing manual intervention","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]}},"/api/imap-orchestrator/sync-health":{"get":{"operationId":"ImapOrchestratorController_getSyncHealth","parameters":[{"name":"accountId","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get lossless mail sync cursor, staging and quarantine health","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]}},"/api/imap-orchestrator/sync-health/{id}/retry":{"post":{"operationId":"ImapOrchestratorController_retryStagedMessage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Retry a failed durable inbound message, or force a re-fetch of an exhausted quarantine row","tags":["IMAP Orchestrator"]}},"/api/imap-orchestrator/heal":{"post":{"operationId":"ImapOrchestratorController_heal","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Auto-heal stuck GAS accounts and IMAP locks for the current tenant","tags":["IMAP Orchestrator"],"x-required-scope":["imap:write"]}},"/api/imap-orchestrator/heal-all":{"post":{"operationId":"ImapOrchestratorController_healAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Auto-heal stuck IMAP/GAS state across all tenants","tags":["IMAP Orchestrator"],"x-required-scope":["imap:write"]}},"/api/imap-orchestrator/fetch-all":{"post":{"operationId":"ImapOrchestratorController_fetchAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Trigger an IMAP fetch for every active account in the tenant","tags":["IMAP Orchestrator"],"x-required-scope":["imap:write"]}},"/api/imap-orchestrator/tech-log":{"get":{"operationId":"ImapOrchestratorController_getTechLog","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the latest N IMAP job log entries for monitoring","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]}},"/api/imap-orchestrator/recent-dialogs":{"get":{"operationId":"ImapOrchestratorController_getRecentDialogs","parameters":[{"name":"accountId","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List recently inserted inbound dialogs","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]}},"/api/imap-orchestrator/jobs/{id}":{"delete":{"operationId":"ImapOrchestratorController_cancelJob","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel an IMAP orchestrator job","tags":["IMAP Orchestrator"]}},"/api/imap-orchestrator/marking-overrides":{"get":{"operationId":"ImapOrchestratorController_getOverrides","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List dialog marking override rules","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]},"post":{"operationId":"ImapOrchestratorController_createOverride","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a dialog marking override rule","tags":["IMAP Orchestrator"],"x-required-scope":["imap:write"]}},"/api/imap-orchestrator/marking-overrides/{id}":{"post":{"operationId":"ImapOrchestratorController_updateOverride","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a dialog marking override rule","tags":["IMAP Orchestrator"]},"delete":{"operationId":"ImapOrchestratorController_deleteOverride","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a dialog marking override rule","tags":["IMAP Orchestrator"]}},"/api/imap-orchestrator/marking-patterns":{"get":{"operationId":"ImapOrchestratorController_getPatterns","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List dialog marking regex patterns","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]},"post":{"operationId":"ImapOrchestratorController_createPattern","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a dialog marking regex pattern","tags":["IMAP Orchestrator"],"x-required-scope":["imap:write"]}},"/api/imap-orchestrator/marking-patterns/{id}":{"post":{"operationId":"ImapOrchestratorController_updatePattern","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a dialog marking regex pattern","tags":["IMAP Orchestrator"]},"delete":{"operationId":"ImapOrchestratorController_deletePattern","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a dialog marking regex pattern","tags":["IMAP Orchestrator"]}},"/api/imap-orchestrator/health-accounts":{"get":{"operationId":"ImapOrchestratorController_getHealthAccounts","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Admin: list all email accounts across every tenant for health checks","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]}},"/api/imap-orchestrator/health-test":{"post":{"operationId":"ImapOrchestratorController_healthTest","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Admin: run SMTP/IMAP connection test (or round-trip) for a specific account","tags":["IMAP Orchestrator"],"x-required-scope":["imap:write"]}},"/api/imap-orchestrator/admin/kill":{"post":{"operationId":"ImapOrchestratorController_killImapCron","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Emergency stop for IMAP cron triggers (#6 Layer 4). All enqueueAll cycles short-circuit until /resume is called. Idempotent — repeated calls only update the reason field.","tags":["IMAP Orchestrator"],"x-required-scope":["admin:write"]}},"/api/imap-orchestrator/admin/resume":{"post":{"operationId":"ImapOrchestratorController_resumeImapCron","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Resume IMAP cron after a kill (#6 Layer 4).","tags":["IMAP Orchestrator"],"x-required-scope":["admin:write"]}},"/api/imap-orchestrator/admin/health":{"get":{"operationId":"ImapOrchestratorController_getImapHealth","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"IMAP orchestrator kill-switch state + queue counts (#6 Layer 4). Returns whether the cron is currently paused and why.","tags":["IMAP Orchestrator"],"x-required-scope":["admin:read"]}},"/api/imap-orchestrator/conveyor-health":{"get":{"operationId":"ImapOrchestratorController_getConveyorHealth","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Per-step inbound conveyor health for this tenant (#336): fetch quarantine, relay inbound silence, staging backlog, delivery reports the classify pass never covered (`classifyNotRun`; a NULL business label on ordinary mail is normal and is NOT backlog), link starvation, bounces not matched to ANY send path (`unresolvedBounces24h`; `alreadyHandled24h` and `foreignMailboxNdr24h` are split out), failed lead rules. `survivedHealing` counts objects that were healed a tick earlier and are still stuck — only those raise alerts. Read-only — no healing, no alerts.","tags":["IMAP Orchestrator"],"x-required-scope":["imap:read"]}},"/api/imap-orchestrator/conveyor-watchdog/run":{"post":{"operationId":"ImapOrchestratorController_runConveyorWatchdog","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run the conveyor watchdog tick across all tenants NOW (#336): measure every step, self-heal (re-enqueue stalled links, rerun pipeline for staging/classify backlog) and send alerts where healing did not help. Same routine the */10 cron runs.","tags":["IMAP Orchestrator"],"x-required-scope":["admin:write"]}},"/api/imap-orchestrator/conveyor-watchdog/last":{"get":{"operationId":"ImapOrchestratorController_getConveyorWatchdogLast","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Result of the last conveyor watchdog tick across all tenants (#336), without recomputing.","tags":["IMAP Orchestrator"],"x-required-scope":["admin:read"]}},"/api/inbound-rules":{"get":{"operationId":"InboundRulesController_findAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all inbound rules","tags":["Inbound Rules"]},"post":{"operationId":"InboundRulesController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInboundRuleDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new inbound rule","tags":["Inbound Rules"]}},"/api/inbound-rules/events":{"get":{"operationId":"InboundRulesController_listAutomationEvents","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"eventType","required":true,"in":"query","schema":{"type":"string"}},{"name":"source","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List recent inbound-rule automation events","tags":["Inbound Rules"],"x-required-scope":["rules:read"]}},"/api/inbound-rules/{id}":{"get":{"operationId":"InboundRulesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get an inbound rule by id","tags":["Inbound Rules"]},"patch":{"operationId":"InboundRulesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateInboundRuleDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an inbound rule","tags":["Inbound Rules"]},"delete":{"operationId":"InboundRulesController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an inbound rule","tags":["Inbound Rules"]}},"/api/inbound-rules/reorder":{"patch":{"operationId":"InboundRulesController_reorder","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderInboundRulesDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder inbound rules (sortOrder)","tags":["Inbound Rules"],"x-required-scope":["rules:write"]}},"/api/inbound-rules/{id}/toggle":{"patch":{"operationId":"InboundRulesController_toggle","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Toggle the active flag of an inbound rule","tags":["Inbound Rules"]}},"/api/inbound-rules/test":{"post":{"operationId":"InboundRulesController_testRules","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Dry-run synthetic inbound message against active rules","tags":["Inbound Rules"],"x-required-scope":["rules:read"]}},"/api/inbound-rules/reapply":{"post":{"operationId":"InboundRulesController_reapply","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReapplyInboundRulesDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Re-apply keyword routing to leads in the intake stage","tags":["Inbound Rules"],"x-required-scope":["rules:write"]}},"/api/dialog-linker/relink/{dialogId}":{"post":{"operationId":"DialogLinkerController_relink","parameters":[{"name":"dialogId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually re-run linker for a specific dialog","tags":["Dialog Linker"]}},"/api/dialog-linker/backfill":{"post":{"operationId":"DialogLinkerController_backfill","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run dialog linker backfill across the tenant (admin)","tags":["Dialog Linker"],"x-required-scope":["linker:write"]}},"/api/dialog-linker/stats":{"get":{"operationId":"DialogLinkerController_getStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get linker statistics by status","tags":["Dialog Linker"],"x-required-scope":["linker:read"]}},"/api/dialog-linker/failure-summary":{"get":{"operationId":"DialogLinkerController_getFailureSummary","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get failed linker reason counts and LinkLog coverage","tags":["Dialog Linker"],"x-required-scope":["linker:read"]}},"/api/dialog-linker/logs/{dialogId}":{"get":{"operationId":"DialogLinkerController_getLogs","parameters":[{"name":"dialogId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get linker logs for a specific dialog","tags":["Dialog Linker"]}},"/api/dialog-linker/logs":{"get":{"operationId":"DialogLinkerController_getAllLogs","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get all linker logs (admin tech log)","tags":["Dialog Linker"],"x-required-scope":["linker:read"]}},"/api/mail-routing-rules":{"get":{"operationId":"MailRoutingController_findAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all mail routing rules","tags":["Mail Routing Rules"]},"post":{"operationId":"MailRoutingController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMailRoutingRuleDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new mail routing rule","tags":["Mail Routing Rules"]}},"/api/mail-routing-rules/{id}":{"get":{"operationId":"MailRoutingController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a mail routing rule by id","tags":["Mail Routing Rules"]},"patch":{"operationId":"MailRoutingController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMailRoutingRuleDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a mail routing rule","tags":["Mail Routing Rules"]},"delete":{"operationId":"MailRoutingController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a mail routing rule","tags":["Mail Routing Rules"]}},"/api/mail-routing-rules/{id}/toggle":{"patch":{"operationId":"MailRoutingController_toggle","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Toggle the active flag of a mail routing rule","tags":["Mail Routing Rules"]}},"/api/mail-routing-rules/test":{"post":{"operationId":"MailRoutingController_testRules","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Dry-run a synthetic email against active routing rules","tags":["Mail Routing Rules"],"x-required-scope":["rules:read"]}},"/api/saved-views":{"get":{"operationId":"SavedViewsController_findAll","parameters":[{"name":"entity","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List saved views for an entity for the current user","tags":["Saved Views"]},"post":{"operationId":"SavedViewsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateViewDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a saved view","tags":["Saved Views"]}},"/api/saved-views/{id}":{"patch":{"operationId":"SavedViewsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateViewDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a saved view (only the owner may edit it)","tags":["Saved Views"]},"delete":{"operationId":"SavedViewsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a saved view (only the owner may delete it)","tags":["Saved Views"]}},"/api/project-templates/runs/{runId}":{"get":{"operationId":"ProjectTemplatesController_findRun","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a project run with steps and totals","tags":["Project Templates"]},"patch":{"operationId":"ProjectTemplatesController_updateRun","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRunDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a project run (name, status, isTest, notes)","tags":["Project Templates"]},"delete":{"operationId":"ProjectTemplatesController_removeRun","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a project run","tags":["Project Templates"]}},"/api/project-templates/runs/{runId}/steps/{stepId}":{"patch":{"operationId":"ProjectTemplatesController_updateRunStep","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRunStepDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a run step (fact, status, issues/questions/ideas)","tags":["Project Templates"]}},"/api/project-templates":{"get":{"operationId":"ProjectTemplatesController_findAll","parameters":[{"name":"includeArchived","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List project templates","tags":["Project Templates"]},"post":{"operationId":"ProjectTemplatesController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a project template","tags":["Project Templates"]}},"/api/project-templates/{id}":{"get":{"operationId":"ProjectTemplatesController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a template with steps and runs","tags":["Project Templates"]},"patch":{"operationId":"ProjectTemplatesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTemplateDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a template (name, description, isArchived)","tags":["Project Templates"]},"delete":{"operationId":"ProjectTemplatesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a template (409 if it has runs — archive instead)","tags":["Project Templates"]}},"/api/project-templates/{id}/steps":{"post":{"operationId":"ProjectTemplatesController_addStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a step to a template","tags":["Project Templates"]}},"/api/project-templates/{id}/steps/{stepId}":{"patch":{"operationId":"ProjectTemplatesController_updateStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStepDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a template step","tags":["Project Templates"]},"delete":{"operationId":"ProjectTemplatesController_removeStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a template step","tags":["Project Templates"]}},"/api/project-templates/{id}/steps/reorder":{"post":{"operationId":"ProjectTemplatesController_reorder","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reorder template steps (full ordered id list)","tags":["Project Templates"]}},"/api/project-templates/{id}/brief-questions":{"get":{"operationId":"ProjectTemplatesController_briefQuestions","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"All brief questions of a template as one list","tags":["Project Templates"]}},"/api/project-templates/{id}/summary":{"get":{"operationId":"ProjectTemplatesController_summary","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"scope","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Plan vs avg fact per step over DONE runs (scope: all|test|real)","tags":["Project Templates"]}},"/api/project-templates/{id}/runs":{"post":{"operationId":"ProjectTemplatesController_createRun","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRunDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a run from a template (steps are snapshotted)","tags":["Project Templates"]}},"/api/search":{"get":{"operationId":"SearchController_search","parameters":[{"name":"q","required":true,"in":"query","schema":{"example":"anna@acme.com","type":"string"}},{"name":"limit","required":false,"in":"query","description":"Max items per bucket (capped at 50). Default 10.","schema":{"example":10,"type":"number"}},{"name":"types","required":false,"in":"query","description":"Comma-separated subset of [contact, company, lead]. Default: all three.","schema":{"example":"contact,company,lead","type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Universal cross-entity search by free-text query. Returns matching contacts, companies, and leads in a single response.","tags":["Search"]}},"/api/activities/feed":{"get":{"operationId":"ActivitiesController_feed","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"entityType","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Unified tenant event feed (activities + emails) for /crm/events — filters: date range, type (ActivityType|EMAIL_IN|EMAIL_OUT), entityType (contact|lead|company); paginated, sorted by date desc","tags":["Activities"],"x-required-scope":["activities:read"]}},"/api/activities":{"get":{"operationId":"ActivitiesController_findAll","parameters":[{"name":"leadId","required":true,"in":"query","schema":{"type":"string"}},{"name":"contactId","required":true,"in":"query","schema":{"type":"string"}},{"name":"companyId","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List activities filtered by lead/contact/company/type","tags":["Activities"]},"post":{"operationId":"ActivitiesController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateActivityDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create an activity (call/task/note) linked to a lead/contact/company","tags":["Activities"]}},"/api/activities/{id}":{"patch":{"operationId":"ActivitiesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateActivityDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an activity (subject, description, due date, done flag)","tags":["Activities"]},"delete":{"operationId":"ActivitiesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an activity by id","tags":["Activities"]}},"/api/admin/rpa":{"get":{"operationId":"RpaAdminController_overview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"RPA service keys (redacted), tenant opt-ins, queue readiness and legacy drain inventory","tags":["Admin RPA"]}},"/api/admin/rpa/keys":{"post":{"operationId":"RpaAdminController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaCreateKeyDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a dedicated RPA service key","tags":["Admin RPA"]}},"/api/admin/rpa/keys/{id}/rotate":{"post":{"operationId":"RpaAdminController_rotate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Rotate a dedicated RPA key, invalidating the previous secret","tags":["Admin RPA"]}},"/api/admin/rpa/keys/{id}/reveal":{"get":{"operationId":"RpaAdminController_reveal","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reveal an encrypted current RPA key for SUPER; legacy hash-only keys cannot be recovered","tags":["Admin RPA"]}},"/api/admin/rpa/keys/{id}/global-access":{"put":{"operationId":"RpaAdminController_globalAccess","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaGlobalAccessDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Explicitly allow an RPA key to claim work for all active tenant users","tags":["Admin RPA"]}},"/api/admin/rpa/keys/{id}/revoke":{"post":{"operationId":"RpaAdminController_revoke","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Revoke RPA service access immediately; started sends remain for reconciliation","tags":["Admin RPA"]}},"/api/admin/rpa/keys/{id}/trace":{"post":{"operationId":"RpaAdminController_trace","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaTraceDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Enable detailed heartbeat/poll trace for one hour, or disable it","tags":["Admin RPA"]}},"/api/admin/rpa/keys/{id}/grants":{"put":{"operationId":"RpaAdminController_grant","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RpaGrantDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Explicit tenant and user opt-in for a service key","tags":["Admin RPA"]}},"/api/admin/rpa/logs":{"get":{"operationId":"RpaAdminController_logs","parameters":[{"name":"tenantId","required":true,"in":"query","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"reasonCode","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Correlated RPA history; allowlisted metadata only, bounded keyset pagination","tags":["Admin RPA"]}},"/api/admin/rpa/task-history":{"get":{"operationId":"RpaAdminController_taskHistory","parameters":[{"name":"tenantId","required":true,"in":"query","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"reasonCode","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Alias for bounded cross-tenant RPA task history","tags":["Admin RPA"]}},"/api/admin/rpa/protocol":{"get":{"operationId":"RpaAdminController_protocol","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"RPA protocol endpoints and retry/lease rules","tags":["Admin RPA"]}},"/api/admin/account-transfers/plan":{"post":{"operationId":"AdminController_planAccountTransfer","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountTransferPlanDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Dry-run an account transfer between tenant databases (SUPER)","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/account-transfers/apply":{"post":{"operationId":"AdminController_applyAccountTransfer","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountTransferApplyDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Apply a confirmed, idempotent account transfer plan (SUPER)","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/account-transfers/{operationId}/deactivate-sources":{"post":{"operationId":"AdminController_deactivateAccountTransferSources","parameters":[{"name":"operationId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountTransferDeactivateSourcesDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Deactivate source users of a completed account transfer (SUPER)","tags":["Admin"]}},"/api/admin/account-transfers/{operationId}":{"get":{"operationId":"AdminController_getAccountTransfer","parameters":[{"name":"operationId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get account transfer operation audit status (SUPER)","tags":["Admin"]}},"/api/admin/tenants/{id}/freeze":{"post":{"operationId":"AdminController_freezeTenant","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Freeze a tenant — stop all sending immediately (SUPER)","tags":["Admin"]}},"/api/admin/tenants/{id}/unfreeze":{"post":{"operationId":"AdminController_unfreezeTenant","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Unfreeze a tenant — resume sending (SUPER)","tags":["Admin"]}},"/api/admin/tenants/{id}/legal-hold":{"post":{"operationId":"AdminController_setLegalHold","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Set/clear legal-hold — pause TTL/purge for a tenant (SUPER)","tags":["Admin"]}},"/api/admin/suppression/global/retro-release":{"post":{"operationId":"AdminController_retroReleaseGlobalSuppression","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Retroactive release of global_suppression for policy/routing/soft addresses with no hard/inactive anywhere on the platform (#550, SUPER)","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/queues":{"get":{"operationId":"AdminController_getQueueStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get stats for all BullMQ queues","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/scoring/health":{"get":{"operationId":"AdminController_getScoringHealth","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Scoring pipeline health: browser worker reachability and queue depths","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/queues/{name}/jobs":{"get":{"operationId":"AdminController_getQueueJobs","parameters":[{"name":"name","required":true,"in":"path","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"start","required":true,"in":"query","schema":{"type":"string"}},{"name":"end","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List jobs in a queue by status","tags":["Admin"]}},"/api/admin/queues/{name}/pause":{"post":{"operationId":"AdminController_pauseQueue","parameters":[{"name":"name","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Pause a BullMQ queue","tags":["Admin"]}},"/api/admin/queues/{name}/resume":{"post":{"operationId":"AdminController_resumeQueue","parameters":[{"name":"name","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Resume a BullMQ queue","tags":["Admin"]}},"/api/admin/queues/{name}/jobs/{id}/cancel":{"post":{"operationId":"AdminController_cancelQueueJob","parameters":[{"name":"name","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel a queue job by id","tags":["Admin"]}},"/api/admin/queues/{name}/jobs/{id}/retry":{"post":{"operationId":"AdminController_retryQueueJob","parameters":[{"name":"name","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Retry a failed queue job","tags":["Admin"]}},"/api/admin/queues/{name}/clean":{"post":{"operationId":"AdminController_cleanQueue","parameters":[{"name":"name","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Clean queue jobs (completed/failed)","tags":["Admin"]}},"/api/admin/storage":{"get":{"operationId":"AdminController_getStorageStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get storage usage stats","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/storage/pdfs":{"get":{"operationId":"AdminController_listPdfs","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List stored PDFs with metadata","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/storage/cleanup-pdfs":{"post":{"operationId":"AdminController_cleanupPdfs","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Cleanup old PDFs from storage","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/tenants":{"get":{"operationId":"AdminController_getTenants","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all tenants with metadata","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/tenants/{dbName}/ldm-ai":{"patch":{"operationId":"AdminController_toggleLdmAi","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Toggle LDM AI for a tenant","tags":["Admin"]}},"/api/admin/campaigns/{dbName}/{id}/audit-unblock":{"patch":{"operationId":"AdminController_auditUnblockCampaign","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Unblock an AUDIT_BLOCKED campaign (manual moderation): reset audit iterations, set PAUSED","tags":["Admin"]}},"/api/admin/tenants/{dbName}/ldm-ai/balance":{"patch":{"operationId":"AdminController_setLdmAiBalance","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set / top up per-tenant LDM AI balance (USD)","tags":["Admin"]}},"/api/admin/tenants/{dbName}/db-quota":{"get":{"operationId":"AdminController_getTenantDbQuota","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get DB quota + current usage for a tenant (SUPER)","tags":["Admin"]},"patch":{"operationId":"AdminController_updateTenantDbQuota","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set DB quota (MB) for a tenant; null = unlimited (SUPER)","tags":["Admin"]}},"/api/admin/tenants/{dbName}/email-accounts-max":{"get":{"operationId":"AdminController_getTenantEmailAccountsMax","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get email accounts cap + current usage for a tenant (SUPER)","tags":["Admin"]},"patch":{"operationId":"AdminController_updateTenantEmailAccountsMax","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set email accounts cap for a tenant; null = platform default (SUPER)","tags":["Admin"]}},"/api/admin/tenants/{dbName}/max-streams":{"patch":{"operationId":"AdminController_updateMaxStreams","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update max parallel streams for a tenant","tags":["Admin"]}},"/api/admin/tenants/{dbName}/transport":{"patch":{"operationId":"AdminController_updateTransport","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update mail transport config for a tenant","tags":["Admin"]}},"/api/admin/tenants/{dbName}/settings-menu":{"get":{"operationId":"AdminController_getSettingsMenu","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get hidden settings-menu tabs for a tenant (#275)","tags":["Admin"]},"patch":{"operationId":"AdminController_updateSettingsMenu","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set hidden settings-menu tabs for a tenant (#275)","tags":["Admin"]}},"/api/admin/tenants/inbox-check":{"get":{"operationId":"AdminController_getInboxCheckTenants","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List inbox-check status across tenants","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/tenants/{dbName}/inbox-check":{"patch":{"operationId":"AdminController_updateInboxCheckTenant","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update inbox-check config for a tenant","tags":["Admin"]}},"/api/admin/tenants/{dbName}/inbox-check/connect":{"post":{"operationId":"AdminController_connectInboxCheckTenant","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectInboxCheckTenantDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Atomically connect paid Inbox Placement for a user workspace","tags":["Admin"]}},"/api/admin/tenants/{dbName}/inbox-check/test":{"post":{"operationId":"AdminController_testInboxCheckTenant","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run inbox-check test for a tenant","tags":["Admin"]}},"/api/admin/ldmai-usage":{"get":{"operationId":"AdminController_getLdmAiUsage","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get LDM AI usage statistics","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/ldmai-queue":{"get":{"operationId":"AdminController_getLdmAiQueueStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get LDM AI queue snapshot","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/ai-monitor":{"get":{"operationId":"AdminController_getAiMonitor","parameters":[{"name":"provider","required":true,"in":"query","schema":{"type":"string"}},{"name":"context","required":true,"in":"query","schema":{"type":"string"}},{"name":"tenant","required":true,"in":"query","schema":{"type":"string"}},{"name":"success","required":true,"in":"query","schema":{"type":"string"}},{"name":"days","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"offset","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get AI monitor dashboard data","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/ai-model-mapping":{"get":{"operationId":"AdminController_getAiModelMapping","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get AI model mapping configuration","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/i18n":{"get":{"operationId":"AdminController_getI18n","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get i18n translations bundle","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/i18n/key":{"put":{"operationId":"AdminController_updateI18nKey","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a single i18n translation key","tags":["Admin"],"x-required-scope":["admin:write"]},"delete":{"operationId":"AdminController_deleteI18nKey","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an i18n translation key","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/i18n/bulk":{"put":{"operationId":"AdminController_bulkUpdateI18n","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Bulk-update i18n translation keys","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/memory":{"get":{"operationId":"AdminController_listMemory","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List memory files","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/memory/stats":{"get":{"operationId":"AdminController_memoryStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get memory storage stats","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/memory/{filename}":{"get":{"operationId":"AdminController_readMemory","parameters":[{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Read a memory file by name","tags":["Admin"]},"put":{"operationId":"AdminController_saveMemory","parameters":[{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Write a memory file by name","tags":["Admin"]},"delete":{"operationId":"AdminController_deleteMemory","parameters":[{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a memory file by name","tags":["Admin"]}},"/api/admin/memory/rename":{"post":{"operationId":"AdminController_renameMemory","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Rename a memory file","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/security/overview":{"get":{"operationId":"AdminController_getSecurityOverview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get security overview dashboard","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/ports":{"get":{"operationId":"AdminController_getPortStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List open network ports detected on the host","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/score":{"get":{"operationId":"AdminController_getSecurityScore","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregate security score","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/recommendations":{"get":{"operationId":"AdminController_getRecommendations","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get security hardening recommendations","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/integrity":{"get":{"operationId":"AdminController_getIntegrity","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check file-integrity vs baseline","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/baseline":{"post":{"operationId":"AdminController_initBaseline","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new file-integrity baseline","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/security/check":{"post":{"operationId":"AdminController_runIntegrityCheck","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run an on-demand security check","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/security/intrusions":{"get":{"operationId":"AdminController_getIntrusions","parameters":[{"name":"hours","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List detected intrusion attempts","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/summary":{"get":{"operationId":"AdminController_getAttackSummary","parameters":[{"name":"hours","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get security summary report","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/honeypot":{"get":{"operationId":"AdminController_getHoneypotEvents","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List recent honeypot events","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/honeypot/stats":{"get":{"operationId":"AdminController_getHoneypotStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregate honeypot statistics","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/lockdown":{"get":{"operationId":"AdminController_getLockdownStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get current lockdown state","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/lockdown/activate":{"post":{"operationId":"AdminController_activateLockdown","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Activate lockdown mode","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/security/lockdown/deactivate":{"post":{"operationId":"AdminController_deactivateLockdown","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Deactivate lockdown mode","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/security/lockdown/history":{"get":{"operationId":"AdminController_getLockdownHistory","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get lockdown activation history","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/events":{"get":{"operationId":"AdminController_getRecentEvents","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List security events log","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/cross-tenant-denied":{"get":{"operationId":"AdminController_getCrossTenantDenied","parameters":[{"name":"hours","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Aggregate security.cross_tenant_denied events by actor x target tenant (#1159)","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/security/backups":{"get":{"operationId":"AdminController_getBackupStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List available backups","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/alert-canary":{"get":{"operationId":"AdminController_getAlertCanaryStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"System alert channel canary status: last success, consecutive failures (#1160)","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/alert-canary/run":{"post":{"operationId":"AdminController_runAlertCanary","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually run one system alert canary tick (#1160)","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/pipelines":{"get":{"operationId":"AdminController_getPipelines","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all pipelines (cross-tenant admin view)","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/honeypot/admin-login":{"get":{"operationId":"HoneypotController_fakeAdminLoginGet","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Honeypot fake admin login GET (logs attacker scan)","tags":["Admin / Honeypot"]},"post":{"operationId":"HoneypotController_fakeAdminLoginPost","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Honeypot fake admin login POST (logs attacker credentials attempt)","tags":["Admin / Honeypot"]}},"/api/honeypot/env":{"get":{"operationId":"HoneypotController_fakeEnv","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Honeypot fake .env file (logs secrets-scanner access)","tags":["Admin / Honeypot"]}},"/api/honeypot/wp-admin":{"get":{"operationId":"HoneypotController_fakeWpAdmin","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Honeypot fake WordPress admin (logs WP-scanner access)","tags":["Admin / Honeypot"]}},"/api/honeypot/phpmyadmin":{"get":{"operationId":"HoneypotController_fakePhpMyAdmin","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Honeypot fake phpMyAdmin (logs DB-scanner access)","tags":["Admin / Honeypot"]}},"/api/honeypot/actuator":{"get":{"operationId":"HoneypotController_fakeActuator","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Honeypot fake Spring Boot actuator (logs probe access)","tags":["Admin / Honeypot"]}},"/api/rpa/poll":{"get":{"operationId":"RpaController_poll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Poll for available RPA work (queued jobs or unprocessed contacts)","tags":["RPA"]}},"/api/rpa/job-status":{"get":{"operationId":"RpaController_jobStatus","parameters":[{"name":"dbName","required":true,"in":"query","schema":{"type":"string"}},{"name":"jobId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Poll RPA job status until ready","tags":["RPA"]}},"/api/rpa/job-report":{"post":{"operationId":"RpaController_jobReport","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Report the result of an RPA send job","tags":["RPA"]}},"/api/rpa/system-report":{"post":{"operationId":"RpaController_systemReport","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Report a process-level RPA error not tied to a job","tags":["RPA"]}},"/api/rpa/system-status":{"get":{"operationId":"RpaController_systemStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get RPA system health: errors, paused mailings, account stats","tags":["RPA"]}},"/api/rpa/task-status":{"get":{"operationId":"RpaController_taskStatus","parameters":[{"name":"dbName","required":true,"in":"query","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Legacy: get mailing-level RPA status with item counts","tags":["RPA"]}},"/api/rpa/report":{"post":{"operationId":"RpaController_report","parameters":[{"name":"dbName","required":true,"in":"query","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Legacy: submit a batch report of RPA item send results","tags":["RPA"]}},"/api/campaigns/{id}/test-task":{"post":{"operationId":"CampaignsController_createTestTask","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"idempotency-key","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestTaskDto"}}}},"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"tags":["Campaigns"]}},"/api/campaigns/{id}/test-task/{taskId}":{"get":{"operationId":"CampaignsController_getTestTask","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"tags":["Campaigns"]}},"/api/campaigns/conveyor-health":{"get":{"operationId":"CampaignsController_conveyorHealth","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Campaign conveyor health for this tenant (#347), read-only. Check `not_sending` (#375) reports campaigns that have due READY emails but have not handed a single one to the transport for longer than CAMPAIGN_WATCHDOG_NOT_SENDING_MIN minutes, with the reason (auto_pause / breaker_stop / manual_pause / no_sender_capacity / blocked). A closed send window or a future schedule is not a stop and is not reported.","tags":["Campaigns"],"x-required-scope":["campaigns:read"]}},"/api/campaigns":{"get":{"operationId":"CampaignsController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List campaigns","tags":["Campaigns"]},"post":{"operationId":"CampaignsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCampaignDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a campaign. renderMode: PLATFORM (default) — rendered by our AI (paid, platform_render operation); BYOC — you render the emails yourself and submit them via POST :id/recipients/content, the platform only bills the audit and the send. The mode locks once the pipeline starts. Optional sendWindow is campaign-owned: omitted fields use the safe initial default, enabled:false is explicit 24/7, and later workspace-default changes do not alter a saved campaign.","tags":["Campaigns"]}},"/api/campaigns/backfill-historic-unsubscribes":{"post":{"operationId":"CampaignsController_backfillHistoricUnsubscribes","parameters":[{"name":"dryRun","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"One-off backfill: mark campaign_recipients as UNSUBSCRIBED for addresses already in suppressed_emails (reason=UNSUBSCRIBED), using the #762 matching criterion. dryRun (default true) only lists rows, no write.","tags":["Campaigns"],"x-required-scope":["campaigns:write"]}},"/api/campaigns/overview":{"get":{"operationId":"CampaignsController_overview","parameters":[{"name":"statuses","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Campaigns overview for dashboard mailings widget","tags":["Campaigns"],"x-required-scope":["campaigns:read"]}},"/api/campaigns/{id}":{"get":{"operationId":"CampaignsController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a campaign by id","tags":["Campaigns"]},"patch":{"operationId":"CampaignsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCampaignDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a campaign (creative pool, routing, status and campaign-owned sendWindow). sendWindow is a partial atomic patch: omitted fields are preserved, malformed fields are rejected, and enabled:false is explicit 24/7.","tags":["Campaigns"]},"delete":{"operationId":"CampaignsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a campaign (cascades recipients; ACTIVE must be paused first)","tags":["Campaigns"]}},"/api/campaigns/{id}/geo-risk":{"get":{"operationId":"CampaignsController_geoRisk","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Geo channel-policy risk breakdown of recipients (read-only WARN report)","tags":["Campaigns"]}},"/api/campaigns/{id}/metrics":{"get":{"operationId":"CampaignsController_metrics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Campaign metrics. delivered is estimated as durable sent minus a durable known delivery failure — the union of `finalStatus=BOUNCED` (incl. rows currently awaiting soft-bounce retry) and `inboxPlacement=NOT_RECEIVED` ever recorded for the recipient (#491: read from append-only campaign_event, not a snapshot of the CURRENT row — the row can leave stage=SENT or have inboxPlacement cleared by a canvas step advance without the earlier verdict becoming untrue). The union is counted once per row: `delivery.exclusions.bounced` plus the disjoint `delivery.exclusions.notReceivedWithoutBounce`, so a row carrying both signals is never subtracted twice. delivery.confirmed is null when no reliable delivery signal exists. Inbox Placement remains a separate measurement with its own buckets; only its negative verdict feeds the exclusion. `policyRejected` counts SMTP policy/spam rejects (5.7.x «message blocked», banned sender) — a subset of `bounced` with the opposite diagnosis: sender reputation and route, not a dead address. Being a subset, it is already inside `exclusions.bounced` and is never subtracted again. Do NOT confuse it with `complained` (recipient/FBL complaint about an ACCEPTED message) or `inboxPlacement.spam` (accepted and filed into Spam). `bounceNatures` is the full split (hard/inactive = dead addresses, policy/routing = route, unclassified = nature not parsed); `policyRejectedByProvider`/`policyRejectedByRelay` point at the problem direction. `sent` counts UNIQUE recipients whose message was EVER accepted by SMTP (immutable `mail_send_attempts`), so a soft-bounce retry never lowers it; `sendVolume.acceptedAttempts` counts accepted attempts (one recipient may have several), and the CURRENT pipeline state lives in `currentStageCounts` / `sendVolume.currentStageSent` — those do move backwards. `bounced`/`bounceNatures` are durable: they include rows currently waiting for a soft-bounce retry (`final_status` already reset, `bounce_nature`/`bounce_retries` are not — see #396), not just rows CURRENTLY `final_status=BOUNCED`. The pipeline-state-only reading lives in `bounceVolume.currentStageBounced` / `bounceVolume.pendingRetryBounced` (the latter is the delta the old mutable-only reading used to hide for the whole retry wait). The `notReceivedWithoutBounce` exclusion is still bounded by the CURRENT `stage=SENT` (a row back in retry has no stale placement verdict to carry), while `sent` is monotone and `bounced` is durable (#396) — so the estimate can still lag upward only through `notReceivedWithoutBounce`, never below the truth.","tags":["Campaigns"]}},"/api/campaigns/{id}/send-series":{"get":{"operationId":"CampaignsController_sendSeries","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"bucket","required":true,"in":"query","schema":{"type":"string"}},{"name":"tz","required":true,"in":"query","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Sending speed time series. Buckets sends by day or week (bucket=day|week) in the given IANA timezone (tz, default UTC). Counts each unique recipient in the bucket of its FIRST SMTP-accepted attempt (append-only mail_send_attempts), so historic bars never shrink after a soft-bounce retry. Gaps are returned as zero buckets. `total + undated` equals the `sent` metric; `undated` are legacy rows without a datable trace. Also returns peak, activeBuckets and avgPerActiveBucket.","tags":["Campaigns"]}},"/api/campaigns/{id}/send-readiness":{"get":{"operationId":"CampaignsController_sendReadiness","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Dry-run all send gates for a campaign: status, breaker, campaign-owned send window, sender pool, routing, inbox-check, due READY rows. Read-only, nothing is sent. `effective.sendWindow` exposes the canonical fields, source, configured, windowOpen and nextOpenAt; malformed stored windows fail closed and never become 24/7. operationalState is RUNNING|WAITING|DEGRADED|BLOCKED|COMPLETED; the separate `pipeline` block reports whether the AI stages (render + tier-2 audit) are halted by a provider outage while sending of READY rows continues (DEGRADED + primaryBlocker AI_STAGES_HALTED). `bounceNatures` splits bounces by nature (hard/inactive = dead addresses; policy/routing = route reputation, address is alive) — durable (#396): includes rows currently waiting for a soft-bounce retry, same predicate as GET /metrics. `relayOverview.pausedDirections` lists relay→provider pairs closed by TTL block rules — the campaign keeps sending via other directions, do NOT restart it (warning DIRECTIONS_PAUSED). `directionWait` (#506) counts rows CURRENTLY deferred because no eligible relay exists for the recipient's provider right now (relay×provider block-rule or empty pool) — these rows are QUEUED with a `nextRetryAt`, NOT terminal FAILED, and are reported separately from `terminalFailureReasons` (warning WAITING_DIRECTION); do NOT treat them as dead addresses or retry manually, they resume on their own once the direction reopens.","tags":["Campaigns"]}},"/api/campaigns/{id}/operational-status":{"get":{"operationId":"CampaignsController_operationalStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Opaque tenant/resource-bound keyset cursor","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Single source of truth for \"what is happening with this campaign right now\". Returns lifecycleStatus (DRAFT|ACTIVE|PAUSED|DONE|ERROR|AUDIT_BLOCKED) SEPARATELY from operationalState (RUNNING|WAITING|DEGRADED|BLOCKED|COMPLETED): an ACTIVE campaign that sends nothing is the exact defect this endpoint exists for, so never report \"active\" without the operational qualifier. primaryBlocker is picked by a documented priority table and carries code, since, retryAt, recoverable, suggestedAction and docsKey; `legitimateWait` marks a normal wait (closed send window, future schedule) rather than a stop. `lastProgressAt` is the last REAL hand-off to transport, not the last campaign event. `nextActions[]` lists machine-readable moves — the endpoint never promises to fix anything by itself. UI, notifications and MCP all read this same computation; send-readiness returns the same state plus the full gate dump.","tags":["Campaigns"]}},"/api/campaigns/{id}/task-history":{"get":{"operationId":"CampaignsController_taskHistory","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"default":50,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Opaque tenant/resource-bound keyset cursor","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Paginated durable delivery-task history for a campaign","tags":["Campaigns"]}},"/api/campaigns/{id}/hard-report":{"get":{"operationId":"CampaignsController_hardReport","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Deterministic read-only quality snapshot for a campaign (#1245, first slice only). `auditor.configured` is the raw campaign.auditorConfig exactly as stored, with no interpretation. `auditor.effective` is the SAME canonical merge(global,campaign) (resolveEffectiveAuditorConfig, #100) that auditBatch actually executes on the hot path — no second formula. No mutation, no AI call. NOT YET included in this slice: Tier-1/Tier-2 coverage/attempts/histogram, per-recipient decision receipts, last10Sent similarity clustering, sdrExpert findings, verification matrix, account/list/creative/task inventory, unread replies, and the full JSON archive with TTL/manifest/SHA-256 — those remain open follow-up work for issue #1245.","tags":["Campaigns"]}},"/api/campaigns/{id}/activity":{"get":{"operationId":"CampaignsController_activity","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"recipientId","required":true,"in":"query","schema":{"type":"string"}},{"name":"stage","required":true,"in":"query","schema":{"type":"string"}},{"name":"kind","required":true,"in":"query","schema":{"type":"string"}},{"name":"since","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Unified chronological event feed for a campaign: the full recipient lifecycle (ingested→screened→rendered→scheduled→handed→sent→delivered/opened/clicked/replied/bounced) + campaign actions (start/pause/resume/stop) with actor{who,reason} attribution — including rule-based auto-pauses (bounce/complaint limit, control-email spam/inbox placement, auditor). Read-only. Pagination {cursor,limit<=200}, filters {type,recipientId,stage,kind,since}. For summary numbers use metrics; for \"why is it stalled right now\" use send-readiness.","tags":["Campaigns"]}},"/api/campaigns/{id}/recipients":{"get":{"operationId":"CampaignsController_listRecipients","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"stage","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"canvasStage","required":true,"in":"query","schema":{"type":"string"}},{"name":"finalStatus","required":true,"in":"query","schema":{"type":"string"}},{"name":"emailValid","required":true,"in":"query","schema":{"type":"string"}},{"name":"auditLevel","required":true,"in":"query","schema":{"type":"string"}},{"name":"inboxPlacement","required":true,"in":"query","schema":{"type":"string"}},{"name":"sentFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"sentTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"evStep","required":true,"in":"query","schema":{"type":"string"}},{"name":"evMetric","required":true,"in":"query","schema":{"type":"string"}},{"name":"failureReason","required":true,"in":"query","schema":{"type":"string"}},{"name":"sortBy","required":true,"in":"query","schema":{"type":"string"}},{"name":"sortDir","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List campaign recipients. `stage` accepts a single stage or a comma-separated list (e.g. FAILED,CREATIVE_FAILED). `failureReason` filters by the normalized stage_error code — the same normalization as `failureReasons` in /metrics, so summary and list always agree (#405).","tags":["Campaigns"]}},"/api/campaigns/{id}/recipients/move-stage":{"post":{"operationId":"CampaignsController_moveRecipientsStage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveRecipientsStageDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Move campaign recipients to a canvas stage (no send)","tags":["Campaigns"]}},"/api/campaigns/{id}/recipients/rerender":{"post":{"operationId":"CampaignsController_rerenderRecipients","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RerenderRecipientsDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset unsent recipients back to SCREENED for a fresh re-render; force:true also grants a new paid audit-attempt window (#531)","tags":["Campaigns"]}},"/api/campaigns/{id}/recipients/repair-unsubscribe":{"post":{"operationId":"CampaignsController_repairUnsubscribe","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepairUnsubscribeDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Backfill missing unsubscribe block and reconcile bodyHash for already-rendered rows (no AI re-render, no billing); stages:[\"FAILED\"] recovers rows burned by body_hash_mismatch (#511); stages:[\"SKIPPED\"] reconciles the hash on stopped rows without unstopping them (#520); CREATIVE_FAILED rows stuck on quality_below_threshold with a now-valid unsubscribe mechanism are requeued to RENDERED for a fresh audit, not force-passed (#526)","tags":["Campaigns"]}},"/api/campaigns/{id}/retry-ai-failures":{"post":{"description":"Returns CREATIVE_FAILED rows with an AI cause back into the pipeline (stage SCREENED). Response: {reset, reason, effectiveProvider, model, failureReasons, lastRecovery}. reason is the outcome code: retried (reset>0, failureReasons = which causes were fixed), nothing_to_retry (no AI failures and nothing was recovered), already_recovered (no failures because a previous call already returned them — most often a side effect of resume; when and how many — in lastRecovery), same_provider (rows have already been tried on the current provider). reset=0 by itself does NOT mean an error — check reason. If the AI provider is not configured — 409 ai_provider_unavailable.","operationId":"CampaignsController_retryAiFailures","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Retry unsent AI failures with the current tenant provider/model — reset=0 is an outcome, read reason (retried | already_recovered | nothing_to_retry | same_provider)","tags":["Campaigns"]}},"/api/campaigns/{id}/reconcile-from-dialogs":{"post":{"operationId":"CampaignsController_reconcileFromDialogs","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"dryRun","required":true,"in":"query","schema":{"type":"string"}},{"name":"linkCreatives","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"One-time: reconcile campaign recipients from existing dialogs (migration)","tags":["Campaigns"]}},"/api/campaigns/{id}/pour":{"post":{"operationId":"CampaignsController_pour","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PourCampaignDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Pour recipients into a campaign. Body takes EXACTLY ONE of: listId (CONTACT list — reads STATIC contactListMembership, smart filters NOT re-expanded), companyListId (#1221: COMPANY list — pours live contacts of ALL companies in that list in one call; a company with zero contacts contributes zero recipients and is not an error), or allContacts:true (entire tenant base). Idempotent (dedup by normalized email) — a repeat call with the same listId/companyListId adds nothing new and returns the durable sourceSync lifecycle/reason. Empty STATIC sources remain WAITING and bound for reconciliation. SMART sources are explicitly unsupported. #565: an empty body is rejected (400) — listId/companyListId/allContacts is REQUIRED, exactly one. #716: ONLY ACTIVE email channels are taken; all ACTIVE channels are materialized and one campaign/email row is retained. Response fields: added, noEmail, duplicate, inactiveChannel, notFound, sourceSync.","tags":["Campaigns"]}},"/api/campaigns/{id}/push":{"post":{"operationId":"CampaignsController_push","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushContactsDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Push contacts directly into campaign (API-push, e.g. from form webhook)","tags":["Campaigns"]}},"/api/campaigns/{id}/pour-from-leads":{"post":{"operationId":"CampaignsController_pourFromLeads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PourFromLeadsDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Pour recipients into a campaign from CRM leads by filter (pipelineId/stageId/interestStatus/limit). #716: ONLY channels with status ACTIVE are taken; contacts whose email channels are all bounced off do not enter the campaign — their count is in the inactiveChannel field of the response.","tags":["Campaigns"]}},"/api/campaigns/{id}/screen":{"post":{"operationId":"CampaignsController_screen","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Screening of NEW recipients (suppression + stop-list): NEW→SCREENED|SKIPPED. A pipeline step between pour and prepare.","tags":["Campaigns"]}},"/api/campaigns/{id}/recipients/content":{"post":{"operationId":"CampaignsController_submitRenderedContent","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitRenderedContentDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Submit self-rendered (BYOC) email content for SCREENED recipients: [{recipientId, subject, bodyHtml, bodyText?}], batch <=100, bodyHtml <=256KB. Submission is free; the content goes through a mandatory paid audit (audit/audit_failed operations), rejection reasons are coarse categories in auditCategories. Limit of 5 audit iterations per recipient; the campaign is blocked (AUDIT_BLOCKED) on systematic rejections.","tags":["Campaigns"]}},"/api/campaigns/{id}/recipients/{rid}/manual":{"patch":{"operationId":"CampaignsController_manualUpdateRecipient","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"rid","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Manual edit of a job by an operator: subject/body/scheduledAt/stage. ONLY from the interface under a human session — agents (MCP/API key) get 403 human_only, because this bypasses the auditor. Every edit is written to the campaign log and to the audit-log with the previous values.","tags":["Campaigns"]}},"/api/campaigns/{id}/recipients/{recipientId}/attachment-link":{"get":{"operationId":"CampaignsController_recipientAttachmentLink","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"recipientId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Refresh a signed link to a recipient personal PDF without regeneration. Returns the exact fingerprint/hash and expiry; this is not permission to send.","tags":["Campaigns"]}},"/api/campaigns/{id}/preparations":{"post":{"operationId":"CampaignsController_enqueuePreparation","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignPreparationRequestDto"}}}},"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"summary":"Start or join a durable bounded preparation operation (no sending). Poll statusUrl; accepted means queued, not completed. Preferred over synchronous prepare for AI and personal PDFs.","tags":["Campaigns"]}},"/api/campaigns/{id}/preparations/{generationId}":{"get":{"operationId":"CampaignsController_preparationStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"generationId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Read a tenant-bound preparation operation. Completed result has the same fields as prepare; failed contains a safe error code/message. This endpoint never sends.","tags":["Campaigns"]}},"/api/campaigns/{id}/prepare":{"post":{"operationId":"CampaignsController_prepare","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Prepare and audit a bounded window of provider-eligible recipients. limit is the requested batch size, not total queue capacity. Inspect preparation.reason and send-readiness before retrying; remaining audience does not mean more content should be generated now.","tags":["Campaigns"]}},"/api/campaigns/{id}/dispatch":{"post":{"operationId":"CampaignsController_dispatch","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Assign sender account + schedule to READY recipients (no send yet). Optional per-campaign schedule override (#265): body { scheduledAt: ISO-in-future, recipientIds?: string[] } — explicit override beats the recommended contact best_send_time; a past scheduledAt is rejected with 400 (never silently projected).","tags":["Campaigns"]}},"/api/campaigns/{id}/send":{"post":{"operationId":"CampaignsController_send","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Hand dispatched READY recipients to the mail_outbox queue (limit=1 for first test send)","tags":["Campaigns"]}},"/api/campaigns/{id}/sync-events":{"post":{"operationId":"CampaignsController_syncEvents","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Sync open/click/bounce events from Dialog records back to recipients. Side effects by bounce nature (#345): hard/inactive/unknown → suppression + GLOBAL stop-list; policy/routing → relay→provider direction pause (TTL block rule) instead of burning the address; soft → scheduled retry.","tags":["Campaigns"]}},"/api/campaigns/{id}/restore-infra-failed":{"post":{"description":"Resets the circuit breaker (PAUSED → ACTIVE) AND, as a side effect, recovers unsent AI failures the same way retry-ai-failures with force does. The recovery result is in the aiRecovery field {reset, reason, effectiveProvider, model, failureReasons}: reset — how many rows returned to the pipeline, failureReasons — the reasons they failed for. So retry-ai-failures called right after resume normally returns reset=0 with reason=already_recovered — that is not an error.","operationId":"CampaignsController_restoreInfraFailed","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreInfraFailedDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Resume a PAUSED campaign (reset circuit breaker) — also retries AI failures","tags":["Campaigns"]}},"/api/campaigns/{id}/resume":{"post":{"operationId":"CampaignsController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"tags":["Campaigns"]}},"/api/campaigns/{id}/pause":{"post":{"description":"Stops sending (ACTIVE → PAUSED) with the same attribution as /resume: a PAUSED event in the campaign feed with actor{who,reason}. Unlike /resume this is NOT a timer — auto-resume will not happen, work can only be resumed by another /resume or PATCH {status:\"ACTIVE\"}. An optional body.reason goes into the feed event. From a status other than ACTIVE — 409 invalid_status_transition. PATCH /campaigns/:id {status:\"PAUSED\"} keeps working as before (compatibility) — this endpoint does not replace it, it closes an asymmetry: the start/stop pair had no named endpoint for stopping, unlike resume.","operationId":"CampaignsController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseCampaignDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Pause an ACTIVE campaign (symmetric to /resume)","tags":["Campaigns"]}},"/api/campaigns/{id}/recipients/{rid}":{"get":{"operationId":"CampaignsController_getRecipient","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"rid","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a recipient with its event log. #368: `sendAttempts` is the IMMUTABLE transport history (one row per attempt, `result=success` means SMTP accepted it) and `retiredSends` holds snapshots of sends that a retry has already wiped off the row — a soft-bounce retry (#346) or a canvas step advance resets `stage/sentAt/accountId/fromEmail/messageId/dialogId`, so the recipient columns describe only the CURRENT attempt. `acceptedAttempts` tells how many times a message to this recipient was actually accepted.","tags":["Campaigns"]}},"/api/best-send-time":{"post":{"operationId":"BestSendTimeController_resolve","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BestSendTimeDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Resolve recommended send time without scheduling; AI fallback uses normal usage logging and billing","tags":["Best Send Time"]}},"/api/v1/agent-guide":{"get":{"operationId":"AgentGuideController_guide","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Expert guide: capability map + recommended flows for MCP/A2A agents","tags":["Agent Card"]}},"/api/v1/agent-guide/context":{"get":{"operationId":"AgentGuideController_context","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Current tenant context core: recent lists, briefs and tasks","tags":["Agent Card"],"x-required-scope":["agent:read"]}},"/api/v1/agent-guide/resume":{"get":{"operationId":"AgentGuideController_resume","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Resume snapshot (read-only): tenant context core, own recent notifications and self-notes, plus an honest next_step","tags":["Agent Card"],"x-required-scope":["agent:read"]}},"/api/v1/agent-guide/campaign-sender-capability":{"get":{"operationId":"AgentGuideController_campaignSenderCapability","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"SDR capability preflight (read-only): structured sender-assignment contract + a receipt required before a campaign write that touches senderConfig or sendWindow","tags":["Agent Card"],"x-required-scope":["agent:read"]}},"/api/admin/agent-guide/overrides":{"get":{"operationId":"AgentGuideAdminController_getOverrides","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the editable agent-guide overrides (raw JSON overlay + meta)","tags":["Admin"],"x-required-scope":["admin:read"]},"put":{"operationId":"AgentGuideAdminController_putOverrides","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentGuideOverridesDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Replace the agent-guide overrides. Body: { domains?, operations?, controllerDomain? } — field-level overlay on the code defaults. Empty/omitted fields fall back to defaults.","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/agent-guide/effective":{"get":{"operationId":"AgentGuideAdminController_getEffective","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview the effective (defaults + overrides) guide map","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/agent-guide/coverage":{"get":{"operationId":"AgentGuideAdminController_coverage","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Guidance coverage report: how many MCP tools have op-level guidance vs domain-fallback vs none. Shows honestly where the expert layer is empty.","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/canvas/{id}/flow":{"get":{"operationId":"CanvasController_getFlow","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the canvas flow definition of a campaign","tags":["Canvas"]},"put":{"operationId":"CanvasController_putFlow","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Replace the canvas flow definition (whole document)","tags":["Canvas"]}},"/api/canvas/{id}/stats":{"get":{"operationId":"CanvasController_stats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Per-step canvas stats (GROUP BY canvasStage)","tags":["Canvas"]}},"/api/canvas/{id}/enrollments":{"get":{"operationId":"CanvasController_enrollments","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"type":"number"}},{"name":"stage","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List canvas enrollments (reuse campaign recipients)","tags":["Canvas"]}},"/api/canvas/{id}/tick":{"post":{"operationId":"CanvasController_tick","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run one orchestrator tick: claim → bring to READY → advance (does NOT send; the single send point picks up READY on its own)","tags":["Canvas"]}},"/api/site-enrichment/detect-forms":{"post":{"operationId":"SiteEnrichmentController_detectFormsRoute","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DetectFormsDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#968 detect forms on a page from HTML: hasForm — whether any form is present at all; hasContactForm — a CONTACT-US form (excluding search/login/subscribe/catalog filter); forms[] — submit address (absolute if pageUrl is supplied), method, kind (contact|search|login|subscribe|catalog_filter|other), confidence (0..1), and reasons[] — a human-readable basis for the decision.","tags":["Site Enrichment"],"x-required-scope":["site-enrichment:read"]}},"/api/site-enrichment/tasks":{"post":{"operationId":"SiteEnrichmentController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSiteEnrichmentTaskDto"}}}},"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"summary":"#903/#889 enqueue the canonical site-crawl task (durable, DB is the source of truth)","tags":["Site Enrichment"],"x-required-scope":["site-enrichment:write"]},"get":{"operationId":"SiteEnrichmentController_findAll","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"scoringTaskId","required":true,"in":"query","schema":{"type":"string"}},{"name":"owned","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#953 list of site-crawl tasks: both linked to a scoring task (scoringTaskId) and unlinked (owned=false — e.g. launched via MCP without a task)","tags":["Site Enrichment"],"x-required-scope":["site-enrichment:read"]}},"/api/site-enrichment/tasks/preview":{"get":{"operationId":"SiteEnrichmentController_preview","parameters":[{"name":"listId","required":true,"in":"query","schema":{"type":"string"}},{"name":"domainField","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#955 preview list coverage WITHOUT starting a crawl: how many cards are in the list, how many have the domain field filled, how many unique domains among them — plus coverage of ALL eligible fields at once (website/domain/URL custom fields)","tags":["Site Enrichment"],"x-required-scope":["site-enrichment:read"]}},"/api/site-enrichment/tasks/{id}":{"get":{"operationId":"SiteEnrichmentController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Status/counters of a site-crawl task","tags":["Site Enrichment"]}},"/api/site-enrichment/tasks/{id}/events":{"get":{"operationId":"SiteEnrichmentController_listEvents","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#903 task transition log, read from the DB, cursor=last received seq","tags":["Site Enrichment"]},"post":{"operationId":"SiteEnrichmentController_addAgentNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentNoteDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#1144 atom B: an agent note into the task journal (kind=agent_note, author taken from the request key/JWT, NOT from the body). Written through the SINGLE existing journal writer (SiteEnrichmentService.appendEvent) — there is no second one. Does NOT touch the task's updatedAt/status/processed/counters and does not count towards MAX_RESUME_ATTEMPTS: an observer note must not affect the observed thing (otherwise it would delay the watchdog's staleness pickup). The body is ONLY {text}; the system kind cannot be supplied from outside (forbidNonWhitelisted → 400 before the controller, see CreateAgentNoteDto).","tags":["Site Enrichment"]}},"/api/site-enrichment/tasks/{id}/reason-summary":{"get":{"operationId":"SiteEnrichmentController_reasonSummary","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#949 summary of failure reasons (for a clickable filter above the journal)","tags":["Site Enrichment"]}},"/api/site-enrichment/tasks/{id}/stats":{"get":{"operationId":"SiteEnrichmentController_stats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#957/#969 unified task statistics read from durable rows: funnel (cards AND domains counted separately, including sourceTotal/visitsSaved from dedup), collected data (substrate-writer receipt — emails/phones/socials/text/native fields, per-map and total), acquisition method, pace/forecast state by domain (plus elapsedSeconds/cardsPerHour/etaAt), breakdown by reason (byReason), breakdown by outcome (byStatus: OK/DOWN/NO_SITE/EMPTY/CAPTCHA) and actual homepage HTTP codes (byHttpStatus, httpStatus:null — no response), launch (launch parameters echoed back — listId/listName/domainField/visitPages/timeoutMs/maxAttempts/mode/surface/startedBy), and links (direct URLs to the scoring-task card and this task's journal) — WITHOUT the full result list (use tasks/:id/items for paginated inspection). The same method serves the legacy alias GET /icp-tasks/companies/scrape/:taskId (stats key) — the only route that actually reaches MCP.","tags":["Site Enrichment"]}},"/api/site-enrichment/tasks/{id}/items":{"get":{"operationId":"SiteEnrichmentController_listItems","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"reasonCode","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#952/#969 crawl task items: paginated, with a filter by outcome (status=OK|DOWN|NO_SITE|EMPTY|CAPTCHA) and/or reason code (reasonCode)","tags":["Site Enrichment"]}},"/api/site-enrichment/tasks/{id}/raw":{"get":{"operationId":"SiteEnrichmentController_rawFetch","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"companyId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#965 diagnostic snapshot of the RAW visited page text(s) for ONE company (homepage + \"Contacts\", BEFORE contact extraction) — TTL 12h, only while diagnostic mode is on; an empty data is legitimate, not an error","tags":["Site Enrichment"]}},"/api/site-enrichment/tasks/{id}/cancel":{"post":{"operationId":"SiteEnrichmentController_cancel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel a site-crawl task (durable — status in the DB, visible to any process)","tags":["Site Enrichment"]}},"/api/site-enrichment/tasks/{id}/pause":{"post":{"operationId":"SiteEnrichmentController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#952 pause a crawl task (durable, non-terminal — resumed via .../resume)","tags":["Site Enrichment"]}},"/api/site-enrichment/tasks/{id}/resume":{"post":{"operationId":"SiteEnrichmentController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#952 resume a paused crawl task","tags":["Site Enrichment"]}},"/api/site-enrichment/tasks/{id}/retry":{"post":{"operationId":"SiteEnrichmentController_retry","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Retry still-not-OK companies of a terminal task (FAILED/PARTIAL/CANCELLED)","tags":["Site Enrichment"]}},"/api/site-enrichment/backlog/stale-http-status":{"get":{"operationId":"SiteEnrichmentController_staleOkBacklog","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#969 backfill: count and ids of tenant cards where customFields.site_status='ok' but a real crawl HTTP code was never recorded (customFields.site_status_http is empty). The condition is live (the same as the migration itself), NOT the write-once flag site_needs_recrawl_969 — a card that has already actually been recrawled drops out of the list by itself, with no separate cleanup step. Not retroactive code guessing.","tags":["Site Enrichment"],"x-required-scope":["site-enrichment:read"]}},"/api/site-enrichment/backlog/stale-http-status/requeue":{"post":{"operationId":"SiteEnrichmentController_requeueStaleOkBacklog","parameters":[{"name":"batchSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#969 backfill: a controlled BATCH re-crawl of flagged cards (batchSize, defaults to 50, cap 200) — via the same create()/run() as a normal task enqueue; not a separate crawl engine.","tags":["Site Enrichment"],"x-required-scope":["site-enrichment:write"]}},"/api/site-enrichment/backlog/down-wait-timeout":{"get":{"operationId":"SiteEnrichmentController_downBacklog","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#1126: count and ids of tenant cards where customFields.site_status='down' AND customFields.site_last_reason is one of a NARROW list of transient failures of OUR OWN infrastructure (currently only 'wait_timeout'), AND customFields.site_status_http is empty (navigation never reached a response). NOT cards with dns_error/tls_error/conn_refused — those are responses FROM THE WORLD about the site, not a failure of our attempt, and are deliberately excluded (see SiteEnrichmentService.TRANSIENT_DOWN_REASONS). The condition is live — a card that has already actually been recrawled drops out of the list by itself.","tags":["Site Enrichment"],"x-required-scope":["site-enrichment:read"]}},"/api/site-enrichment/backlog/down-wait-timeout/requeue":{"post":{"operationId":"SiteEnrichmentController_requeueDownBacklog","parameters":[{"name":"batchSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#1126: a controlled BATCH re-crawl of cards from backlog/down-wait-timeout (batchSize, defaults to 50, cap 200) — via the same create()/run() as a normal task enqueue; not a separate crawl engine, only a real crawl changes a card's status.","tags":["Site Enrichment"],"x-required-scope":["site-enrichment:write"]}},"/api/development-pipeline/board":{"get":{"operationId":"DevelopmentPipelineController_board","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Board across 4 delivery stages (queue/agents/merge/deploy)","tags":["Development Pipeline"]}},"/api/development-pipeline/attention":{"get":{"operationId":"DevelopmentPipelineController_attentionSnapshot","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"\"Needs an owner\" block + delivery strip (issue #1004): red tasks/deploys, findings without an issue, agent questions, approve branches waiting for merge, \"no priority\" counter, main-pipeline/smoke-prod/merge-queue status, main→smoke stall past the threshold (issue #999, atom A7: isHanging/ageMinutes on mainPipeline), wall/acceptance verdict on the MR head SHA (issue #999, atom A5: mergeAcceptance[].hasVerdictOnHeadSha/verdict, reading MR notes in the acceptance_watch.py format, no GitLab mutations)","tags":["Development Pipeline"]}},"/api/development-pipeline/prod-counter":{"get":{"operationId":"DevelopmentPipelineController_prodCounter","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"\"IN PROD\" showcase (issue #1010): issues that shipped via a successful main pipeline with green smoke-prod; done/merged do not count as prod","tags":["Development Pipeline"]}},"/api/development-pipeline/ci-runs-per-merge":{"get":{"operationId":"DevelopmentPipelineController_ciRunsPerMerge","parameters":[{"name":"minutes","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"\"CI runs per merge\" KPI over a window (issue #999, atom A9), read-only: the same calculation as warden/runs_per_merge.py. There are no pipeline/deploy launch buttons here and never will be — GitLab reads only.","tags":["Development Pipeline"]}},"/api/development-pipeline/journal":{"get":{"operationId":"DevelopmentPipelineController_journalSnapshot","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Tester journal !505 as source of truth (issue #500): block 3 rules, roles, block 2 findings and the integrity gate. GitLab being unavailable does not fail the response — `available:false` + `reason`.","tags":["Development Pipeline"]}},"/api/development-pipeline/journal/findings/{findingId}/create-issue":{"post":{"operationId":"DevelopmentPipelineController_createIssueFromFinding","parameters":[{"name":"findingId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIssueFromFindingDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create an issue from a journal finding that has no issue number (issue #500 p.2) — label `from::journal`, in the chosen project. Only on an explicit owner click, there is no auto-creation without a human.","tags":["Development Pipeline"]}},"/api/development-pipeline/journal/findings":{"post":{"operationId":"DevelopmentPipelineController_appendJournalFinding","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendJournalFindingDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Append one finding line to Block 2 of journal !505 (issue #1152) — an atomic write via API with CAS by length+sha256, instead of a client PUT of the whole description. Visible on the MCP surface.","tags":["Development Pipeline"]}},"/api/development-pipeline/issues/{iid}/pause":{"patch":{"operationId":"DevelopmentPipelineController_setPaused","parameters":[{"name":"iid","required":true,"in":"path","schema":{"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPausedDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Pause an issue — do not pick it up for work while the `paused` label is set","tags":["Development Pipeline"]}},"/api/development-pipeline/issues/priority-triage":{"post":{"operationId":"DevelopmentPipelineController_priorityTriage","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriorityTriageDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"One-off idempotent triage: set priority on every open issue without a P label","tags":["Development Pipeline"]}},"/api/development-pipeline/issues/{iid}/priority":{"patch":{"operationId":"DevelopmentPipelineController_setPriority","parameters":[{"name":"iid","required":true,"in":"path","schema":{"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPriorityDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Issue priority — P1-critical / P2-integrity / P3-ux","tags":["Development Pipeline"]}},"/api/development-pipeline/issues/{iid}/model":{"patch":{"operationId":"DevelopmentPipelineController_setModel","parameters":[{"name":"iid","required":true,"in":"path","schema":{"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetModelDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Executor model — sonnet (default) / opus / fable / codex-sol / codex-terra","tags":["Development Pipeline"]}},"/api/development-pipeline/issues/{iid}/take-next":{"patch":{"operationId":"DevelopmentPipelineController_takeNext","parameters":[{"name":"iid","required":true,"in":"path","schema":{"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectScopedDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"\"Take next\" — unpause and move the issue to the front of the queue (P1)","tags":["Development Pipeline"]}},"/api/development-pipeline/issues/{iid}/close":{"patch":{"operationId":"DevelopmentPipelineController_closeIssue","parameters":[{"name":"iid","required":true,"in":"path","schema":{"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectScopedDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Close an issue on behalf of the owner (issue #439) — label `closed::by-owner` + close + comment + audit record","tags":["Development Pipeline"]}},"/api/development-pipeline/conveyor/issues":{"post":{"operationId":"ConveyorBridgeController_createIssue","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConveyorIssueDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new conveyor task (issue #1001) via the bridge; on an empty/unclear description — 422 with validator questions","tags":["Development Pipeline — Conveyor Bridge"]}},"/api/development-pipeline/conveyor/issues/{num}/priority":{"patch":{"operationId":"ConveyorBridgeController_setPriority","parameters":[{"name":"num","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetConveyorPriorityDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set conveyor task priority P1/P2/P3 in one click (issue #1001)","tags":["Development Pipeline — Conveyor Bridge"]}},"/api/development-pipeline/conveyor/issues/{num}/pause":{"patch":{"operationId":"ConveyorBridgeController_setPaused","parameters":[{"name":"num","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetConveyorPausedDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Pause/unpause a conveyor task from the console in one click (issue #1001, owner request 17.08)","tags":["Development Pipeline — Conveyor Bridge"]}},"/api/development-pipeline/conveyor/issues/{num}/action":{"post":{"operationId":"ConveyorBridgeController_issueAction","parameters":[{"name":"num","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConveyorIssueActionDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"retry/cancel a conveyor task from blocked/failed (issue #1001)","tags":["Development Pipeline — Conveyor Bridge"]}},"/api/development-pipeline/conveyor/template":{"get":{"operationId":"ConveyorBridgeController_getTemplate","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Live TEMPLATE.md + docs/pipeline/*.md from the bridge for the \"Rules\" tab — no copy in frontend code (issue #1001)","tags":["Development Pipeline — Conveyor Bridge"]}},"/api/marking/patterns":{"get":{"operationId":"MarkingController_listPatterns","parameters":[{"name":"result","required":true,"in":"query","schema":{"type":"string"}},{"name":"enabled","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all marking patterns","tags":["Marking"],"x-required-scope":["marking:read"]},"post":{"operationId":"MarkingController_createPattern","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new marking pattern","tags":["Marking"],"x-required-scope":["marking:write"]}},"/api/marking/patterns/{id}/toggle":{"patch":{"operationId":"MarkingController_togglePattern","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Enable or disable a marking pattern","tags":["Marking"]}},"/api/marking/patterns/{id}":{"delete":{"operationId":"MarkingController_deletePattern","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a marking pattern","tags":["Marking"]}},"/api/marking/classify":{"post":{"operationId":"MarkingController_classify","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Classify a message against the marking patterns","tags":["Marking"],"x-required-scope":["marking:read"]}},"/api/marking/dialogs/{id}/classify":{"post":{"operationId":"MarkingController_classifyDialog","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Classify a specific dialog against the marking patterns","tags":["Marking"]}},"/api/provider-configs":{"get":{"operationId":"ProviderConfigController_list","parameters":[{"name":"enabled","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all email provider configurations","tags":["Provider Config"]}},"/api/provider-configs/resolve":{"get":{"operationId":"ProviderConfigController_resolve","parameters":[{"name":"email","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Resolve the email provider by domain","tags":["Provider Config"],"x-required-scope":["settings:read"]}},"/api/provider-configs/{provider}":{"get":{"operationId":"ProviderConfigController_getOne","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single provider configuration by provider key","tags":["Provider Config"]},"put":{"operationId":"ProviderConfigController_upsert","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Upsert a provider configuration","tags":["Provider Config"]},"delete":{"operationId":"ProviderConfigController_remove","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a provider configuration","tags":["Provider Config"]}},"/api/provider-configs/{provider}/toggle":{"patch":{"operationId":"ProviderConfigController_toggle","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Enable or disable a provider configuration","tags":["Provider Config"]}},"/api/provider-configs/{provider}/domains":{"post":{"operationId":"ProviderConfigController_addDomain","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a domain mapping to a provider configuration","tags":["Provider Config"]}},"/api/provider-configs/{provider}/domains/{pattern}":{"delete":{"operationId":"ProviderConfigController_removeDomain","parameters":[{"name":"pattern","required":true,"in":"path","schema":{"type":"string"}},{"name":"matchType","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove a domain mapping from a provider configuration","tags":["Provider Config"]}},"/api/legal/terms":{"get":{"operationId":"LegalController_getTerms","parameters":[{"name":"locale","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the current terms of service text (public). Web default is ru; the ldm_terms agent tool requests locale=en explicitly.","tags":["Legal"]},"put":{"operationId":"LegalController_updateTerms","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update the terms of service text (SUPER only)","tags":["Legal"],"x-required-scope":["legal:write"]}},"/api/legal/documents":{"get":{"operationId":"LegalController_listDocuments","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all legal documents (key/title/summary) — public","tags":["Legal"]}},"/api/legal/documents/{key}":{"get":{"operationId":"LegalController_getDocument","parameters":[{"name":"key","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get one legal document by key (terms|aup|privacy|dpa|mode2|campaign_guarantee|security) — public","tags":["Legal"]}},"/api/legal/documents/{key}/publish":{"post":{"operationId":"LegalController_publishVersion","parameters":[{"name":"key","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Publish a new version of a legal document (SUPER)","tags":["Legal"]}},"/api/legal/documents/{key}/versions":{"get":{"operationId":"LegalController_listVersions","parameters":[{"name":"key","required":true,"in":"path","schema":{"type":"string"}},{"name":"locale","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List versions of a legal document (SUPER)","tags":["Legal"]}},"/api/legal/acceptances":{"post":{"operationId":"LegalController_recordAcceptance","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Record the current user's acceptance of a legal document","tags":["Legal"]},"get":{"operationId":"LegalController_listAcceptances","parameters":[{"name":"userId","required":true,"in":"query","schema":{"type":"string"}},{"name":"docKey","required":true,"in":"query","schema":{"type":"string"}},{"name":"tenantId","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Acceptance registry — who accepted which version when (SUPER)","tags":["Legal"],"x-required-scope":["legal:read"]}},"/api/legal/acceptances/me":{"get":{"operationId":"LegalController_myAcceptances","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"The current user's own acceptances","tags":["Legal"]}},"/api/legal":{"get":{"operationId":"LegalController_listAll","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all legal documents (SUPER only)","tags":["Legal"]}},"/api/dsar":{"post":{"operationId":"DsarController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Submit a data-subject request (public): erasure erases+suppresses immediately","tags":["DSAR"]},"get":{"operationId":"DsarController_list","parameters":[{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Data-subject request registry (SUPER)","tags":["DSAR"]}},"/api/dsar/lookup":{"get":{"operationId":"DsarController_lookup","parameters":[{"name":"email","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Look up a subject by email: global suppression status + request history (SUPER)","tags":["DSAR"],"x-required-scope":["legal:read"]}},"/api/dsar/{id}/resolve":{"post":{"operationId":"DsarController_resolve","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Resolve a data-subject request (SUPER)","tags":["DSAR"]}},"/api/system/version":{"get":{"operationId":"SystemController_getVersion","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Deployed build version: app semver + commit SHA + build timestamp (public)","tags":["System"]}},"/api/system/operator":{"get":{"operationId":"SystemController_getOperator","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Operator (legal entity) details from config — null fields mean \"not filled by owner\" (public)","tags":["System"]}},"/api/connectors/tilda/webhook":{"post":{"operationId":"ConnectorsController_tildaWebhook","parameters":[{"name":"pipelineId","required":true,"in":"query","schema":{"type":"string"}},{"name":"stageId","required":true,"in":"query","schema":{"type":"string"}},{"name":"listId","required":true,"in":"query","schema":{"type":"string"}},{"name":"source","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Tilda form webhook (disabled — requires authorization, see #193)","tags":["Connectors"],"x-required-scope":["connectors:write"]}},"/api/connectors/dadata/name":{"get":{"operationId":"ConnectorsController_dadataName","parameters":[{"name":"q","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Normalize Russian full name via DaData API","tags":["Connectors"],"x-required-scope":["connectors:read"]}},"/api/share-og/{code}":{"get":{"operationId":"SharePublicController_getOgHtml","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Render OG meta-tag HTML for bot crawlers by short code","tags":["Share Public"]}},"/api/s/{code}":{"get":{"operationId":"SharePublicController_getByShortCode","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get publicly-shared entity by short code (no auth)","tags":["Share Public"]}},"/api/share-public/{token}":{"get":{"operationId":"SharePublicController_getShared","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get publicly-shared entity by legacy full token (no auth)","tags":["Share Public"]}},"/api/health":{"get":{"operationId":"HealthController_liveness","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Liveness probe","tags":["Health"]}},"/api/health/capacity":{"get":{"operationId":"HealthController_capacity","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Resource capacity check for load admission","tags":["Health"]}},"/api/unsubscribe/{token}":{"get":{"operationId":"UnsubscribeController_handleUnsubscribe","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Handle unsubscribe click from email link (public)","tags":["Unsubscribe"]},"post":{"operationId":"UnsubscribeController_oneClickUnsubscribe","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"RFC 8058 one-click unsubscribe endpoint","tags":["Unsubscribe"]}},"/api/v1/health":{"get":{"operationId":"AgentCardController_health","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Public API health check","tags":["Agent Card"]}},"/api/v1/.well-known/agent-card.json":{"get":{"operationId":"AgentCardController_card","parameters":[{"name":"full","required":false,"in":"query","description":"1/true → full uncurated capability list","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Get the LDM-proprietary agent card. Default response is the curated capability subset (#477); pass ?full=1 for the complete OpenAPI-derived catalog.","tags":["Agent Card"]}},"/api/v1/.well-known/agent.json":{"get":{"operationId":"AgentCardController_cardA2A","parameters":[{"name":"full","required":false,"in":"query","description":"1/true → full uncurated skill list","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Get the A2A 0.2.5-compliant agent card. Default response is the curated skill subset (#477); pass ?full=1 for the complete OpenAPI-derived catalog.","tags":["Agent Card"]}},"/api/v1/.well-known/oauth-protected-resource":{"get":{"operationId":"AgentCardController_oauthProtectedResource","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"RFC 9728 OAuth 2.0 Protected Resource Metadata (#476). LDM has no OAuth authorization server yet — this document is honest about that and points automatable clients at the key-less MCP bootstrap flow (ldm_register) instead of a dead-end auth server.","tags":["Agent Card"]}},"/api/billing/balance":{"get":{"operationId":"BillingController_getBalance","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Account balance (USD) + operation prices (platform_render/audit/audit_failed/send) + topUpUrl. Top-up is only via the personal account; every paid response contains a _billing { operation, cost, balance_after } block.","tags":["Billing"],"x-required-scope":["billing:read"]}},"/api/billing/ledger":{"get":{"operationId":"BillingController_listLedger","parameters":[{"name":"campaignId","required":true,"in":"query","schema":{"type":"string"}},{"name":"entryType","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Balance movement journal (billing_ledger): entryType (CHARGE|CREDIT|ADJUSTMENT|REFUND), operation, cost, balance_after, campaignId/recipientId. Also shows background cron-pipeline charges that are absent from HTTP responses. Filters: campaignId, entryType.","tags":["Billing"],"x-required-scope":["billing:read"]}},"/api/admin/billing/tenants":{"get":{"operationId":"AdminBillingController_listTenantBalances","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Balances of all tenants (wave 4): dbName, name, selfSignup, balance (null = unlimited), sum of charges over 30 days. For the admin \"Billing and pricing\" tab.","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/admin/billing/tenants/{dbName}/ledger":{"get":{"operationId":"AdminBillingController_tenantLedger","parameters":[{"name":"dbName","required":true,"in":"path","schema":{"type":"string"}},{"name":"entryType","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"cursor","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Ledger for a specific tenant (wave 4): CHARGE|CREDIT|ADJUSTMENT|REFUND movements, cursor pagination.","tags":["Admin"]}},"/api/admin/billing/pricing":{"get":{"operationId":"AdminBillingController_getPricing","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Platform price registry: code defaults, registry overrides and effective prices + signupCreditUsd.","tags":["Admin"],"x-required-scope":["admin:write"]},"patch":{"operationId":"AdminBillingController_patchPricing","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Change the platform price (field-level merge): { pricing: { : usd | null }, signupCreditUsd?: usd, selfSignupActiveLimit?: int }. null on an operation = revert to the code default. selfSignupActiveLimit — beta capacity (max ACTIVE self-signup accounts; beyond it — a PENDING queue). The change is visible everywhere without a deploy; an AuditEvent is written.","tags":["Admin"],"x-required-scope":["admin:write"]}},"/api/public/pricing":{"get":{"operationId":"PublicPricingController_pricing","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Public platform pricing (USD): operations (inbox_placement / inbox_placement_byoc / creative_approval / ...) + starting balance on signup (signupCreditUsd). No authorization required; tenant overrides do not apply.","tags":["Public"]}},"/api/deliverability/probe/relay-reach":{"post":{"operationId":"DeliverabilityController_startRelayReach","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"summary":"C1: probe whether the given relay can deliver to the given providers (Layer 1 neutral baseline)","tags":["Deliverability"],"x-required-scope":["deliverability:write"]}},"/api/deliverability/probe/creative-through-relay":{"post":{"operationId":"DeliverabilityController_startCreativeThroughRelay","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"summary":"C2: probe whether a specific creative reaches inbox through (relay × provider)","tags":["Deliverability"],"x-required-scope":["deliverability:write"]}},"/api/deliverability/matrix":{"get":{"operationId":"DeliverabilityController_getMatrix","parameters":[{"name":"relayAccountId","required":false,"in":"query","description":"optional; default — the tenant's whole send pool (smtpHost set, status not DISABLED); #512 — NOT isRelay=true, that flag is about probe sources","schema":{"type":"string"}},{"name":"creativeId","required":false,"in":"query","description":"optional; if set — adds the creative axis to the matrix","schema":{"type":"string"}},{"name":"freshSince","required":false,"in":"query","description":"ISO date; consider probes fresher than this date (default = now - 7d)","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the deliverability matrix for the tenant (baseline / creative / block-rule per relay × provider)","tags":["Deliverability"],"x-required-scope":["deliverability:read"]}},"/api/deliverability/probe/creative-tune":{"post":{"operationId":"DeliverabilityController_startCreativeTune","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"summary":"C3: iteratively tune a creative (remove markers) until it reaches inbox via (relay, provider)","tags":["Deliverability"],"x-required-scope":["deliverability:write"]}},"/api/deliverability/probe/full-pipeline":{"post":{"operationId":"DeliverabilityController_startFullPipeline","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"summary":"Full pipeline: run C1 across all (relay × provider) and auto-chain C2/C3 via worker","tags":["Deliverability"],"x-required-scope":["deliverability:write"]}},"/api/deliverability/tuned-variants/{id}/promote":{"post":{"operationId":"DeliverabilityController_promoteTunedVariant","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Promote a tuned variant to a new Creative row in the tenant","tags":["Deliverability"]}},"/api/deliverability/probe/{jobId}":{"get":{"operationId":"DeliverabilityController_getJobStatus","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregate status for a probe batch (jobId)","tags":["Deliverability"]},"delete":{"operationId":"DeliverabilityController_cancelProbeJob","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel pending probes in a batch (in-flight workers no-op safely)","tags":["Deliverability"]}},"/api/deliverability/probes":{"get":{"operationId":"DeliverabilityController_listProbes","parameters":[{"name":"relayAccountId","required":false,"in":"query","schema":{"type":"string"}},{"name":"provider","required":false,"in":"query","schema":{"type":"string"}},{"name":"creativeId","required":false,"in":"query","schema":{"type":"string"}},{"name":"layer","required":false,"in":"query","description":"1 | 2 | 3","schema":{"example":1,"type":"number"}},{"name":"status","required":false,"in":"query","description":"pending|sent|placed|failed|timed_out|cancelled","schema":{"type":"string"}},{"name":"since","required":false,"in":"query","description":"ISO startedAt lower bound","schema":{"type":"string"}},{"name":"until","required":false,"in":"query","description":"ISO startedAt upper bound","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"capped at 200","schema":{"example":50,"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"example":0,"type":"number"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List probe history with filters (raw audit-style log)","tags":["Deliverability"],"x-required-scope":["deliverability:read"]}},"/api/deliverability/block-rules":{"post":{"operationId":"DeliverabilityController_createManualBlockRule","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateManualBlockRuleDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a manual block rule (defaults to category=should_not_send, reason=manual)","tags":["Deliverability"],"x-required-scope":["deliverability:write"]},"get":{"operationId":"DeliverabilityController_listBlockRules","parameters":[{"name":"relayAccountId","required":false,"in":"query","schema":{"type":"string"}},{"name":"provider","required":false,"in":"query","schema":{"type":"string"}},{"name":"category","required":false,"in":"query","schema":{"enum":["cannot_deliver","should_not_send","marginal"],"type":"string"}},{"name":"includeExpired","required":false,"in":"query","description":"#701: include rules whose TTL has already run out (each row carries `active`)","schema":{"type":"boolean"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List block rules for the tenant — active only by default; includeExpired=true adds expired ones, flagged with active:false","tags":["Deliverability"],"x-required-scope":["deliverability:read"]}},"/api/deliverability/block-rules/{id}":{"delete":{"operationId":"DeliverabilityController_deleteBlockRule","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"campaignId","required":false,"in":"query","description":"#509: attribute the unblock in this campaign's feed","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a block rule (manual unblock) — narrower scope required","tags":["Deliverability"]}},"/api/deliverability/tuned-variants":{"get":{"operationId":"DeliverabilityController_listTunedVariants","parameters":[{"name":"creativeId","required":false,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List Layer-3 tuned creative variants (optionally filtered by parent creativeId)","tags":["Deliverability"],"x-required-scope":["deliverability:read"]}},"/api/email-accounts/{id}/deliverability":{"get":{"operationId":"EmailAccountDeliverabilityController_getAccountSnapshot","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Embedded deliverability snapshot for this email account (providers × {baseline, creative, blocked})","tags":["Email Accounts — Deliverability"]}},"/api/email-accounts/{id}/deliverability/probe":{"post":{"operationId":"EmailAccountDeliverabilityController_probeAccount","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"summary":"\"Probe now\" — convenience C1 trigger scoped to this account","tags":["Email Accounts — Deliverability"]}},"/api/email-accounts/{id}/deliverability/block-rules/{provider}":{"delete":{"operationId":"EmailAccountDeliverabilityController_unblockProvider","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"campaignId","required":false,"in":"query","description":"#509: attribute the unblock in this campaign's feed","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Unblock a (this account × provider) block rule — narrower scope required","tags":["Email Accounts — Deliverability"]}},"/api/share-links":{"post":{"operationId":"ShareLinksController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a share link for an entity","tags":["Share Links"]},"get":{"operationId":"ShareLinksController_findByEntity","parameters":[{"name":"entityType","required":true,"in":"query","schema":{"type":"string"}},{"name":"entityId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List share links for an entity","tags":["Share Links"]}},"/api/share-links/{id}":{"delete":{"operationId":"ShareLinksController_revoke","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Revoke a share link","tags":["Share Links"]}},"/api/exports/columns":{"get":{"operationId":"ExportsController_getColumns","parameters":[{"name":"entity","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List exportable columns and groups for an entity","tags":["Exports"],"x-required-scope":["exports:read"]}},"/api/exports":{"post":{"operationId":"ExportsController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateExportDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create an export job","tags":["Exports"]},"get":{"operationId":"ExportsController_list","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List my export jobs","tags":["Exports"]}},"/api/exports/{id}":{"get":{"operationId":"ExportsController_status","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the status of an export job","tags":["Exports"]}},"/api/exports/{id}/download":{"get":{"operationId":"ExportsController_download","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download a completed export file","tags":["Exports"]}},"/api/support/thread":{"get":{"operationId":"SupportController_getThread","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get own support thread with message history","tags":["Support"],"x-required-scope":["support:read"]}},"/api/support/unread-count":{"get":{"operationId":"SupportController_unreadCount","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Unread support messages badge count","tags":["Support"],"x-required-scope":["support:read"]}},"/api/support/messages":{"post":{"operationId":"SupportController_sendMessage","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"body":{"type":"string"},"files":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Send a message to support (optional JPG/PNG attachments)","tags":["Support"],"x-required-scope":["support:write"]}},"/api/support/attachments/{id}":{"get":{"operationId":"SupportController_serveAttachment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Serve a support attachment (thread owner or SUPER only)","tags":["Support"]}},"/api/support/read":{"post":{"operationId":"SupportController_markRead","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Mark support replies as read","tags":["Support"],"x-required-scope":["support:write"]}},"/api/support/status":{"post":{"operationId":"SupportController_setStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Close or reopen own support ticket","tags":["Support"],"x-required-scope":["support:write"]}},"/api/admin/support/threads":{"get":{"operationId":"SupportAdminController_listThreads","parameters":[{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all support threads","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/support/unread-count":{"get":{"operationId":"SupportAdminController_unreadCount","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Total unread user messages across threads","tags":["Admin"],"x-required-scope":["admin:read"]}},"/api/admin/support/threads/{id}":{"get":{"operationId":"SupportAdminController_getThread","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a support thread with messages (marks as read)","tags":["Admin"]}},"/api/admin/support/threads/{id}/reply":{"post":{"operationId":"SupportAdminController_reply","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"body":{"type":"string"},"files":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Reply to a support thread (optional JPG/PNG attachments)","tags":["Admin"]}},"/api/admin/support/threads/{id}/status":{"post":{"operationId":"SupportAdminController_setStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Close or reopen a support thread","tags":["Admin"]}},"/api/a2a":{"post":{"operationId":"A2AController_dispatch","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"description":"Single JSON-RPC 2.0 request. A JSON array of requests (batch, §6) is also accepted at runtime — documented shape here is the single-request form.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/A2ABodyDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"A2A JSON-RPC 2.0 dispatch (single or batch, supports SSE for streaming methods)","tags":["A2A"]}},"/api/admin/api-monitor":{"get":{"operationId":"ApiMonitorController_list","parameters":[{"name":"since","required":true,"in":"query","schema":{"type":"string"}},{"name":"until","required":true,"in":"query","schema":{"type":"string"}},{"name":"authMode","required":true,"in":"query","schema":{"type":"string"}},{"name":"statusClass","required":true,"in":"query","schema":{"type":"string"}},{"name":"path","required":true,"in":"query","schema":{"type":"string"}},{"name":"keyPrefix","required":true,"in":"query","schema":{"type":"string"}},{"name":"userId","required":true,"in":"query","schema":{"type":"string"}},{"name":"tenantId","required":true,"in":"query","schema":{"type":"string"}},{"name":"mcpToolName","required":true,"in":"query","schema":{"type":"string"}},{"name":"a2aMethod","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List API request log entries with filters (SUPER only)","tags":["Observability / API Monitor"]}},"/api/admin/api-monitor/aggregates":{"get":{"operationId":"ApiMonitorController_aggregates","parameters":[{"name":"since","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregated API monitor metrics (RPS, latency percentiles, top paths)","tags":["Observability / API Monitor"],"x-required-scope":["admin:read"]}},"/api/admin/api-monitor/mcp/tools":{"get":{"operationId":"ApiMonitorController_mcpTools","parameters":[{"name":"since","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"MCP tools usage breakdown — per-tool counts, latency p95, error rate. SUPER only. Used by the MCP tab on the admin API monitor page.","tags":["Observability / API Monitor"],"x-required-scope":["admin:read"]}},"/api/admin/api-monitor/mcp/keys":{"get":{"operationId":"ApiMonitorController_mcpKeys","parameters":[{"name":"since","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Per-bearer-key usage — count, error rate, top-3 tools per key. SUPER only.","tags":["Observability / API Monitor"],"x-required-scope":["admin:read"]}},"/api/admin/api-monitor/mcp/timeseries":{"get":{"operationId":"ApiMonitorController_mcpTimeseries","parameters":[{"name":"since","required":true,"in":"query","schema":{"type":"string"}},{"name":"bucketMinutes","required":true,"in":"query","schema":{"type":"string"}},{"name":"toolName","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"MCP requests time series bucketed by N minutes (default 60). Optional toolName filter for per-tool charts.","tags":["Observability / API Monitor"],"x-required-scope":["admin:read"]}},"/api/me/api-monitor/calls":{"get":{"operationId":"ApiMonitorSelfController_calls","parameters":[{"name":"since","required":true,"in":"query","schema":{"type":"string"}},{"name":"until","required":true,"in":"query","schema":{"type":"string"}},{"name":"statusClass","required":true,"in":"query","schema":{"type":"string"}},{"name":"mcpToolName","required":true,"in":"query","schema":{"type":"string"}},{"name":"path","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"includeInternal","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Read your own API/MCP call journal — time, MCP tool name, method, path, HTTP status, duration, error, resourceId (object a create call produced), costUsd (mirrors _billing.cost) and correlationId. Scoped to your own tenant; foreign tenantId cannot be requested. #1212: the SDK's own /api-keys/whoami preflight before every tool call is hidden by default — pass includeInternal=true to see it.","tags":["Observability / API Monitor"],"x-required-scope":["agent:read"]}},"/api/admin/api-tests/catalog":{"get":{"operationId":"ApiTestsController_catalog","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List the catalog of synthetic API test suites","tags":["Observability / API Tests"],"x-required-scope":["admin:read"]}},"/api/admin/api-tests/run":{"post":{"operationId":"ApiTestsController_run","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run a synthetic API test suite (SUPER only)","tags":["Observability / API Tests"],"x-required-scope":["admin:write"]}},"/api/admin/api-tests/runs":{"get":{"operationId":"ApiTestsController_list","parameters":[{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"suiteId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List recent synthetic API test runs","tags":["Observability / API Tests"],"x-required-scope":["admin:read"]}},"/api/admin/api-tests/runs/{id}":{"get":{"operationId":"ApiTestsController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get details of a single synthetic API test run","tags":["Observability / API Tests"]}},"/api/allowlist":{"get":{"operationId":"AllowlistController_list","parameters":[{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List allowlist entries with optional type/search filters","tags":["Allowlist"]},"post":{"operationId":"AllowlistController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create an allowlist entry (email or domain)","tags":["Allowlist"]}},"/api/allowlist/check":{"get":{"operationId":"AllowlistController_check","parameters":[{"name":"email","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check whether an email/domain is allowlisted","tags":["Allowlist"],"x-required-scope":["suppression:read"]}},"/api/allowlist/bulk":{"post":{"operationId":"AllowlistController_bulkCreate","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Bulk-create allowlist entries (up to 1000)","tags":["Allowlist"],"x-required-scope":["suppression:write"]}},"/api/allowlist/{id}":{"delete":{"operationId":"AllowlistController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an allowlist entry by id","tags":["Allowlist"]}},"/api/sequences":{"get":{"operationId":"SequencesController_list","parameters":[{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List email sequences","tags":["Sequences"]},"post":{"operationId":"SequencesController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create an email sequence","tags":["Sequences"]}},"/api/sequences/{id}":{"get":{"operationId":"SequencesController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a sequence by id","tags":["Sequences"]},"patch":{"operationId":"SequencesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a sequence","tags":["Sequences"]},"delete":{"operationId":"SequencesController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a sequence","tags":["Sequences"]}},"/api/sequences/{id}/steps":{"post":{"operationId":"SequencesController_addStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add a step to a sequence","tags":["Sequences"]}},"/api/sequences/{id}/steps/{stepId}":{"patch":{"operationId":"SequencesController_updateStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a sequence step","tags":["Sequences"]},"delete":{"operationId":"SequencesController_deleteStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a sequence step","tags":["Sequences"]}},"/api/sequences/{id}/steps/{stepId}/variants":{"get":{"operationId":"SequencesController_listVariants","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List A/B variants on a step","tags":["Sequences"]},"post":{"operationId":"SequencesController_addVariant","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Add an A/B variant to a step","tags":["Sequences"]}},"/api/sequences/{id}/steps/{stepId}/variants/{variantId}":{"patch":{"operationId":"SequencesController_updateVariant","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"variantId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an A/B variant","tags":["Sequences"]},"delete":{"operationId":"SequencesController_deleteVariant","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"variantId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an A/B variant","tags":["Sequences"]}},"/api/sequences/{id}/steps/{stepId}/variants/stats":{"get":{"operationId":"SequencesController_variantStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get A/B variant statistics for a step","tags":["Sequences"]}},"/api/sequences/{id}/enroll":{"post":{"operationId":"SequencesController_enroll","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Enroll contacts into a sequence","tags":["Sequences"]}},"/api/sequences/{id}/enrollments":{"get":{"operationId":"SequencesController_listEnrollments","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List enrollments for a sequence","tags":["Sequences"]}},"/api/sequences/enrollments/{eid}/pause":{"post":{"operationId":"SequencesController_pauseEnrollment","parameters":[{"name":"eid","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Pause an enrollment","tags":["Sequences"]}},"/api/sequences/enrollments/{eid}/resume":{"post":{"operationId":"SequencesController_resumeEnrollment","parameters":[{"name":"eid","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Resume an enrollment","tags":["Sequences"]}},"/api/sequences/enrollments/{eid}/cancel":{"post":{"operationId":"SequencesController_cancelEnrollment","parameters":[{"name":"eid","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel an enrollment","tags":["Sequences"]}},"/api/agency":{"get":{"operationId":"AgencyController_list","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List agency sub-accounts and parent tenant metadata","tags":["Agency"]},"post":{"operationId":"AgencyController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new sub-account tenant under the caller","tags":["Agency"]}},"/api/agency/stats":{"get":{"operationId":"AgencyController_stats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Aggregate stats per sub-account child","tags":["Agency"],"x-required-scope":["admin:read"]}},"/api/agency/{childId}":{"delete":{"operationId":"AgencyController_detach","parameters":[{"name":"childId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Detach (un-parent) a sub-account from the agency","tags":["Agency"]}},"/api/audit-events":{"get":{"operationId":"AuditController_list","parameters":[{"name":"action","required":true,"in":"query","schema":{"type":"string"}},{"name":"actorId","required":true,"in":"query","schema":{"type":"string"}},{"name":"targetType","required":true,"in":"query","schema":{"type":"string"}},{"name":"targetId","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List audit events with filters (action, actor, target, date range)","tags":["Audit"]},"post":{"operationId":"AuditController_manualWrite","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Manually write an audit event (used by agents to attribute their actions)","tags":["Audit"]}},"/api/audit-events/aggregates":{"get":{"operationId":"AuditController_aggregates","parameters":[{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregate audit-event counts over a date range","tags":["Audit"],"x-required-scope":["admin:read"]}},"/api/branding":{"get":{"operationId":"BrandingController_get","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get resolved white-label branding for the caller tenant (defaults merged)","tags":["Branding"]},"patch":{"operationId":"BrandingController_update","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Partially update tenant white-label branding","tags":["Branding"]},"delete":{"operationId":"BrandingController_reset","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset tenant white-label branding back to defaults","tags":["Branding"]}},"/api/cohort-metrics/funnel":{"get":{"operationId":"CohortMetricsController_funnel","parameters":[{"name":"sequenceId","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get sequence funnel metrics for a date range","tags":["Cohort Metrics"],"x-required-scope":["mailing:read"]}},"/api/cohort-metrics/latency":{"get":{"operationId":"CohortMetricsController_latency","parameters":[{"name":"sequenceId","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get reply latency metrics for a sequence/date range","tags":["Cohort Metrics"],"x-required-scope":["mailing:read"]}},"/api/cohort-metrics/cohorts":{"get":{"operationId":"CohortMetricsController_cohorts","parameters":[{"name":"sequenceId","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get cohort breakdown for a sequence/date range","tags":["Cohort Metrics"],"x-required-scope":["mailing:read"]}},"/api/enrichment/company":{"post":{"operationId":"EnrichmentController_company","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Enrich a company by domain, INN or name","tags":["Enrichment"],"x-required-scope":["connectors:read"]}},"/api/enrichment/email":{"post":{"operationId":"EnrichmentController_findEmail","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Find an email address from name and domain","tags":["Enrichment"],"x-required-scope":["connectors:read"]}},"/api/domains/dns-check":{"post":{"operationId":"DomainsController_check","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run DNS health check for a single domain","tags":["Domains"],"x-required-scope":["mailing:read"]}},"/api/domains/dns-check/bulk":{"post":{"operationId":"DomainsController_bulk","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Run DNS health check for up to 20 domains","tags":["Domains"],"x-required-scope":["mailing:read"]}},"/api/prompt-templates":{"get":{"operationId":"PromptTemplatesController_list","parameters":[{"name":"kind","required":true,"in":"query","schema":{"type":"string"}},{"name":"isActive","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List prompt templates with optional filters","tags":["Prompt Templates"]},"post":{"operationId":"PromptTemplatesController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new prompt template","tags":["Prompt Templates"]}},"/api/prompt-templates/{id}":{"get":{"operationId":"PromptTemplatesController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single prompt template by id","tags":["Prompt Templates"]},"patch":{"operationId":"PromptTemplatesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a prompt template","tags":["Prompt Templates"]},"delete":{"operationId":"PromptTemplatesController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a prompt template","tags":["Prompt Templates"]}},"/api/prompt-templates/{idOrName}/render":{"post":{"operationId":"PromptTemplatesController_render","parameters":[{"name":"idOrName","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Render a prompt template (by id or name) with caller variables","tags":["Prompt Templates"]}},"/api/custom-events":{"post":{"operationId":"CustomEventsController_track","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Track a single custom event","tags":["Custom Events"]},"get":{"operationId":"CustomEventsController_list","parameters":[{"name":"eventName","required":true,"in":"query","schema":{"type":"string"}},{"name":"entityType","required":true,"in":"query","schema":{"type":"string"}},{"name":"entityId","required":true,"in":"query","schema":{"type":"string"}},{"name":"source","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List custom events with filters and pagination","tags":["Custom Events"]}},"/api/custom-events/bulk":{"post":{"operationId":"CustomEventsController_bulkTrack","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Track up to 500 custom events in one request","tags":["Custom Events"],"x-required-scope":["events:write"]}},"/api/custom-events/aggregates":{"get":{"operationId":"CustomEventsController_aggregates","parameters":[{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregated custom event counts by date range","tags":["Custom Events"],"x-required-scope":["events:read"]}},"/api/custom-objects/defs":{"get":{"operationId":"CustomObjectsController_listDefs","parameters":[{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"isActive","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List custom object definitions","tags":["Custom Objects"],"x-required-scope":["crm:read"]},"post":{"operationId":"CustomObjectsController_createDef","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a custom object definition","tags":["Custom Objects"],"x-required-scope":["crm:write"]}},"/api/custom-objects/defs/{slug}":{"get":{"operationId":"CustomObjectsController_getDef","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a custom object definition by slug","tags":["Custom Objects"]},"patch":{"operationId":"CustomObjectsController_updateDef","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a custom object definition","tags":["Custom Objects"]},"delete":{"operationId":"CustomObjectsController_deleteDef","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a custom object definition","tags":["Custom Objects"]}},"/api/custom-objects/{slug}/records":{"get":{"operationId":"CustomObjectsController_listRecords","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List records of a custom object","tags":["Custom Objects"]},"post":{"operationId":"CustomObjectsController_createRecord","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a record of a custom object","tags":["Custom Objects"]}},"/api/custom-objects/{slug}/records/{id}":{"get":{"operationId":"CustomObjectsController_getRecord","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a custom object record by id or externalId","tags":["Custom Objects"]},"patch":{"operationId":"CustomObjectsController_updateRecord","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a custom object record","tags":["Custom Objects"]},"delete":{"operationId":"CustomObjectsController_deleteRecord","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a custom object record","tags":["Custom Objects"]}},"/api/icp-tasks":{"get":{"operationId":"IcpExtensionController_findAll","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List ICP tasks with pagination and status filter","tags":["ICP Extension"]},"post":{"operationId":"IcpExtensionController_create","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIcpTaskDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new ICP task","tags":["ICP Extension"]}},"/api/icp-tasks/companies/scrape/preview":{"get":{"operationId":"IcpExtensionController_scrapePreview","parameters":[{"name":"listId","required":true,"in":"query","schema":{"type":"string"}},{"name":"domainField","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#955 preview list coverage WITHOUT starting a crawl: how many cards, how many have the domain field filled, how many unique domains among them (alias of .../preview on the canonical site-enrichment)","tags":["ICP Extension"],"x-required-scope":["icp:read"]}},"/api/icp-tasks/companies/scrape/{taskId}":{"get":{"operationId":"IcpExtensionController_getScrapeStatus","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"includeResults","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#835 status and progress of a site-crawl task. #957 (fix): includeResults=false removes the results field from the response — on large tasks (thousands of cards) the full result list stops fitting in the response and gets in the way of working with the task via MCP; by default results is returned (the old contract), an explicit includeResults=false returns only aggregates (total/processed/ok/down/noSite). To page through the results themselves — GET .../companies/scrape/:taskId/items or the canonical .../site-enrichment/tasks/:id/items. #957 (continued): the response NOW carries a stats key — the same enriched statistics byte-for-byte as the canonical GET .../site-enrichment/tasks/:id/stats (cards AND domains funnel counted separately, breakdown of collected data by field, pace/forecast, launch parameters echoed back — listId/listName/domainField/visitPages/timeoutMs/maxAttempts/mode/surface/startedBy, direct links to the scoring-task card and this same task's journal); this is a legacy route (ldm_icp_scrape_status) that remains available. The canonical ldm_site_enrichment_tasks_* tools exist in the client catalog but may return 403 insufficient_scope. The legacy alias stays available for clients that lack scope for the new tools.","tags":["ICP Extension"]}},"/api/icp-tasks/companies/scrape/{taskId}/cancel":{"post":{"operationId":"IcpExtensionController_cancelScrape","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#835 cancel a site-crawl task","tags":["ICP Extension"]}},"/api/icp-tasks/{id}":{"get":{"operationId":"IcpExtensionController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get an ICP task by id","tags":["ICP Extension"]},"patch":{"operationId":"IcpExtensionController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIcpTaskDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update an ICP task","tags":["ICP Extension"]},"delete":{"operationId":"IcpExtensionController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete an ICP task","tags":["ICP Extension"]}},"/api/icp-tasks/{id}/scoring-prompt":{"get":{"operationId":"IcpExtensionController_scoringPromptPreview","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Preview the ACTUAL scoring prompt for this task (brief-driven / custom / default)","tags":["ICP Extension"]}},"/api/icp-tasks/companies/scrape":{"post":{"operationId":"IcpExtensionController_scrapeCompanies","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeCompaniesDto"}}}},"responses":{"202":{"description":""}},"security":[{"jwt":[]}],"summary":"#298/#835 server-side crawl fetcher: enqueued in the background, the response is a taskId immediately. Input is companyIds OR listId (#955, the whole list with no 500-item cap on the request body — SiteEnrichmentService resolves it in full); with an explicit limit, the first limit are taken into work (defaults to 50 for companyIds input), how many were actually enqueued is visible in the queued field.","tags":["ICP Extension"],"x-required-scope":["icp:write"]}},"/api/icp-tasks/companies/scrape/{taskId}/pause":{"post":{"operationId":"IcpExtensionController_pauseScrape","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#952 pause a crawl task (alias of .../pause on the canonical site-enrichment)","tags":["ICP Extension"]}},"/api/icp-tasks/companies/scrape/{taskId}/resume":{"post":{"operationId":"IcpExtensionController_resumeScrape","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"#952 resume a paused crawl task (alias of .../resume on the canonical site-enrichment)","tags":["ICP Extension"]}},"/api/icp-tasks/companies/scrape/{taskId}/items":{"get":{"operationId":"IcpExtensionController_scrapeItems","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"reasonCode","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#952 crawl task items with a filter by outcome/reason code (alias of .../items on the canonical site-enrichment)","tags":["ICP Extension"]}},"/api/icp-tasks/{id}/regenerate-key":{"post":{"operationId":"IcpExtensionController_regenerateKey","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Regenerate the project key for an ICP task","tags":["ICP Extension"]}},"/api/icp-tasks/{id}/statistics":{"get":{"operationId":"IcpExtensionController_getStatistics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get statistics for an ICP task","tags":["ICP Extension"]}},"/api/icp-tasks/{id}/items":{"get":{"operationId":"IcpExtensionController_getItems","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"module","required":true,"in":"query","schema":{"type":"string"}},{"name":"sortBy","required":true,"in":"query","schema":{"type":"string"}},{"name":"sortDir","required":true,"in":"query","schema":{"type":"string"}},{"name":"q","required":true,"in":"query","schema":{"type":"string"}},{"name":"companyId","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateFrom","required":true,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List items belonging to an ICP task","tags":["ICP Extension"]}},"/api/icp-tasks/{id}/download-extension":{"get":{"operationId":"IcpExtensionController_downloadExtension","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"lang","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download a pre-built Chrome extension zip for an ICP task","tags":["ICP Extension"]}},"/api/ext/auth":{"get":{"operationId":"IcpExtApiController_authorize","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Authorize the Chrome extension by project key","tags":["ICP Extension / API"]}},"/api/ext/icpreview/next":{"get":{"operationId":"IcpExtApiController_getNextItem","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the next ICP review item for the extension","tags":["ICP Extension / API"]}},"/api/ext/icpreview/ai":{"post":{"operationId":"IcpExtApiController_analyzeAi","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Analyze an ICP review item with AI","tags":["ICP Extension / API"]}},"/api/ext/icpreview/enrich":{"post":{"operationId":"IcpExtApiController_enrich","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Auto-enrich the company card from the visited site (#281 item 7)","tags":["ICP Extension / API"]}},"/api/ext/icpreview/complete":{"post":{"operationId":"IcpExtApiController_complete","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Mark an ICP review item as completed","tags":["ICP Extension / API"]}},"/api/ext/formassist/config":{"get":{"operationId":"IcpExtApiController_getFormAssistConfig","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get form assist configuration for the extension","tags":["ICP Extension / API"]}},"/api/ext/company/lookup":{"get":{"operationId":"IcpExtApiController_lookupCompany","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"host","required":true,"in":"query","schema":{"type":"string"}},{"name":"task_item_id","required":true,"in":"query","schema":{"type":"string"}},{"name":"company_id","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Lookup CRM company by site host (widget company card)","tags":["ICP Extension / API"]}},"/api/ext/formassist/profile":{"get":{"operationId":"IcpExtApiController_getFormAssistProfile","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Resolved profile values for manual form fill (context menu)","tags":["ICP Extension / API"]}},"/api/ext/formassist/ai":{"post":{"operationId":"IcpExtApiController_formAssistAi","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Run AI form-fill suggestion for the extension","tags":["ICP Extension / API"]}},"/api/ext/formassist/complete":{"post":{"operationId":"IcpExtApiController_formAssistComplete","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Report form-assist completion from the extension","tags":["ICP Extension / API"]}},"/api/ext/sendemail/stats":{"get":{"operationId":"IcpExtApiController_getSendEmailStats","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get send-email stats for the extension","tags":["ICP Extension / API"]}},"/api/ext/sendemail/capture":{"post":{"operationId":"IcpExtApiController_captureEmail","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Capture an email address from the extension","tags":["ICP Extension / API"]}},"/api/ext/messenger/generate":{"post":{"operationId":"IcpExtApiController_generateMessage","parameters":[{"name":"channel","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate a messenger message (channel = vk|telegram|whatsapp|linkedin)","tags":["ICP Extension / API"]}},"/api/ext/messenger/complete":{"post":{"operationId":"IcpExtApiController_messengerComplete","parameters":[{"name":"channel","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Report messenger send completion (creates/links a Contact by url)","tags":["ICP Extension / API"]}},"/api/ext/presentation":{"post":{"operationId":"IcpExtApiController_presentation","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Generate a presentation PDF (mode = attach → base64 | link → OG url)","tags":["ICP Extension / API"]}},"/api/ext/presentation/pdf/{filename}":{"get":{"operationId":"IcpExtApiController_presentationPdf","parameters":[{"name":"filename","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Serve a presentation PDF by filename (no key, public link)","tags":["ICP Extension / API"]}},"/api/ext/presentation/{token}":{"get":{"operationId":"IcpExtApiController_presentationOg","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Public OG preview page for a presentation link (no key)","tags":["ICP Extension / API"]}},"/api/custom-extract":{"post":{"operationId":"CustomExtractController_run","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomExtractRequestDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#972 custom extraction over ALREADY supplied material: a word/word list (KEYWORD), a regular expression (REGEX, via compileSafeRegex — the same barrier as inbound-rules), or an AI prompt (PROMPT, a custom prompt can be supplied via promptOverride). The response distinguishes three outcomes: found / not_found / cannot_search (no material, broken rule, AI unavailable, no funds, tenant queue full) — see reason. KEYWORD/REGEX return immediately (200, mode=sync); PROMPT is enqueued (202, mode=queued, jobId) — AI balance and the tenant pending-task limit are checked BEFORE enqueueing.","tags":["Custom Extract"]}},"/api/custom-extract/{jobId}":{"get":{"operationId":"CustomExtractController_getStatus","parameters":[{"name":"jobId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"#972 status/result of a PROMPT custom-extraction job enqueued by the POST above. The job is checked for ownership by the CURRENT tenant (the job carries the tenantId from enqueueing) — a foreign jobId is indistinguishable from a nonexistent one (status=unknown), the job number does not leak foreign data (pipeline gate per MR !1195: the same defect class as incident_tenant_isolation_idor).","tags":["Custom Extract"]}},"/api/ext/linkedin/session":{"post":{"operationId":"LinkedinExtApiController_session","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Upload/update a session (cookies from an authorized browser)","tags":["LinkedIn / Extension API"]}},"/api/ext/linkedin/next":{"get":{"operationId":"LinkedinExtApiController_next","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"accountId","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Claim the next due action (atomically). Empty → 204","tags":["LinkedIn / Extension API"]}},"/api/ext/linkedin/report":{"post":{"operationId":"LinkedinExtApiController_report","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Report on an action execution","tags":["LinkedIn / Extension API"]}},"/api/ext/linkedin/events":{"post":{"operationId":"LinkedinExtApiController_events","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Widget events (accept/reply/warning/challenge)","tags":["LinkedIn / Extension API"]}},"/api/ext/linkedin/config":{"get":{"operationId":"LinkedinExtApiController_config","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Client config: toggles + guard-rails","tags":["LinkedIn / Extension API"]}},"/api/ext/linkedin/heartbeat":{"post":{"operationId":"LinkedinExtApiController_heartbeat","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"summary":"Widget heartbeat (+optionally fresh cookies)","tags":["LinkedIn / Extension API"]}},"/api/linkedin/integration":{"get":{"operationId":"LinkedinController_getIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"LinkedIn integration status (toggle, defaults)","tags":["LinkedIn"],"x-required-scope":["linkedin:read"]},"patch":{"operationId":"LinkedinController_updateIntegration","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Enable/disable the module, kill-switch, defaults","tags":["LinkedIn"],"x-required-scope":["linkedin:write"]}},"/api/linkedin/accounts":{"get":{"operationId":"LinkedinController_listAccounts","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List of LinkedIn accounts (without cookies)","tags":["LinkedIn"],"x-required-scope":["linkedin:read"]}},"/api/linkedin/accounts/{id}":{"get":{"operationId":"LinkedinController_getAccount","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Account by id (without cookies)","tags":["LinkedIn"]},"patch":{"operationId":"LinkedinController_patchAccount","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Change account limits/windows/pause","tags":["LinkedIn"]}},"/api/linkedin/accounts/{id}/disconnect":{"post":{"operationId":"LinkedinController_disconnect","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Revoke session (erase cookies)","tags":["LinkedIn"]}},"/api/linkedin/campaigns":{"get":{"operationId":"LinkedinController_listCampaigns","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List of campaigns","tags":["LinkedIn"],"x-required-scope":["linkedin:read"]},"post":{"operationId":"LinkedinController_createCampaign","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a campaign","tags":["LinkedIn"],"x-required-scope":["linkedin:write"]}},"/api/linkedin/campaigns/{id}":{"patch":{"operationId":"LinkedinController_patchCampaign","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Change campaign (name/status/scenario)","tags":["LinkedIn"]}},"/api/linkedin/campaigns/{id}/leads":{"post":{"operationId":"LinkedinController_pourLeads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Pour leads into a campaign","tags":["LinkedIn"]}},"/api/linkedin/scenarios":{"get":{"operationId":"LinkedinController_listScenarios","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List of scenarios","tags":["LinkedIn"],"x-required-scope":["linkedin:read"]},"post":{"operationId":"LinkedinController_createScenario","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a scenario","tags":["LinkedIn"],"x-required-scope":["linkedin:write"]}},"/api/linkedin/stats":{"get":{"operationId":"LinkedinController_stats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Dashboard: funnel + acceptance/reply-rate","tags":["LinkedIn"],"x-required-scope":["linkedin:read"]}},"/api/phantom-browser/profiles":{"get":{"operationId":"PhantomBrowserController_listProfiles","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List all Phantom browser profiles","tags":["Phantom Browser"],"x-required-scope":["admin:read"]},"post":{"operationId":"PhantomBrowserController_createProfile","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new Phantom browser profile","tags":["Phantom Browser"],"x-required-scope":["admin:write"]}},"/api/phantom-browser/profiles/sync":{"post":{"operationId":"PhantomBrowserController_syncProfiles","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Re-send the profiles list to the connected Phantom client","tags":["Phantom Browser"],"x-required-scope":["admin:write"]}},"/api/phantom-browser/profiles/{id}":{"get":{"operationId":"PhantomBrowserController_getProfile","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single Phantom browser profile by id","tags":["Phantom Browser"]},"put":{"operationId":"PhantomBrowserController_updateProfile","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a Phantom browser profile","tags":["Phantom Browser"]},"delete":{"operationId":"PhantomBrowserController_deleteProfile","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a Phantom browser profile","tags":["Phantom Browser"]}},"/api/phantom-browser/client/status":{"get":{"operationId":"PhantomBrowserController_getClientStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the Phantom desktop client connection status","tags":["Phantom Browser"],"x-required-scope":["admin:read"]}},"/api/phantom-browser/client/token/regenerate":{"post":{"operationId":"PhantomBrowserController_regenerateToken","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Regenerate the Phantom client auth token","tags":["Phantom Browser"],"x-required-scope":["admin:write"]}},"/api/phantom-browser/profiles/{id}/launch":{"post":{"operationId":"PhantomBrowserController_launchProfile","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Launch a profile on the user's Phantom desktop client","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/stop":{"post":{"operationId":"PhantomBrowserController_stopProfile","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Stop a running profile on the Phantom desktop client","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/navigate":{"post":{"operationId":"PhantomBrowserController_navigate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Navigate the Phantom browser profile to a URL","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/screenshot":{"post":{"operationId":"PhantomBrowserController_screenshot","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Take a screenshot in the Phantom browser profile (base64 JPEG)","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/screenshot.jpg":{"get":{"operationId":"PhantomBrowserController_screenshotImage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the latest Phantom browser screenshot as a JPEG image","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/html":{"get":{"operationId":"PhantomBrowserController_getHtml","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the current Phantom browser page's HTML","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/page-info":{"get":{"operationId":"PhantomBrowserController_getPageInfo","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the current Phantom browser page URL and title","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/execute":{"post":{"operationId":"PhantomBrowserController_executeJs","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Execute JavaScript in the Phantom browser page context","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/click":{"post":{"operationId":"PhantomBrowserController_click","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Click an element in the Phantom browser by CSS selector","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/type":{"post":{"operationId":"PhantomBrowserController_typeText","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Type text into a focused element or selector in the Phantom browser","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/cookies":{"get":{"operationId":"PhantomBrowserController_getCookies","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get cookies for the current Phantom browser page","tags":["Phantom Browser"]},"post":{"operationId":"PhantomBrowserController_setCookies","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Set cookies on the current Phantom browser page — lets the worker browse a site already logged-in. Accepts the Cookie-Editor / EditThisCookie export format directly (or the plain CDP shape); the server normalizes it (expirationDate→expires, sameSite no_restriction→None, drops hostOnly/session/storeId). Example body: { \"cookies\": [ { \"domain\": \".linkedin.com\", \"name\": \"li_at\", \"value\": \"AQ...\", \"path\": \"/\", \"expirationDate\": 1814817974.7, \"secure\": true, \"httpOnly\": true, \"sameSite\": \"no_restriction\" } ] }","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/scroll":{"post":{"operationId":"PhantomBrowserController_scroll","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Scroll the current Phantom browser page","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/wait":{"post":{"operationId":"PhantomBrowserController_waitFor","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Wait for a selector to appear in the Phantom browser page","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/solve-captcha":{"post":{"operationId":"PhantomBrowserController_solveCaptcha","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Solve a captcha on the current Phantom browser page (via RuCaptcha)","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/proxy":{"put":{"operationId":"PhantomBrowserController_setProxy","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Set the proxy configuration on a Phantom browser profile","tags":["Phantom Browser"]},"delete":{"operationId":"PhantomBrowserController_removeProxy","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Remove the proxy configuration from a Phantom browser profile","tags":["Phantom Browser"]}},"/api/phantom-browser/profiles/{id}/proxy/test":{"post":{"operationId":"PhantomBrowserController_testProxy","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Test a Phantom browser profile proxy (launch and report IP)","tags":["Phantom Browser"]}},"/api/phantom-browser/launches":{"get":{"operationId":"PhantomBrowserController_listLaunches","parameters":[{"name":"profileId","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List Phantom browser profile launches","tags":["Phantom Browser"],"x-required-scope":["admin:read"]}},"/api/phantom-browser/scenarios":{"get":{"operationId":"PhantomBrowserController_listScenarios","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List Phantom browser scenarios","tags":["Phantom Browser"],"x-required-scope":["admin:read"]},"post":{"operationId":"PhantomBrowserController_createScenario","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new Phantom browser scenario","tags":["Phantom Browser"],"x-required-scope":["admin:write"]}},"/api/phantom-browser/scenarios/{id}":{"get":{"operationId":"PhantomBrowserController_getScenario","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single Phantom browser scenario by id","tags":["Phantom Browser"]},"put":{"operationId":"PhantomBrowserController_updateScenario","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a Phantom browser scenario","tags":["Phantom Browser"]},"delete":{"operationId":"PhantomBrowserController_deleteScenario","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a Phantom browser scenario","tags":["Phantom Browser"]}},"/api/phantom-browser/schedules":{"get":{"operationId":"PhantomBrowserController_listSchedules","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List Phantom browser schedules","tags":["Phantom Browser"],"x-required-scope":["admin:read"]},"post":{"operationId":"PhantomBrowserController_createSchedule","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new Phantom browser schedule","tags":["Phantom Browser"],"x-required-scope":["admin:write"]}},"/api/phantom-browser/schedules/{id}":{"put":{"operationId":"PhantomBrowserController_updateSchedule","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Update a Phantom browser schedule","tags":["Phantom Browser"]},"delete":{"operationId":"PhantomBrowserController_deleteSchedule","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Delete a Phantom browser schedule","tags":["Phantom Browser"]}},"/api/phantom-browser/admin/stats":{"get":{"operationId":"PhantomBrowserController_getAdminStats","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get Phantom browser admin stats (SUPER only)","tags":["Phantom Browser"],"x-required-scope":["admin:read"]}},"/api/phantom-browser/download/config":{"get":{"operationId":"PhantomBrowserController_downloadConfig","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download the Phantom desktop client config.json with the user's token","tags":["Phantom Browser"],"x-required-scope":["admin:read"]}},"/api/phantom-browser/sync":{"post":{"operationId":"PhantomBrowserDownloadController_syncByToken","parameters":[{"name":"x-phantom-token","required":true,"in":"header","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Sync Phantom desktop client profiles using its token","tags":["Phantom Browser / Download"]}},"/api/phantom-browser/update/check":{"get":{"operationId":"PhantomBrowserDownloadController_updateCheck","parameters":[{"name":"version","required":true,"in":"query","schema":{"type":"string"}},{"name":"hash","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Check for available Phantom client updates","tags":["Phantom Browser / Download"]}},"/api/phantom-browser/update/bundle":{"get":{"operationId":"PhantomBrowserDownloadController_updateBundle","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download the Phantom client update bundle (gzipped source files)","tags":["Phantom Browser / Download"]}},"/api/phantom-browser/download/{platform}":{"get":{"operationId":"PhantomBrowserDownloadController_download","parameters":[{"name":"platform","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download the Phantom client binary for a given platform","tags":["Phantom Browser / Download"]}},"/api/phantom-browser/logs":{"post":{"operationId":"PhantomBrowserDownloadController_receiveLogs","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Receive logs from the Phantom desktop client","tags":["Phantom Browser / Download"]}},"/api/import/templates":{"get":{"operationId":"ImportController_getTemplates","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List available import templates","tags":["Import"],"x-required-scope":["import:read"]}},"/api/import/templates/detect":{"post":{"operationId":"ImportController_detectTemplate","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DetectTemplateDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Detect the best matching import template from CSV headers","tags":["Import"],"x-required-scope":["import:read"]}},"/api/import/templates/apply":{"post":{"operationId":"ImportController_applyTemplate","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyTemplateDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Apply an import template to CSV headers","tags":["Import"],"x-required-scope":["import:read"]}},"/api/import/tasks":{"post":{"operationId":"ImportController_createTask","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportTaskConfigDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Create a new import task","tags":["Import"],"x-required-scope":["import:write"]}},"/api/import/from-url":{"post":{"operationId":"ImportController_importFromUrl","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportFromUrlDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Import a list from a link (Google Sheets or a direct .csv/.xlsx URL) — the \"link -> file\" link, does not start the import itself (#805). Response includes suggestedMapping/unmapped (#1058): a proposed column -> field mapping (from the detected template when one matched, or a header-name heuristic otherwise) with a sample value per column, plus the columns nobody could confidently guess.","tags":["Import"],"x-required-scope":["import:write"]}},"/api/import/tasks/{id}":{"get":{"operationId":"ImportController_getTask","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get an import task by id","tags":["Import"]}},"/api/import/tasks/{id}/log":{"get":{"operationId":"ImportController_getLog","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"number"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"number"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the row-level log for an import task","tags":["Import"]}},"/api/import/tasks/{id}/log/csv":{"get":{"operationId":"ImportController_getLogCsv","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Download the import task log as CSV","tags":["Import"]}},"/api/import/tasks/{id}/cancel":{"post":{"operationId":"ImportController_cancelTask","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel an in-progress import task","tags":["Import"]}},"/api/import/tasks/{id}/rollback":{"post":{"operationId":"ImportController_rollbackTask","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Rollback the changes made by an import task","tags":["Import"]}},"/api/creative-on-demand/{creativeId}/generate":{"post":{"operationId":"OnDemandController_generate","parameters":[{"name":"creativeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateRequestDto"}}}},"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Enqueue an on-demand generation request for a creative","tags":["Creatives / On-Demand"]}},"/api/creative-on-demand/{creativeId}/requests/{requestId}":{"get":{"operationId":"OnDemandController_getRequest","parameters":[{"name":"creativeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"requestId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get a single on-demand request by id","tags":["Creatives / On-Demand"]}},"/api/creative-on-demand/{creativeId}/requests/{requestId}/cancel":{"post":{"operationId":"OnDemandController_cancel","parameters":[{"name":"creativeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"requestId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Cancel an in-flight on-demand request","tags":["Creatives / On-Demand"]}},"/api/creative-on-demand/{creativeId}/requests":{"get":{"operationId":"OnDemandController_list","parameters":[{"name":"creativeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"offset","required":true,"in":"query","schema":{"type":"string"}},{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List on-demand requests for a creative","tags":["Creatives / On-Demand"]}},"/api/creative-on-demand/{creativeId}/stats":{"get":{"operationId":"OnDemandController_stats","parameters":[{"name":"creativeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get aggregated on-demand stats for a creative","tags":["Creatives / On-Demand"]}},"/api/creative-on-demand/{creativeId}/qc-config":{"get":{"operationId":"OnDemandController_getQcConfig","parameters":[{"name":"creativeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get QC configuration for a creative","tags":["Creatives / On-Demand"]},"put":{"operationId":"OnDemandController_putQcConfig","parameters":[{"name":"creativeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QcConfigDto"}}}},"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Upsert QC configuration for a creative","tags":["Creatives / On-Demand"]},"delete":{"operationId":"OnDemandController_resetQcConfig","parameters":[{"name":"creativeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Reset QC configuration to defaults","tags":["Creatives / On-Demand"]}},"/api/utils/timezones":{"get":{"operationId":"UtilsController_listTimezones","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List IANA timezones with cities, country, offset","tags":["Utils"],"x-required-scope":["utils:read"]}},"/api/utils/timezone-lookup":{"post":{"operationId":"UtilsController_lookupTimezone","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Look up timezone by city or country","tags":["Utils"],"x-required-scope":["utils:read"]}},"/api/landing/apply":{"post":{"operationId":"LandingController_apply","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Submit a public landing-page application form","tags":["Landing"]}},"/api/jobs/{queue}/{id}":{"get":{"operationId":"JobsController_getJob","parameters":[{"name":"queue","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Get the status of any background job by queue + id (Wave 15 unified poll)","tags":["Jobs"]}},"/api/seo-index/overview":{"get":{"operationId":"SeoIndexController_overview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Summary of clicks/impressions/CTR/position over 7/28/90d with delta vs the previous period","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/segments":{"get":{"operationId":"SeoIndexController_segments","parameters":[{"name":"days","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Breakdown of metrics by site sections","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/sitemaps":{"get":{"operationId":"SeoIndexController_sitemaps","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Sitemap status: type, upload date, submitted/indexed, errors","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/pages":{"get":{"operationId":"SeoIndexController_pages","parameters":[{"name":"section","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Top pages by clicks (snapshot, filter by section, pagination)","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/queries":{"get":{"operationId":"SeoIndexController_queries","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Top search queries by clicks (snapshot, pagination)","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/history":{"get":{"operationId":"SeoIndexController_history","parameters":[{"name":"days","required":true,"in":"query","schema":{"type":"string"}},{"name":"segment","required":true,"in":"query","schema":{"type":"string"}},{"name":"property","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Daily series of clicks/impressions/ctr/position for charts","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/coverage":{"get":{"operationId":"SeoIndexController_coverage","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"URLs in the sitemap versus the number of pages with impressions","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/index-coverage":{"get":{"operationId":"SeoIndexController_indexCoverage","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Total sitemap page count per surface (landing/blog/check/email-stats); index status is unknown until URL Inspection (#770) is wired — deprecated GSC sitemap.indexed is not reported as a page count","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/yandex/overview":{"get":{"operationId":"SeoIndexController_yandexOverview","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Yandex.Webmaster: clicks/impressions/position with delta + Yandex site quality index (ICS) and pages in search per host","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/yandex/queries":{"get":{"operationId":"SeoIndexController_yandexQueries","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Yandex.Webmaster: top search queries (snapshot, pagination)","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/yandex/sitemaps":{"get":{"operationId":"SeoIndexController_yandexSitemaps","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Yandex.Webmaster: sitemaps — type, URL, errors, last crawl date","tags":["SEO Index"],"x-required-scope":["admin:read"]}},"/api/seo-index/indexnow":{"get":{"operationId":"SeoIndexController_indexNowStatus","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"IndexNow ping status: whether a key is configured, time/mode/URL count of the last ping","tags":["SEO Index"],"x-required-scope":["admin:read"]},"post":{"operationId":"SeoIndexController_indexNowForcePing","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Force IndexNow ping — pings the ENTIRE sitemap list (not just the diff from the cron run). Use after bulk sitemap edits, when waiting for the next cron tick (12h) is not an option.","tags":["SEO Index"],"x-required-scope":["admin:write"]}},"/api/profi-orders":{"get":{"operationId":"ProfiOrdersController_list","parameters":[{"name":"keyword","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Profi.ru order feed (pagination, keyword filter)","tags":["Profi Orders"]}},"/api/profi-orders/status":{"get":{"operationId":"ProfiOrdersController_status","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Monitor status: last ingest and per-keyword counters","tags":["Profi Orders"],"x-required-scope":["admin:read"]}},"/api/profi-orders/ingest":{"post":{"operationId":"ProfiOrdersController_ingest","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"201":{"description":""}},"security":[{"jwt":[]}],"summary":"Receive orders from the external Profi.ru monitor","tags":["Profi Orders"],"x-required-scope":["admin:write"]}},"/api/rum/vitals":{"post":{"operationId":"RumController_vitals","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"204":{"description":""}},"summary":"Accept a batch of Core Web Vitals from an anonymous client (sendBeacon). Public, no authorization.","tags":["RUM"]}},"/api/pipeline/events":{"post":{"operationId":"PipelineController_events","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineEventDto"}}}},"responses":{"202":{"description":""}},"summary":"Ingest a conveyor event from the orchestrator host (upsert task/step, append log, file snapshot)","tags":["Pipeline Events"]}},"/api/pipeline/summary":{"get":{"operationId":"PipelineController_getSummary","parameters":[{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Task counters by status + how many reached prod per hour/shift (issue #998)","tags":["Pipeline Events"]}},"/api/pipeline/speed":{"get":{"operationId":"PipelineController_getSpeed","parameters":[{"name":"force","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"\"Speed\" block: lead time 7/30d, per-stage breakdown, throughput, WIP (issue #1009)","tags":["Pipeline Events"]}},"/api/pipeline/speed/stage/{name}/tasks":{"get":{"operationId":"PipelineController_getStageTasks","parameters":[{"name":"name","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Tasks in a specific stage, sorted by time spent in it (issue #1009, click on the stage bar)","tags":["Pipeline Events"]}},"/api/pipeline/tasks":{"get":{"operationId":"PipelineController_listTasks","parameters":[{"name":"status","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"List of conveyor tasks (status filter, pagination)","tags":["Pipeline Events"]}},"/api/pipeline/tasks/{id}":{"get":{"operationId":"PipelineController_getTask","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"A conveyor task together with its steps","tags":["Pipeline Events"]}},"/api/pipeline/tasks/{id}/stage-timeline":{"get":{"operationId":"PipelineController_getStageTimeline","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Per-stage breakdown of one task (issue #998): queued→in_progress→review→…→prod","tags":["Pipeline Events"]}},"/api/pipeline/steps/{id}/logs":{"get":{"operationId":"PipelineController_getStepLogs","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"pageSize","required":true,"in":"query","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Conveyor step logs (pagination, total is a separate count, without all row bodies)","tags":["Pipeline Events"]}},"/api/pipeline/files/{name}":{"get":{"operationId":"PipelineController_getFile","parameters":[{"name":"name","required":true,"in":"path","schema":{"type":"string"}},{"name":"X-Tenant-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Tenant UUID — required for all tenant-scoped endpoints"}],"responses":{"200":{"description":""}},"security":[{"jwt":[]}],"summary":"Snapshot of a conveyor service file (GATES.md/questions.md/TEMPLATE.md)","tags":["Pipeline Events"]}}},"info":{"title":"LDM v3 API","description":"Multi-tenant B2B outreach automation platform. Auth: JWT Bearer (15-min) or tenant API key (ldm_*) managed in CRM Settings → API Keys. All tenant-scoped endpoints require the X-Tenant-Id header.","version":"1.0.0","contact":{}},"tags":[],"servers":[{"url":"https://api.live-direct-marketing.online","description":"Production"},{"url":"https://api.dev.live-direct-marketing.online","description":"Development"},{"url":"http://127.0.0.1:3000","description":"Local"}],"components":{"securitySchemes":{"jwt":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"JWT access token from /auth/login (Bearer )"},"tenant-api-key":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Tenant API key (Bearer ldm_*) for MCP/A2A clients. Issued via CRM Settings → API Keys."},"rpa-service":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Dedicated RPA service key. No tenant API-key or query-key authentication."}},"schemas":{"PushKeysDto":{"type":"object","properties":{"p256dh":{"type":"string","maxLength":300},"auth":{"type":"string","maxLength":100}},"required":["p256dh","auth"]},"PushSubscribeDto":{"type":"object","properties":{"endpoint":{"type":"string","maxLength":2048},"keys":{"$ref":"#/components/schemas/PushKeysDto"},"expirationTime":{"type":"number","nullable":true}},"required":["endpoint","keys"]},"PushUnsubscribeDto":{"type":"object","properties":{"endpoint":{"type":"string","maxLength":2048}},"required":["endpoint"]},"CreateSelfNoteDto":{"type":"object","properties":{"title":{"type":"string","description":"Note title"},"message":{"type":"string","description":"Note text"}},"required":["title","message"]},"RegisterDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":8,"maxLength":128},"firstName":{"type":"string","maxLength":100},"lastName":{"type":"string","maxLength":100},"channel":{"type":"object"},"org":{"type":"string","maxLength":200},"use_case":{"type":"string","maxLength":500},"website":{"type":"string","maxLength":300},"full_account":{"type":"boolean"},"termsAccepted":{"type":"boolean"}},"required":["email"]},"SignupQuestionnaireDto":{"type":"object","properties":{"token":{"type":"string","description":"signup_token из ответа регистрации (живёт 7 дней)","minLength":32,"maxLength":128},"applicant_type":{"type":"object","description":"Тип заявителя: юрлицо или частное лицо (анкета без сайта компании)"},"company_name":{"type":"string","minLength":2,"maxLength":200},"company_website":{"type":"string","description":"Домен проверяется автоматом: зарегистрирован, резолвится, отвечает по HTTP","maxLength":300},"company_email":{"type":"string","description":"Корпоративный ящик для связи и апрува","format":"email"},"use_case":{"type":"string","minLength":10,"maxLength":1000},"contacts_source":{"type":"object","description":"Откуда берётся база контактов — главный маркер спам-рассылки"},"outbound_volume_monthly":{"type":"number","minimum":0,"maximum":10000000},"operator_type":{"type":"object","description":"Кто ведёт аккаунт: человек, агент или связка"},"human_contact":{"type":"string","description":"Контакт ответственного человека (имя/телефон/мессенджер)","maxLength":300},"country":{"type":"string","maxLength":200},"company_registration_id":{"type":"string","description":"ИНН/рег.номер юрлица, если есть","maxLength":64}},"required":["token","applicant_type","company_name","use_case","contacts_source"]},"LoginDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string"}},"required":["email","password"]},"RefreshDto":{"type":"object","properties":{"refreshToken":{"type":"string"}},"required":["refreshToken"]},"ForgotPasswordDto":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]},"ResetPasswordDto":{"type":"object","properties":{"token":{"type":"string"},"newPassword":{"type":"string","minLength":8,"maxLength":128}},"required":["token","newPassword"]},"CreateUserDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":8},"firstName":{"type":"string"},"lastName":{"type":"string"},"role":{"type":"object"}},"required":["email","password"]},"UpdateRoleDto":{"type":"object","properties":{"role":{"type":"object"}},"required":["role"]},"UpdateStatusDto":{"type":"object","properties":{"status":{"type":"object"}},"required":["status"]},"UpdatePasswordDto":{"type":"object","properties":{"password":{"type":"string","minLength":8}},"required":["password"]},"UpdateProfileDto":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"}}},"AddCommentDto":{"type":"object","properties":{}},"CreateCustomFieldDto":{"type":"object","properties":{"entity":{"type":"string","default":"company"},"slug":{"type":"string","pattern":"/^[a-z0-9_]+$/"},"label":{"type":"string"},"labelEn":{"type":"string"},"fieldType":{"type":"string"},"options":{"type":"array","items":{"type":"object"}},"isRequired":{"type":"boolean"},"isVisibleInTable":{"type":"boolean"},"isFilterable":{"type":"boolean"},"isSortable":{"type":"boolean"},"numberFormat":{"type":"object"},"group":{"type":"string"},"settings":{"type":"object"}},"required":["slug","label","fieldType"]},"SetValuesDto":{"type":"object","properties":{"values":{"type":"object"},"source":{"type":"string"}},"required":["values"]},"UpdateCustomFieldDto":{"type":"object","properties":{"label":{"type":"string"},"labelEn":{"type":"string"},"options":{"type":"array","items":{"type":"object"}},"isRequired":{"type":"boolean"},"isVisibleInTable":{"type":"boolean"},"isFilterable":{"type":"boolean"},"isSortable":{"type":"boolean"},"numberFormat":{"type":"object"},"group":{"type":"string"},"sortOrder":{"type":"number"}}},"CompaniesBulkDto":{"type":"object","properties":{"action":{"type":"string","description":"Bulk action name (e.g. delete, addTags, removeTags, setField, addToList)"},"companyIds":{"description":"Company ids to act on","type":"array","items":{"type":"string"}},"ids":{"description":"Alias for companyIds","type":"array","items":{"type":"string"}},"tagIds":{"description":"Tag ids for addTags/removeTags actions","type":"array","items":{"type":"string"}},"listId":{"type":"string","description":"Target list id for addToList action"},"fieldName":{"type":"string","description":"Field name for a setField-style action"},"fieldValue":{"type":"object","description":"Field value for a setField-style action (shape depends on fieldName)"}},"required":["action"]},"ExportCompaniesDto":{"type":"object","properties":{"scope":{"type":"string","description":"Which companies to export","enum":["all","filtered","selected"]},"companyIds":{"description":"Company ids to export when scope is \"selected\"","type":"array","items":{"type":"string"}},"search":{"type":"string","description":"Search term applied when scope is \"filtered\""},"format":{"type":"string","description":"Export file format (e.g. csv, xlsx)"},"columns":{"description":"Column keys to include (defaults to COMPANY_EXPORT_COLUMNS defaults)","type":"array","items":{"type":"string"}},"listId":{"type":"string","description":"Restrict export to companies in this list id"}},"required":["scope"]},"MergeCompaniesDto":{"type":"object","properties":{"keepId":{"type":"string","description":"Id of the company record to keep"},"mergeIds":{"description":"Ids of the companies to merge into keepId and delete","type":"array","items":{"type":"string"}}},"required":["keepId","mergeIds"]},"ImportFromGoogleSheetsDto":{"type":"object","properties":{"url":{"type":"string","description":"Google Sheets URL to fetch rows from"}},"required":["url"]},"CompaniesImportPreviewDto":{"type":"object","properties":{"rows":{"description":"Raw rows parsed from the source file/sheet","type":"array","items":{"type":"object"}},"mapping":{"type":"object","description":"Column -> field mapping (csvColumn -> target field)"}},"required":["rows","mapping"]},"CompaniesImportStartDto":{"type":"object","properties":{"rows":{"description":"Raw rows parsed from the source file/sheet","type":"array","items":{"type":"object"}},"mapping":{"type":"object","description":"Column -> field mapping (csvColumn -> target field)"},"options":{"type":"object","description":"dedupeBy: \"auto\"|\"inn\"|\"domain\" (default auto); duplicateHandling: \"skip\"|\"update\"|\"enrich\"|\"create\" (default skip). \"enrich\" (#1057) fills only EMPTY fields of the matched duplicate from the file, never overwrites non-empty ones; customFields merge by the same rule (canon mergeCustomFields). listId (#1057): every row that matched a card — created, updated, OR a found duplicate (skip/enrich) — is added to this list; must be an existing list id in this tenant."}},"required":["rows","mapping"]},"CompaniesImportCombinedDto":{"type":"object","properties":{"rows":{"description":"Raw rows parsed from the source file/sheet","type":"array","items":{"type":"object"}},"mapping":{"type":"object","description":"Column -> field mapping. Company fields (name, domain, inn, industry, size, country, city, address, state, phone, website, source), custom cf:, contact c:firstName/c:lastName/c:email/c:phone/c:position/c:personalEmail/c:linkedin"},"options":{"type":"object","description":"dedupeBy, genericContactName, listId — see POST /companies/import/combined summary"}},"required":["rows","mapping"]},"CreateCompanyDto":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"domain":{"type":"string"},"industry":{"type":"string"},"size":{"type":"object"},"country":{"type":"string"},"city":{"type":"string"},"address":{"type":"string"},"phone":{"type":"string"},"website":{"type":"string"},"description":{"type":"string"},"source":{"type":"string"},"taxId":{"type":"string","maxLength":20},"status":{"type":"object"},"importBatchId":{"type":"string"}},"required":["name"]},"UpdateCompanyDto":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"domain":{"type":"string"},"industry":{"type":"string"},"size":{"type":"object"},"country":{"type":"string"},"city":{"type":"string"},"address":{"type":"string"},"phone":{"type":"string"},"website":{"type":"string"},"description":{"type":"string"},"source":{"type":"string"},"taxId":{"type":"string","maxLength":20},"status":{"type":"object"},"importBatchId":{"type":"string"},"state":{"type":"string"},"linkedin":{"type":"string"},"foundedYear":{"type":"string","pattern":"/^\\d{4}$/"},"catalogInn":{"type":"string","maxLength":12},"logo":{"type":"string"}}},"RpaReportDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required on placement-gated tasks and echoed in the durable receipt"},"taskId":{"type":"string","minLength":1,"maxLength":4096},"leaseId":{"type":"string","minLength":1,"maxLength":128},"fencingToken":{"type":"number","minimum":1},"operation":{"type":"string","enum":["CONTROL","REAL"],"description":"Required for placement-gated tasks; binds this receipt to one immutable phase."},"operationId":{"type":"string","maxLength":128,"description":"Immutable operation identity returned in the full claim."},"taskVersion":{"type":"string","maxLength":128},"contentFingerprint":{"type":"string","maxLength":128},"outcome":{"type":"string","enum":["SENT","DEFINITE_FAILURE","UNKNOWN"]},"relayAccountId":{"type":"string","minLength":1,"maxLength":128},"method":{"type":"string","enum":["RPA"]},"envelopeHash":{"type":"string","minLength":64,"maxLength":64},"occurredAt":{"type":"string"},"providerMessageId":{"type":"string","maxLength":998},"headersApplied":{"type":"boolean"},"provider":{"type":"string","maxLength":256},"sender":{"type":"string","maxLength":320,"description":"Sender mailbox from claim.envelope.from; display name is not part of sender identity."},"senderName":{"type":"string","maxLength":320,"description":"Optional display name. Does not authorize delivery or change receipt identity."}},"required":["workerId","taskId","leaseId","fencingToken","outcome","relayAccountId","method","envelopeHash","occurredAt","headersApplied"]},"RpaHeartbeatDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required for placement-gated tasks; legacy workers fail closed when omitted"},"protocolVersion":{"type":"string","enum":["1"]},"taskId":{"type":"string","minLength":1,"maxLength":4096,"description":"Supply all three lease fields to extend a live task; omit all for service telemetry only"},"leaseId":{"type":"string","minLength":1,"maxLength":128},"fencingToken":{"type":"number","minimum":1},"operation":{"type":"string","enum":["CONTROL","REAL"]},"operationId":{"type":"string","maxLength":128},"taskVersion":{"type":"string","maxLength":128},"contentFingerprint":{"type":"string","maxLength":128}},"required":["workerId","protocolVersion"]},"RpaWorkerDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required for placement-gated tasks; legacy workers fail closed when omitted"}},"required":["workerId"]},"RpaLeaseDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required for placement-gated tasks; legacy workers fail closed when omitted"},"taskId":{"type":"string","minLength":1,"maxLength":4096},"leaseId":{"type":"string","minLength":1,"maxLength":128},"fencingToken":{"type":"number","minimum":1},"operation":{"type":"string","enum":["CONTROL","REAL"]},"operationId":{"type":"string","maxLength":128},"taskVersion":{"type":"string","maxLength":128},"contentFingerprint":{"type":"string","maxLength":128}},"required":["workerId","taskId","leaseId","fencingToken"]},"RpaReportRequestDto":{"type":"object","properties":{"taskId":{"type":"string","minLength":1,"maxLength":4096},"leaseId":{"type":"string","minLength":1,"maxLength":128},"outcome":{"type":"string","enum":["SENT","DEFINITE_FAILURE","UNKNOWN"]},"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required on placement-gated tasks and echoed in the durable receipt"},"fencingToken":{"type":"number","minimum":1},"operation":{"type":"string","enum":["CONTROL","REAL"],"description":"Required for placement-gated tasks; binds this receipt to one immutable phase."},"operationId":{"type":"string","maxLength":128,"description":"Immutable operation identity returned in the full claim."},"taskVersion":{"type":"string","maxLength":128},"contentFingerprint":{"type":"string","maxLength":128},"relayAccountId":{"type":"string","minLength":1,"maxLength":128},"method":{"type":"string","enum":["RPA"]},"envelopeHash":{"type":"string","minLength":64,"maxLength":64},"occurredAt":{"type":"string"},"providerMessageId":{"type":"string","maxLength":998},"headersApplied":{"type":"boolean"},"provider":{"type":"string","maxLength":256},"sender":{"type":"string","maxLength":320,"description":"Sender mailbox from claim.envelope.from; display name is not part of sender identity."},"senderName":{"type":"string","maxLength":320,"description":"Optional display name. Does not authorize delivery or change receipt identity."}},"required":["taskId","leaseId","outcome"]},"RpaProfileReleaseDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required for placement-gated tasks; legacy workers fail closed when omitted"},"taskId":{"type":"string","minLength":1,"maxLength":4096},"leaseId":{"type":"string","minLength":1,"maxLength":128},"fencingToken":{"type":"number","minimum":1},"operation":{"type":"string","enum":["CONTROL","REAL"]},"operationId":{"type":"string","maxLength":128},"taskVersion":{"type":"string","maxLength":128},"contentFingerprint":{"type":"string","maxLength":128},"sessionClosed":{"type":"number","enum":[true],"description":"Positive executor acknowledgement that this task browser session is closed. Mail reports alone do not release the profile before expiresAt."}},"required":["workerId","taskId","leaseId","fencingToken","sessionClosed"]},"RpaReturnDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required on placement-gated tasks and echoed in the durable receipt"},"taskId":{"type":"string","minLength":1,"maxLength":4096},"leaseId":{"type":"string","minLength":1,"maxLength":128},"fencingToken":{"type":"number","minimum":1},"operation":{"type":"string","enum":["CONTROL","REAL"],"description":"Required for placement-gated tasks; binds this receipt to one immutable phase."},"operationId":{"type":"string","maxLength":128,"description":"Immutable operation identity returned in the full claim."},"taskVersion":{"type":"string","maxLength":128},"contentFingerprint":{"type":"string","maxLength":128},"outcome":{"type":"string","enum":["DEFINITE_FAILURE"]},"relayAccountId":{"type":"string","minLength":1,"maxLength":128},"method":{"type":"string","enum":["RPA"]},"envelopeHash":{"type":"string","minLength":64,"maxLength":64},"occurredAt":{"type":"string"},"providerMessageId":{"type":"string","maxLength":998},"headersApplied":{"type":"boolean"},"provider":{"type":"string","maxLength":256},"sender":{"type":"string","maxLength":320,"description":"Sender mailbox from claim.envelope.from; display name is not part of sender identity."},"senderName":{"type":"string","maxLength":320,"description":"Optional display name. Does not authorize delivery or change receipt identity."}},"required":["workerId","taskId","leaseId","fencingToken","outcome","relayAccountId","method","envelopeHash","occurredAt","headersApplied"]},"RpaReconciliationListDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required for placement-gated tasks; legacy workers fail closed when omitted"},"after":{"type":"string","description":"Read the next page after this delivery ID, independently in each authorized target"}},"required":["workerId"]},"RpaReconcileDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required on placement-gated tasks and echoed in the durable receipt"},"taskId":{"type":"string","minLength":1,"maxLength":4096},"leaseId":{"type":"string","minLength":1,"maxLength":128},"fencingToken":{"type":"number","minimum":1},"operation":{"type":"string","enum":["CONTROL","REAL"],"description":"Required for placement-gated tasks; binds this receipt to one immutable phase."},"operationId":{"type":"string","maxLength":128,"description":"Immutable operation identity returned in the full claim."},"taskVersion":{"type":"string","maxLength":128},"contentFingerprint":{"type":"string","maxLength":128},"outcome":{"type":"string","enum":["SENT","DEFINITE_FAILURE","UNKNOWN"]},"relayAccountId":{"type":"string","minLength":1,"maxLength":128},"method":{"type":"string","enum":["RPA"]},"envelopeHash":{"type":"string","minLength":64,"maxLength":64},"occurredAt":{"type":"string"},"providerMessageId":{"type":"string","maxLength":998},"headersApplied":{"type":"boolean"},"provider":{"type":"string","maxLength":256},"sender":{"type":"string","maxLength":320,"description":"Sender mailbox from claim.envelope.from; display name is not part of sender identity."},"senderName":{"type":"string","maxLength":320,"description":"Optional display name. Does not authorize delivery or change receipt identity."},"eventId":{"type":"string","format":"uuid"},"evidenceKind":{"type":"string","enum":["PROVIDER_SENT","EXECUTOR_NOT_SENT"]},"evidenceId":{"type":"string","minLength":1,"maxLength":256,"description":"Reference to retained executor/provider evidence. An empty Sent-folder search is not NOT_SENT evidence."}},"required":["workerId","taskId","leaseId","fencingToken","outcome","relayAccountId","method","envelopeHash","occurredAt","headersApplied","eventId","evidenceKind","evidenceId"]},"RpaExecutionErrorDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required for placement-gated tasks; legacy workers fail closed when omitted"},"taskId":{"type":"string","minLength":1,"maxLength":4096},"leaseId":{"type":"string","minLength":1,"maxLength":128},"fencingToken":{"type":"number","minimum":1},"operation":{"type":"string","enum":["CONTROL","REAL"]},"operationId":{"type":"string","maxLength":128},"taskVersion":{"type":"string","maxLength":128},"contentFingerprint":{"type":"string","maxLength":128},"eventId":{"type":"string","format":"uuid"},"stage":{"type":"string","enum":["PROFILE","OPEN_SITE","LOGIN","PREPARE","SEND","CONFIRM"]},"errorCode":{"type":"string","enum":["PROFILE_START_FAILED","WEBSITE_UNAVAILABLE","DNS_ERROR","TIMEOUT","AUTH_FAILED","TWO_FACTOR_REQUIRED","CAPTCHA_REQUIRED","ACCOUNT_BANNED","DELIVERY_UNCERTAIN"]},"sendAttempted":{"type":"boolean"}},"required":["workerId","taskId","leaseId","fencingToken","eventId","stage","errorCode","sendAttempted"]},"RpaPlacementDto":{"type":"object","properties":{"workerId":{"type":"string","minLength":1,"maxLength":128},"capabilityVersion":{"type":"string","maxLength":64,"description":"Required on placement-gated tasks"},"taskId":{"type":"string","minLength":1,"maxLength":4096},"leaseId":{"type":"string","minLength":1,"maxLength":128},"fencingToken":{"type":"number","minimum":1},"operation":{"type":"string","enum":["CONTROL","REAL"]},"operationId":{"type":"string","maxLength":128},"taskVersion":{"type":"string","maxLength":128},"contentFingerprint":{"type":"string","maxLength":128},"placement":{"type":"string","enum":["INBOX","SPAM","PROMOTIONS","NOT_RECEIVED","ERROR"]},"scope":{"type":"string","enum":["seed_copy"]},"provenance":{"type":"string","enum":["external_rpa"]},"correlation":{"type":"string","minLength":1,"maxLength":256},"evidenceId":{"type":"string","minLength":1,"maxLength":256},"measuredAt":{"type":"string"},"sentAt":{"type":"string"}},"required":["workerId","taskId","leaseId","fencingToken","placement","scope","provenance","correlation","evidenceId","measuredAt","sentAt"]},"CheckEmailsDto":{"type":"object","properties":{"emails":{"minItems":1,"type":"array","items":{"type":"string"}}},"required":["emails"]},"CreateReportDto":{"type":"object","properties":{"title":{"type":"string","description":"Report title","maxLength":300},"description":{"type":"string","description":"Required explanation: what is in the file, where the data comes from, how to use it (min. 10 characters)"},"fileName":{"type":"string","description":"File name with an extension from the whitelist (csv, xlsx, json, pdf, txt, md, zip, png, jpg)"},"contentBase64":{"type":"string","description":"File content in base64 (decoded size <= REPORTS_MAX_FILE_BASE64_MB, default 30 MB)"}},"required":["title","description","fileName","contentBase64"]},"FromExportDto":{"type":"object","properties":{"title":{"type":"string","description":"Title (default — export file name)"},"description":{"type":"string","description":"Explanation (default — export auto-description)"}}},"UpdateReportDto":{"type":"object","properties":{"title":{"type":"string","maxLength":300},"description":{"type":"string","description":"Min. 10 characters"}}},"VerifyOneDto":{"type":"object","properties":{"email":{"type":"string","description":"Email to verify"}},"required":["email"]},"VerifyBatchDto":{"type":"object","properties":{"emails":{"description":"Emails to verify","type":"array","items":{"type":"string"}}},"required":["emails"]},"CreateDefinitionDto":{"type":"object","properties":{"entity":{"type":"string"},"name":{"type":"string"},"fieldKey":{"type":"string"},"type":{"type":"string"},"isRequired":{"type":"boolean"},"settings":{"type":"object"},"label":{"type":"string"},"labelEn":{"type":"string"},"group":{"type":"string"},"isVisibleInTable":{"type":"boolean"},"isFilterable":{"type":"boolean"},"isSortable":{"type":"boolean"},"numberFormat":{"type":"object"}},"required":["entity","name","fieldKey","type"]},"UpdateDefinitionDto":{"type":"object","properties":{"name":{"type":"string"},"isRequired":{"type":"boolean"},"settings":{"type":"object"},"sortOrder":{"type":"number"},"label":{"type":"string"},"labelEn":{"type":"string"},"group":{"type":"string"},"isVisibleInTable":{"type":"boolean"},"isFilterable":{"type":"boolean"},"isSortable":{"type":"boolean"},"numberFormat":{"type":"object"}}},"ReorderItemDto":{"type":"object","properties":{"id":{"type":"string"},"sortOrder":{"type":"number"}},"required":["id","sortOrder"]},"ReorderDto":{"type":"object","properties":{}},"SetValueDto":{"type":"object","properties":{"fieldId":{"type":"string"},"value":{"type":"object"},"source":{"type":"string"}},"required":["fieldId","value"]},"ContactsBulkDto":{"type":"object","properties":{"action":{"type":"string","description":"Bulk action name (delete, addTags, removeTags, addToList, removeFromList, updateField)"},"contactIds":{"description":"Contact ids to act on","type":"array","items":{"type":"string"}},"ids":{"description":"Alias for contactIds","type":"array","items":{"type":"string"}},"selectAll":{"type":"boolean","description":"Resolve target ids server-side from the current filter instead of contactIds/ids"},"search":{"type":"string","description":"Search term used when selectAll is true"},"listId":{"type":"string","description":"Target list id for addToList/removeFromList; also the fallback selectAll filter list"},"filterListId":{"type":"string","description":"Source filter list id when selectAll is true (listId is reserved for the addToList/removeFromList target)"},"tagIds":{"description":"Tag ids for addTags/removeTags actions","type":"array","items":{"type":"string"}},"companyId":{"type":"string","description":"Company id for a company-scoped action"},"fieldName":{"type":"string","description":"Field name for an updateField-style action"},"fieldValue":{"type":"object","description":"Field value for an updateField-style action (shape depends on fieldName)"},"digProvider":{"type":"string","description":"DIG selectAll filter: enrichment provider"},"digDomainType":{"type":"string","description":"DIG selectAll filter: domain type"},"digHasMx":{"type":"string","description":"DIG selectAll filter: has MX (\"true\"/\"false\")"},"digHasSpf":{"type":"string","description":"DIG selectAll filter: has SPF (\"true\"/\"false\")"},"digHasDmarc":{"type":"string","description":"DIG selectAll filter: has DMARC (\"true\"/\"false\")"},"digIsRoleBased":{"type":"string","description":"DIG selectAll filter: role-based mailbox (\"true\"/\"false\")"},"digIsDisposable":{"type":"string","description":"DIG selectAll filter: disposable domain (\"true\"/\"false\")"},"digIsSuspicious":{"type":"string","description":"DIG selectAll filter: suspicious (\"true\"/\"false\")"},"digAnalyzed":{"type":"string","description":"DIG selectAll filter: already analyzed (\"true\"/\"false\")"},"emailValidStatus":{"type":"string","description":"DIG selectAll filter: email validation status"}},"required":["action"]},"ExportContactsDto":{"type":"object","properties":{"scope":{"type":"string","description":"Which contacts to export","enum":["all","filtered","selected","list"]},"contactIds":{"description":"Contact ids to export when scope is \"selected\"","type":"array","items":{"type":"string"}},"listId":{"type":"string","description":"Restrict export to contacts in this list"},"search":{"type":"string","description":"Search term applied when scope is \"filtered\""},"format":{"type":"string","description":"Export file format (e.g. csv, xlsx)"},"includeCustomFields":{"type":"boolean","description":"Include tenant custom field columns"}},"required":["scope"]},"ContactsImportPreviewDto":{"type":"object","properties":{"rows":{"description":"Raw rows parsed from the source file/sheet","type":"array","items":{"type":"object"}},"mapping":{"type":"object","description":"Column -> field mapping (csvColumn -> target field)"}},"required":["rows","mapping"]},"ContactsImportStartDto":{"type":"object","properties":{"rows":{"description":"Raw rows parsed from the source file/sheet","type":"array","items":{"type":"object"}},"mapping":{"type":"object","description":"Column -> field mapping (csvColumn -> target field)"},"options":{"type":"object","description":"duplicateHandling: \"skip\"|\"update\"|\"create\" (default skip); listId; tagIds"}},"required":["rows","mapping"]},"CreateContactDto":{"type":"object","properties":{"firstName":{"type":"string","maxLength":100},"lastName":{"type":"string","maxLength":100},"middleName":{"type":"string","maxLength":100},"gender":{"type":"string","enum":["male","female","unknown"]},"position":{"type":"string"},"department":{"type":"string"},"companyId":{"type":"string"},"source":{"type":"string"},"contactType":{"type":"string","enum":["PERSONAL","COMPANY"]},"importBatchId":{"type":"string","description":"[LEGACY] import_task_id for import rollback"}},"required":["firstName"]},"UpdateContactDto":{"type":"object","properties":{"firstName":{"type":"string","maxLength":100},"lastName":{"type":"string","maxLength":100},"middleName":{"type":"string","maxLength":100},"gender":{"type":"string","enum":["male","female","unknown"]},"position":{"type":"string"},"department":{"type":"string"},"companyId":{"type":"string"},"source":{"type":"string"},"contactType":{"type":"string","enum":["PERSONAL","COMPANY"]}}},"MergeContactsDto":{"type":"object","properties":{"keepId":{"type":"string","description":"Id of the contact record to keep"},"mergeIds":{"description":"Ids of the contacts to merge into keepId and delete","type":"array","items":{"type":"string"}}},"required":["keepId","mergeIds"]},"AddChannelDto":{"type":"object","properties":{"type":{"type":"string","enum":["EMAIL","PHONE","LINKEDIN","TELEGRAM","VK","WHATSAPP","WEBSITE","SKYPE","OTHER"],"example":"EMAIL","description":"Channel type — UPPERCASE enum. Use field name \"type\", NOT \"kind\"."},"value":{"type":"string","example":"anna@acme.com","description":"Channel value — email address, phone number, URL, etc."},"label":{"type":"string","example":"work"},"isPrimary":{"type":"boolean","example":false,"description":"Set as primary channel of this type for the contact."}},"required":["type","value"]},"UpdateChannelDto":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"isPrimary":{"type":"boolean"},"status":{"type":"string","enum":["ACTIVE","BOUNCED","OPTED_OUT","INVALID","STOP_ALL","CHECKING"]},"emailValidStatus":{"type":"string","enum":["UNKNOWN","VALID","INVALID","CATCH_ALL","DISPOSABLE","ROLE","SPAM_TRAP","HARD_BOUNCE","UNSUBSCRIBED"]}}},"CreatePipelineDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string"},"currency":{"type":"string"},"isDefault":{"type":"boolean"},"isHidden":{"type":"boolean"}},"required":["name"]},"UpdatePipelineDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string"},"currency":{"type":"string"},"isDefault":{"type":"boolean"},"isActive":{"type":"boolean"},"isHidden":{"type":"boolean"}}},"CreateStageDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"type":{"type":"object"},"color":{"type":"string"},"probability":{"type":"number","minimum":0,"maximum":100},"rottingDays":{"type":"number"},"sortOrder":{"type":"number"}},"required":["name"]},"ReorderStagesDto":{"type":"object","properties":{"stageIds":{"type":"array","items":{"type":"string"}}},"required":["stageIds"]},"UpdateStageDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"type":{"type":"object"},"color":{"type":"string"},"probability":{"type":"number","minimum":0,"maximum":100},"rottingDays":{"type":"number"},"sortOrder":{"type":"number"},"isHidden":{"type":"boolean"}}},"CreateAutomationDto":{"type":"object","properties":{"trigger":{"type":"object"},"action":{"type":"object"},"config":{"type":"object"},"name":{"type":"string","maxLength":200},"isActive":{"type":"boolean"}},"required":["trigger","action","config"]},"UpdateAutomationDto":{"type":"object","properties":{"trigger":{"type":"object"},"action":{"type":"object"},"config":{"type":"object"},"name":{"type":"string","maxLength":200},"isActive":{"type":"boolean"},"sortOrder":{"type":"number"}}},"SetInterestDto":{"type":"object","properties":{"status":{"type":"string","description":"Interest status value (validated against the allowed set in LeadsService)"},"note":{"type":"string","description":"Free-text note, max 500 chars (enforced in LeadsService)"}},"required":["status"]},"UpdateDealDto":{"type":"object","properties":{"amount":{"type":"number"},"currency":{"type":"string"},"probability":{"type":"number"},"expectedCloseDate":{"type":"string","description":"ISO date string"}}},"CreateLeadDto":{"type":"object","properties":{"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"title":{"type":"string","maxLength":255},"description":{"type":"string"},"amount":{"type":"number"},"currency":{"type":"string"},"pipelineId":{"type":"string"},"stageId":{"type":"string"},"companyId":{"type":"string"},"contactId":{"type":"string"},"source":{"type":"string"}},"required":["title"]},"UpdateLeadDto":{"type":"object","properties":{"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"title":{"type":"string","maxLength":255},"description":{"type":"string"},"amount":{"type":"number"},"currency":{"type":"string"},"companyId":{"type":"string"},"contactId":{"type":"string"},"source":{"type":"string"},"expectedCloseDate":{"type":"string"}}},"MoveLeadDto":{"type":"object","properties":{"stageId":{"type":"string"},"pipelineId":{"type":"string"},"lostReason":{"type":"string"}},"required":["stageId"]},"LeadsBulkDto":{"type":"object","properties":{"action":{"type":"string","description":"Bulk action name (e.g. delete, addTags, removeTags, setField, moveStage)"},"ids":{"description":"Lead ids to act on","type":"array","items":{"type":"string"}},"leadIds":{"description":"Alias for ids","type":"array","items":{"type":"string"}},"tagIds":{"description":"Tag ids for addTags/removeTags actions","type":"array","items":{"type":"string"}},"fieldName":{"type":"string","description":"Field name for a setField-style action"},"fieldValue":{"type":"object","description":"Field value for a setField-style action (shape depends on fieldName)"},"stageId":{"type":"string","description":"Target stage id for a moveStage-style action"},"priority":{"type":"object","description":"Priority value for a setPriority-style action"}},"required":["action"]},"ExportLeadsDto":{"type":"object","properties":{"scope":{"type":"string","description":"Which leads to export","enum":["all","filtered","selected"]},"leadIds":{"description":"Lead ids to export when scope is \"selected\"","type":"array","items":{"type":"string"}},"pipelineId":{"type":"string","description":"Restrict export to leads in this pipeline"},"stageId":{"type":"string","description":"Restrict export to leads in this stage"},"format":{"type":"string","description":"Export file format (e.g. csv, xlsx)"}},"required":["scope"]},"LeadsImportPreviewDto":{"type":"object","properties":{"rows":{"description":"Raw rows parsed from the source file/sheet","type":"array","items":{"type":"object"}},"mapping":{"type":"object","description":"Column -> field mapping (csvColumn -> target field)"}},"required":["rows","mapping"]},"LeadsImportStartDto":{"type":"object","properties":{"rows":{"description":"Raw rows parsed from the source file/sheet","type":"array","items":{"type":"object"}},"mapping":{"type":"object","description":"Column -> field mapping (csvColumn -> target field)"},"options":{"type":"object"}},"required":["rows","mapping"]},"CreateTagDto":{"type":"object","properties":{"name":{"type":"string","maxLength":50},"color":{"type":"string"}},"required":["name"]},"UpdateTagDto":{"type":"object","properties":{"name":{"type":"string","maxLength":50},"color":{"type":"string"}}},"AttachTagDto":{"type":"object","properties":{"tagId":{"type":"string"}},"required":["tagId"]},"ContactListsCreateDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"type":{"type":"string"},"smartFilters":{"type":"object"},"isPinned":{"type":"boolean"},"groupId":{"type":"object","nullable":true}},"required":["name"]},"ContactListsUpdateDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"type":{"type":"string"},"smartFilters":{"type":"object"},"viewConfig":{"type":"object"},"isPinned":{"type":"boolean"},"groupId":{"type":"object","nullable":true}}},"ContactListsReorderItemDto":{"type":"object","properties":{"id":{"type":"string"},"sortOrder":{"type":"number"}},"required":["id","sortOrder"]},"ContactListsReorderDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ContactListsReorderItemDto"}}},"required":["items"]},"ContactListsAddContactsDto":{"type":"object","properties":{"contactIds":{"type":"array","items":{"type":"string"}}},"required":["contactIds"]},"CompanyListsCreateDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"type":{"type":"string"},"smartFilters":{"type":"object","description":"SMART lists only: explicit versioned native company filters. STATIC lists leave this unset.","example":{"version":1,"filterRules":[{"field":"industry","operator":"contains","value":"SaaS"}]}},"isPinned":{"type":"boolean"},"groupId":{"type":"object","nullable":true}},"required":["name"]},"CompanyListsUpdateDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"type":{"type":"string"},"smartFilters":{"type":"object","description":"SMART lists only: explicit versioned native company filters. STATIC lists leave this unset.","example":{"version":1,"filterRules":[{"field":"industry","operator":"contains","value":"SaaS"}]}},"isPinned":{"type":"boolean"},"groupId":{"type":"object","nullable":true}}},"CompanyListsReorderItemDto":{"type":"object","properties":{"id":{"type":"string"},"sortOrder":{"type":"number"}},"required":["id","sortOrder"]},"CompanyListsReorderDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CompanyListsReorderItemDto"}}},"required":["items"]},"CompanyListsAddCompaniesDto":{"type":"object","properties":{"companyIds":{"type":"array","items":{"type":"string"}}},"required":["companyIds"]},"CompanyListsMergeDto":{"type":"object","properties":{"targetId":{"type":"string","description":"Id of the list to merge member companies into"},"mode":{"type":"string","description":"move: relocate companies to targetId; copy: keep them in both lists","enum":["move","copy"]}},"required":["targetId","mode"]},"UpdateAiProvidersDto":{"type":"object","properties":{"aiProvider":{"type":"string"},"aitunnelKey":{"type":"string","nullable":true},"hydraaiKey":{"type":"string","nullable":true},"claudeApiKey":{"type":"string","nullable":true},"balanceThreshold":{"type":"number"},"defaultAiModel":{"type":"string"},"fallbackProvider":{"type":"string"}}},"RequestLdmAiDto":{"type":"object","properties":{"note":{"type":"string"}}},"UpdateNotificationsDto":{"type":"object","properties":{"pushKey":{"type":"string"},"pushNotify":{"type":"boolean"},"notifyEmail":{"type":"string"},"emailNotify":{"type":"boolean"}}},"UpdateWorkspaceDto":{"type":"object","properties":{"workspaceName":{"type":"string"},"defaultCurrency":{"type":"string"},"defaultLanguage":{"type":"string"}}},"ChangePasswordDto":{"type":"object","properties":{"currentPassword":{"type":"string"},"newPassword":{"type":"string","minLength":8}},"required":["currentPassword","newPassword"]},"ComposeAttachmentDto":{"type":"object","properties":{"filename":{"type":"string"},"contentBase64":{"type":"string"},"contentType":{"type":"string"}},"required":["filename","contentBase64"]},"ComposeDto":{"type":"object","properties":{"accountId":{"type":"string"},"accountListId":{"type":"string"},"toEmail":{"type":"string","format":"email"},"toName":{"type":"string"},"fromName":{"type":"string"},"subject":{"type":"string"},"bodyText":{"type":"string"},"bodyHtml":{"type":"string"},"contactId":{"type":"string"},"companyId":{"type":"string"},"leadId":{"type":"string"},"scheduledAt":{"type":"string"},"timezone":{"type":"string"},"intentKey":{"type":"string","description":"Validated business intent for customer outreach; LIVE without it is held."},"policyWindowDays":{"type":"number","minimum":1,"maximum":3650},"attachmentsJson":{"type":"array","items":{"$ref":"#/components/schemas/ComposeAttachmentDto"}}},"required":["toEmail","subject"]},"ImageImportSourceDto":{"type":"object","properties":{"attachmentRef":{"type":"string"},"libraryFileId":{"type":"string"}}},"ImageImportTargetDto":{"type":"object","properties":{"store":{"type":"object","default":"ASSETS"}}},"ImageImportNormalizeDto":{"type":"object","properties":{"maxEdgePx":{"type":"number","minimum":1},"format":{"type":"object"},"quality":{"type":"number","minimum":1}}},"ImageImportDto":{"type":"object","properties":{"source":{"$ref":"#/components/schemas/ImageImportSourceDto"},"imageRefs":{"type":"array","items":{"type":"string"}},"all":{"type":"boolean"},"target":{"$ref":"#/components/schemas/ImageImportTargetDto"},"normalize":{"$ref":"#/components/schemas/ImageImportNormalizeDto"},"minEdgePx":{"type":"number","minimum":1}},"required":["source"]},"AttachEntityFileDto":{"type":"object","properties":{"contactId":{"type":"string"},"companyId":{"type":"string"},"leadId":{"type":"string"},"createdBy":{"type":"string"}}},"UpdateLibraryItemDto":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"briefId":{"type":"string","nullable":true},"leadId":{"type":"string","nullable":true},"contactId":{"type":"string","nullable":true},"companyId":{"type":"string","nullable":true}}},"CustomRuleDto":{"type":"object","properties":{"id":{"type":"string","description":"Rule id"},"phrase":{"type":"string","description":"Phrase to search"},"severity":{"type":"string","description":"Severity"},"scope":{"type":"string","description":"Scope"},"message":{"type":"string","description":"Message"},"weight":{"type":"number","description":"Weight"}},"required":["id","phrase","severity","scope","weight"]},"CheckContentDto":{"type":"object","properties":{"subject":{"type":"string","description":"Subject"},"bodyText":{"type":"string","description":"Body text"},"bodyHtml":{"type":"string","description":"Body html"},"customRules":{"description":"Custom rules","type":"array","items":{"$ref":"#/components/schemas/CustomRuleDto"}}}},"CreateBranchDto":{"type":"object","properties":{"methodId":{"type":"number","description":"Sub-branch method (11 email validation, 14 ICP review, 15 DIG, 22 scoring)"},"methodName":{"type":"string"},"description":{"type":"string"},"branchTrigger":{"type":"object","description":"Branch entry condition: { event, condition? }"},"mailingConfig":{"type":"object"},"contactListId":{"type":"string"},"creativeId":{"type":"string"},"accountListId":{"type":"string"}},"required":["methodId","methodName","branchTrigger"]},"EnrollInBranchDto":{"type":"object","properties":{"contactIds":{"type":"array","items":{"type":"string"}}},"required":["contactIds"]},"CreateTaskDto":{"type":"object","properties":{"methodId":{"type":"number","description":"Method id — e.g. 22=scoring (lead gen), 11=email validation, 14=ICP review, 15=DIG, 12=mailing (legacy, use /campaigns instead)"},"methodName":{"type":"string","description":"Human-readable label mirroring methodId, e.g. \"scoring\""},"description":{"type":"string"},"config":{"type":"object","description":"Method-specific configuration payload (shape depends on methodId)"},"mailingConfig":{"type":"object","description":"Mailing configuration patch (methodId=12, legacy)"},"contactListId":{"type":"string","description":"Contact list to source items from at POST /tasks/:id/start"},"contactListIdFinish":{"type":"string","description":"Contact list to move finished items into"},"accountListId":{"type":"string"},"creativeId":{"type":"string"},"creativeIds":{"type":"array","items":{"type":"string"}},"companyListId":{"type":"string","description":"CompanyList id — for methodId=22 (scoring): items are populated from this list at POST /tasks/:id/start; must reference an existing list"},"resumeAt":{"type":"string","description":"ISO date string — task waits (does not run) until this moment"},"streamCount":{"type":"number","description":"Parallel stream count, clamped to the tenant maxStreams setting"}},"required":["methodId","methodName"]},"UpdateTaskDto":{"type":"object","properties":{"description":{"type":"string"},"config":{"type":"object","description":"Task configuration; shape depends on methodId"},"mailingConfig":{"type":"object"},"contactListId":{"type":"string"},"contactListIdFinish":{"type":"string"},"accountListId":{"type":"string"},"creativeId":{"type":"string"},"creativeIds":{"type":"array","items":{"type":"string"}},"companyListId":{"type":"string"},"resumeAt":{"type":"string","description":"ISO time of resumption"},"streamCount":{"type":"number"}}},"StartTaskDto":{"type":"object","properties":{"limit":{"type":"number","minimum":1,"description":"Trial run: process no more than N items and pause the task. The limit is ONE-TIME — the next start without the parameter runs the rest to completion.","maximum":1000,"example":100}}},"AddPipelineStepDto":{"type":"object","properties":{"type":{"type":"string","description":"Pipeline step type: SITE_AVAILABILITY, AI_CONTENT, KEYWORDS, EMAIL_EXTRACT, PHONE_EXTRACT, SOCIAL_LINKS, TECH_DETECT, GEO_FILTER, NALOG_LOOKUP, AI_CARD_FIELD, etc."},"enabled":{"type":"boolean","description":"Step is active (defaults to true)"},"name":{"type":"string","description":"Human-readable step name (defaults to type)"},"config":{"type":"object","description":"Step configuration (shape depends on type)"},"onSuccess":{"type":"string","description":"Routing on success: CONTINUE|STOP|MOVE_TO_LIST|DELETE"},"onSuccessTarget":{"type":"string","description":"Target for onSuccess=MOVE_TO_LIST (list id)"},"onFail":{"type":"string","description":"Routing on failure: CONTINUE|STOP|MOVE_TO_LIST|DELETE"},"onFailTarget":{"type":"string","description":"Target for onFail=MOVE_TO_LIST (list id)"},"onError":{"type":"string","description":"Routing on error: CONTINUE|STOP|MOVE_TO_LIST|DELETE"},"onErrorTarget":{"type":"string","description":"Target for onError=MOVE_TO_LIST (list id)"}},"required":["type"]},"ReorderStepsDto":{"type":"object","properties":{"stepIds":{"description":"Step identifiers in the desired execution order","type":"array","items":{"type":"string"}}},"required":["stepIds"]},"UpdatePipelineStepDto":{"type":"object","properties":{"type":{"type":"string","description":"ScoringStepType value"},"enabled":{"type":"boolean"},"name":{"type":"string"},"config":{"type":"object","description":"Step configuration; shape depends on type"},"onSuccess":{"type":"string","description":"CONTINUE | STOP | MOVE_TO_LIST | DELETE"},"onSuccessTarget":{"type":"string"},"onFail":{"type":"string","description":"CONTINUE | STOP | MOVE_TO_LIST | DELETE"},"onFailTarget":{"type":"string"},"onError":{"type":"string","description":"CONTINUE | STOP | MOVE_TO_LIST | DELETE"},"onErrorTarget":{"type":"string"}}},"RetryScoringResultsDto":{"type":"object","properties":{"reasonCodes":{"type":"array","minItems":1,"description":"AND filter shared by preview and retry. Without statuses, selects technical failures only; UNAVAILABLE still requires includeUnavailable. An empty array is rejected.","items":{"type":"string","enum":["dns_fail","tls_fail","conn_refused","timeout","http_4xx","http_5xx","redirect_loop","empty_content","no_material","ai_no_response","ai_parse_fail","batch_parse_fail","verdict_negative","verdict_contradictory","internal_error","stub_page","unclassified"]}},"statuses":{"type":"array","description":"ScoringResult statuses to retry. Defaults to ERROR only (the old behavior). UNAVAILABLE (dead domain) is excluded from this list by the service even if specified here — see includeUnavailable. STUB_MATERIAL (#1146) — the material was a JS stub/error page/parking page; a retry makes sense if the site material is expected to have changed.","items":{"type":"string","enum":["ERROR","UNAVAILABLE","NO_WWW","SCORED_BELOW_THRESHOLD","SKIPPED","STUB_MATERIAL"]}},"includeUnavailable":{"type":"boolean","description":"Explicit confirmation: include UNAVAILABLE (dead domains) in the retry, despite the crawl usually being useless and paid. Without this flag the service silently drops UNAVAILABLE from statuses."},"processedAfter":{"type":"string","description":"Only results with processedAt >= this ISO time"},"processedBefore":{"type":"string","description":"Only results with processedAt <= this ISO time"},"resultIds":{"description":"Targeted retry: ids of specific ScoringResult rows (not status/window). Combined with companyIds via OR; records not belonging to this task are silently ignored.","type":"array","items":{"type":"string"}},"companyIds":{"description":"Targeted retry: companyId of the cards (alternative to resultIds, combined with it via OR).","type":"array","items":{"type":"string"}},"includeActive":{"type":"boolean","description":"Explicit confirmation: include ACTIVE records (an already-accepted verdict) in the targeted retry over resultIds/companyIds, despite this erasing the card's honest verdict. Without the flag the service silently skips ACTIVE entries from the list. Applies ONLY together with resultIds/companyIds — does not affect statuses (ACTIVE remains unreachable there by any means, see @IsIn above)."},"preview":{"type":"boolean","description":"Read-only preview: return how many rows (and, if cheap, which ids) this same call would select, without running the retry or changing ScoringResult/TaskItem. The journal (active_reset_by_retry) is not written when preview=true."},"contradictoryOnly":{"type":"boolean","description":"Narrow the selection to results where the contradiction flag fired at any step (data.contradictoryFields — a non-empty array). Combined with the other selection conditions (statuses/processedAfter/processedBefore/resultIds/companyIds, includeActive/includeUnavailable) as an additional narrowing (AND), not a replacement for them."}}},"UpdateErrorSettingsDto":{"type":"object","properties":{"reasonClasses":{"type":"array","minItems":1,"description":"Scoring failure classes counted by the configured pause thresholds. Default: platform. Network/material remain visible even when not selected.","items":{"type":"string","enum":["platform","network","material"]}},"consecutiveErrorLimit":{"type":"number","minimum":1,"description":"N consecutive errors → auto-pause"},"errorRatePercent":{"type":"number","description":"Error rate within the window, %"},"errorRateWindowMin":{"type":"number","minimum":1,"description":"Observation window, minutes"},"errorRateMinItems":{"type":"number","minimum":1,"description":"Minimum items before checking the rate"}}},"UpdateTaskMemoryDto":{"type":"object","properties":{"memory":{"type":"string"}},"required":["memory"]},"UpdateAiSettingsDto":{"type":"object","properties":{"provider":{"type":"object","nullable":true,"description":"Provider: hydraai | aitunnel | claude | ldmai"},"models":{"type":"object","description":"Model per call kind, e.g. { scoring: \"...\" }","additionalProperties":{"type":"string"}}}},"UpdateCronSettingsDto":{"type":"object","properties":{"cronEnabled":{"type":"boolean"},"cronInterval":{"type":"number","minimum":1,"description":"Cron interval, minutes"},"batchSize":{"type":"number","minimum":1,"description":"Batch size; the service clamps it to the allowed range"},"rateLimit":{"type":"number","minimum":1},"scoringMode":{"type":"string"}}},"CreateCreativeDto":{"type":"object","properties":{"type":{"type":"string","enum":["EMAIL","ATTACHMENT","VK","TELEGRAM","FORM","PHONE","WHATSAPP","LINKEDIN","AUTOPILOT","AUTOPILOT_V2"]},"autopilotConfig":{"type":"object","nullable":true,"additionalProperties":true,"description":"Autopilot configuration. aiVariables entries may carry requiredInputs and fallback."},"senderMethod":{"type":"string","enum":["NONE","SPINTAX","AI"]},"subjectMethod":{"type":"string","enum":["NONE","SPINTAX","AI"]},"bodyMethod":{"type":"string","enum":["NONE","SPINTAX","AI"]},"name":{"type":"string"},"description":{"type":"string","nullable":true},"isActive":{"type":"boolean"},"subject":{"type":"string","nullable":true},"bodyHtml":{"type":"string","nullable":true},"bodyText":{"type":"string","nullable":true},"messageText":{"type":"string","nullable":true},"formConfig":{"type":"object","nullable":true},"attachmentUrl":{"type":"string","nullable":true,"maxLength":2048},"attachmentName":{"type":"string","nullable":true,"maxLength":255},"attachmentCreativeId":{"type":"string","nullable":true},"variables":{"type":"object","nullable":true},"previewContactId":{"type":"string","nullable":true},"previewCompanyId":{"type":"string","nullable":true},"aiPromptSubject":{"type":"object","nullable":true},"aiPromptBody":{"type":"object","nullable":true},"aiModel":{"type":"string","nullable":true},"aiTemperature":{"type":"number"},"briefId":{"type":"string","nullable":true},"includeDossier":{"type":"boolean"},"formCompanyName":{"type":"string","nullable":true},"formContactName":{"type":"string","nullable":true},"formEmail":{"type":"string","nullable":true},"formPhone":{"type":"string","nullable":true},"formTitle":{"type":"string","nullable":true},"pixelTracking":{"type":"boolean"},"linkTracking":{"type":"boolean"},"unsubscribeLink":{"type":"boolean"}},"required":["type","name"]},"AiGenerateCreativeDto":{"type":"object","properties":{"prompt":{"type":"string","description":"Prompt describing the creative to generate"},"tone":{"type":"string","description":"Desired tone of voice, free text"},"language":{"type":"string","description":"Output language, e.g. \"ru\" or \"en\""},"type":{"type":"string","enum":["email","message"],"description":"Creative kind to generate"},"provider":{"type":"string","description":"AI provider override"},"model":{"type":"string","description":"AI model override"},"temperature":{"type":"number","minimum":0,"maximum":2},"creativeId":{"type":"string","description":"Existing creative to regenerate in place"}},"required":["prompt"]},"UpdateCreativeDto":{"type":"object","properties":{"autopilotConfig":{"type":"object","nullable":true,"additionalProperties":true,"description":"Autopilot configuration. aiVariables entries may carry requiredInputs and fallback."},"name":{"type":"string"},"description":{"type":"string","nullable":true},"isActive":{"type":"boolean"},"subject":{"type":"string","nullable":true},"bodyHtml":{"type":"string","nullable":true},"bodyText":{"type":"string","nullable":true},"messageText":{"type":"string","nullable":true},"formConfig":{"type":"object","nullable":true},"attachmentUrl":{"type":"string","nullable":true,"maxLength":2048},"attachmentName":{"type":"string","nullable":true,"maxLength":255},"attachmentCreativeId":{"type":"string","nullable":true},"variables":{"type":"object","nullable":true},"previewContactId":{"type":"string","nullable":true},"previewCompanyId":{"type":"string","nullable":true},"senderMethod":{"type":"object"},"subjectMethod":{"type":"object"},"bodyMethod":{"type":"object"},"aiPromptSubject":{"type":"object","nullable":true},"aiPromptBody":{"type":"object","nullable":true},"aiModel":{"type":"string","nullable":true},"aiTemperature":{"type":"number"},"briefId":{"type":"string","nullable":true},"includeDossier":{"type":"boolean"},"formCompanyName":{"type":"string","nullable":true},"formContactName":{"type":"string","nullable":true},"formEmail":{"type":"string","nullable":true},"formPhone":{"type":"string","nullable":true},"formTitle":{"type":"string","nullable":true},"pixelTracking":{"type":"boolean"},"linkTracking":{"type":"boolean"},"unsubscribeLink":{"type":"boolean"}}},"PreviewCreativeDto":{"type":"object","properties":{"sampleData":{"type":"object","description":"Sample values keyed by variable name, override for resolved contact/company/lead data"},"seed":{"type":"number","description":"Deterministic seed for spintax/variant resolution"},"companyId":{"type":"string"},"contactId":{"type":"string"},"leadId":{"type":"string"}}},"StartInboxPlacementTestDto":{"type":"object","properties":{"accountId":{"type":"string","description":"Email account the seed letters are sent from. Required: seed reservation is paid, and the platform deliberately does not pick an account for you (#791)."},"providers":{"description":"Seed providers to cover, e.g. [\"gmail\",\"outlook\",\"yandex\"]. Omit for the default set.","type":"array","items":{"type":"string"}},"companyId":{"type":"string","description":"Company used to resolve merge variables while rendering the seed letter"},"contactId":{"type":"string","description":"Contact used to resolve merge variables while rendering the seed letter"},"leadId":{"type":"string","description":"Lead used to resolve merge variables while rendering the seed letter"}},"required":["accountId"]},"TestSendDto":{"type":"object","properties":{"toEmail":{"type":"string","description":"Recipient for sender=\"account\". Omit for sender=\"platform\" to use the tenant owner address."},"companyId":{"type":"string","description":"Company used to resolve template variables"},"contactId":{"type":"string","description":"Contact used to resolve template variables"},"leadId":{"type":"string","description":"Lead used to resolve template variables"},"accountId":{"type":"string","description":"Connected email account used when sender=\"account\""},"sender":{"type":"string","enum":["account","platform"],"default":"account"},"sampleData":{"type":"object","description":"Explicit variable values overriding company/contact/lead data","additionalProperties":{"type":"string"}}}},"VariableNormalizationRuleDto":{"type":"object","properties":{"type":{"type":"string","enum":["regex_replace","truncate","default_if_empty","skip_if_equals","skip_if_matches","ai_normalize"]},"pattern":{"type":"string"},"replacement":{"type":"string"},"maxLength":{"type":"number"},"ellipsis":{"type":"boolean"},"defaultValue":{"type":"string"},"equalsVariable":{"type":"string"},"prompt":{"type":"string"},"model":{"type":"string"},"cacheKey":{"type":"string"}},"required":["type"]},"VariableRuleEntryDto":{"type":"object","properties":{"variable":{"type":"string"},"enabled":{"type":"boolean"},"rules":{"type":"array","items":{"$ref":"#/components/schemas/VariableNormalizationRuleDto"}}},"required":["variable","enabled","rules"]},"SaveVariableRulesDto":{"type":"object","properties":{"variableRules":{"type":"array","items":{"$ref":"#/components/schemas/VariableRuleEntryDto"}}},"required":["variableRules"]},"GeneratePdfMetadataDto":{"type":"object","properties":{"title":{"type":"string"},"author":{"type":"string"},"subject":{"type":"string"},"keywords":{"type":"array","items":{"type":"string"}},"filename":{"type":"string"},"creator":{"type":"string"},"producer":{"type":"string"},"creationDate":{"type":"string"},"modificationDate":{"type":"string"}}},"GeneratePdfDto":{"type":"object","properties":{"async":{"type":"boolean","description":"Return a durable generation handle immediately and poll the PDF generation status endpoint.","default":false},"sampleData":{"type":"object","additionalProperties":{"type":"string"},"description":"Explicit variable values overriding resolved company/contact/lead data."},"companyId":{"type":"string"},"contactId":{"type":"string"},"leadId":{"type":"string"},"format":{"type":"string","enum":["A4","Letter"],"default":"A4"},"landscape":{"type":"boolean","default":false},"pageNumbers":{"type":"boolean","description":"Show page numbers in footer.","default":false},"metadata":{"$ref":"#/components/schemas/GeneratePdfMetadataDto"}}},"ResolveVariablesDto":{"type":"object","properties":{"contactId":{"type":"string"},"recipientEmail":{"type":"string"}},"required":["contactId"]},"TransitionBriefIntakeItemDto":{"type":"object","properties":{"status":{"type":"string","enum":["IN_REVIEW","IGNORED","REJECTED"],"example":"IN_REVIEW"},"reason":{"type":"string","maxLength":500,"example":"Operator reviewed the sender and attachments."},"idempotencyKey":{"type":"string","maxLength":128,"example":"review-intake-item-123-v1"}},"required":["status","reason","idempotencyKey"]},"LinkBriefIntakeItemDto":{"type":"object","properties":{"briefId":{"type":"string","example":"brief-id"},"contactId":{"type":"object","nullable":true,"description":"Existing customer Contact, or null to clear a wrong association."},"companyId":{"type":"object","nullable":true,"description":"Existing customer Company, or null to clear a wrong association."},"reason":{"type":"string","maxLength":500,"example":"Human confirmed that these materials belong to this brief."},"idempotencyKey":{"type":"string","maxLength":128,"example":"link-intake-item-123-to-brief-id-v1"}},"required":["briefId","reason","idempotencyKey"]},"LogBriefIntakeWorkDto":{"type":"object","properties":{"action":{"type":"string","enum":["READ","FACTS_EXTRACTED","CHANGE_PROPOSED","CHANGE_APPLIED","IGNORED","NOTE"]},"reason":{"type":"string","maxLength":500,"example":"Extracted only facts explicitly supported by the cited customer sources."},"details":{"type":"object","additionalProperties":true},"sourceRefs":{"minItems":1,"description":"Required for derived facts/proposals/applied changes; dialog:/dialog-attachment:/intake: refs only.","type":"array","items":{"type":"string"}},"briefId":{"type":"string","example":"brief-id"},"idempotencyKey":{"type":"string","maxLength":128,"example":"intake-item-123-read-v1"}},"required":["action","reason","idempotencyKey"]},"CreateBriefDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"isActive":{"type":"boolean"},"content":{"type":"object","description":"Initial content, validated against brief-content-v1.2 before save."},"variables":{"type":"object"},"locks":{"type":"object","description":"Map of section paths to boolean lock state."},"targetCompanyListId":{"type":"string","nullable":true,"description":"Target company list ID. Can be a string or null."}},"required":["name"]},"UpdateBriefMetaDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"isActive":{"type":"boolean"},"targetCompanyListId":{"type":"object","nullable":true,"description":"#847: целевой список проекта. `null` — снять связь явно.\nБез этого поля читатель (`resolveTargetList`) был бы механизмом без\nвызывающего: связь стала бы исправимой, но не исправленной."},"reason":{"type":"string"}}},"UpdateBriefContentDto":{"type":"object","properties":{"patch":{"type":"object","description":"Partial JSON-merge patch for `content`. Top-level keys whose path is locked (locks[key] === true) are rejected with 423. Merged result is validated against brief-content-v1.2."},"reason":{"type":"string"}},"required":["patch"]},"UpdateBriefVariablesDto":{"type":"object","properties":{"patch":{"type":"object","description":"Partial JSON-merge patch for `variables`."},"reason":{"type":"string"}},"required":["patch"]},"UpdateBriefIntakeAliasDto":{"type":"object","properties":{"alias":{"type":"string","minLength":8,"maxLength":64,"pattern":"/^brief-[a-z0-9](?:[a-z0-9-]*[a-z0-9])$/"}},"required":["alias"]},"CreateEmailAccountDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"},"displayName":{"type":"string"},"signature":{"type":"string"},"notes":{"type":"string"},"smtpHost":{"type":"string"},"smtpPort":{"type":"number","minimum":1},"smtpLogin":{"type":"string"},"smtpPassword":{"type":"string"},"smtpSsl":{"type":"boolean"},"imapHost":{"type":"string"},"imapPort":{"type":"number","minimum":1},"imapLogin":{"type":"string"},"imapPassword":{"type":"string"},"imapSsl":{"type":"boolean"},"imapMode":{"type":"string"},"type":{"type":"object"},"service":{"type":"object"},"provider":{"type":"string","description":"Lower-case provider key (`gmail`, `yandex`, `mailru`, `outlook`, ...).\nNot stored on EmailAccount — service normalizes it to {@link service}\nwhen `service` is not explicitly set."},"status":{"type":"string"},"dailySendLimit":{"type":"number","minimum":0},"hourlySendLimit":{"type":"number","minimum":0},"minSendIntervalSeconds":{"type":"number","minimum":0},"sendMethod":{"type":"string"},"fetchPriority":{"type":"string"},"webPassword":{"type":"string"},"isRelay":{"type":"boolean"},"oauthClientAlias":{"type":"string"},"folderId":{"type":"string"},"profileId":{"type":"string"},"profilePlatform":{"type":"string"},"listId":{"type":"string"},"_confirmDuplicate":{"type":"boolean"}},"required":["email"]},"ImportOauthDto":{"type":"object","properties":{"combo":{"type":"string"},"email":{"type":"string"},"password":{"type":"string"},"refreshToken":{"type":"string"},"clientId":{"type":"string"},"listId":{"type":"string"}}},"ImportOauthBulkDto":{"type":"object","properties":{"combos":{"type":"array","items":{"type":"string"}},"listId":{"type":"string"}},"required":["combos"]},"Buffer":{"type":"object","properties":{}},"CreateInboundRuleDto":{"type":"object","properties":{"name":{"type":"string"},"accountId":{"type":"string"},"toEmail":{"type":"string"},"fromEmail":{"type":"string"},"fromDomain":{"type":"string"},"keywords":{"type":"array","items":{"type":"string"}},"keywordMode":{"type":"string"},"subjectPattern":{"type":"string"},"searchScope":{"type":"array","items":{"type":"string"}},"matchType":{"type":"string"},"aiCriteria":{"type":"string"},"aiModel":{"type":"string"},"pipelineId":{"type":"string"},"stageId":{"type":"string"},"leadTitle":{"type":"string"},"leadSource":{"type":"string"},"leadPriority":{"type":"object"},"linkContact":{"type":"boolean"},"linkDialog":{"type":"boolean"},"createWithoutContact":{"type":"boolean"},"sortOrder":{"type":"number"}},"required":["name","pipelineId"]},"ReorderInboundRulesDto":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}},"items":{"type":"array","items":{"$ref":"#/components/schemas/ReorderItemDto"}}}},"UpdateInboundRuleDto":{"type":"object","properties":{"name":{"type":"string"},"isActive":{"type":"boolean"},"accountId":{"type":"string","nullable":true},"toEmail":{"type":"string","nullable":true},"fromEmail":{"type":"string","nullable":true},"fromDomain":{"type":"string","nullable":true},"keywords":{"type":"array","items":{"type":"string"}},"keywordMode":{"type":"string"},"subjectPattern":{"type":"string","nullable":true},"searchScope":{"type":"array","items":{"type":"string"}},"matchType":{"type":"string"},"aiCriteria":{"type":"string","nullable":true},"aiModel":{"type":"string","nullable":true},"pipelineId":{"type":"string"},"stageId":{"type":"string","nullable":true},"leadTitle":{"type":"string","nullable":true},"leadSource":{"type":"string","nullable":true},"leadPriority":{"type":"object"},"linkContact":{"type":"boolean"},"linkDialog":{"type":"boolean"},"createWithoutContact":{"type":"boolean"},"sortOrder":{"type":"number"}}},"ReapplyInboundRulesDto":{"type":"object","properties":{"pipelineId":{"type":"string"},"fromStageId":{"type":"string"}},"required":["pipelineId","fromStageId"]},"CreateMailRoutingRuleDto":{"type":"object","properties":{"name":{"type":"string"},"accountId":{"type":"string"},"toEmail":{"type":"string"},"fromEmail":{"type":"string"},"fromDomain":{"type":"string"},"subjectPattern":{"type":"string"},"keywords":{"type":"array","items":{"type":"string"}},"keywordMode":{"type":"string"},"searchScope":{"type":"array","items":{"type":"string"}},"matchType":{"type":"string"},"aiCriteria":{"type":"string"},"aiModel":{"type":"string"},"action":{"type":"string"},"targetFolder":{"type":"string"},"forwardTo":{"type":"string"},"markRead":{"type":"boolean"},"stopProcessing":{"type":"boolean"},"sortOrder":{"type":"number"}},"required":["name"]},"UpdateMailRoutingRuleDto":{"type":"object","properties":{"name":{"type":"string"},"isActive":{"type":"boolean"},"accountId":{"type":"string","nullable":true},"toEmail":{"type":"string","nullable":true},"fromEmail":{"type":"string","nullable":true},"fromDomain":{"type":"string","nullable":true},"subjectPattern":{"type":"string","nullable":true},"keywords":{"type":"array","items":{"type":"string"}},"keywordMode":{"type":"string"},"searchScope":{"type":"array","items":{"type":"string"}},"matchType":{"type":"string"},"aiCriteria":{"type":"string","nullable":true},"aiModel":{"type":"string","nullable":true},"action":{"type":"string"},"targetFolder":{"type":"string"},"forwardTo":{"type":"string","nullable":true},"markRead":{"type":"boolean"},"stopProcessing":{"type":"boolean"},"sortOrder":{"type":"number"}}},"CreateViewDto":{"type":"object","properties":{"entity":{"type":"string"},"name":{"type":"string"},"config":{"type":"object"}},"required":["entity","name","config"]},"UpdateViewDto":{"type":"object","properties":{"name":{"type":"string"},"config":{"type":"object"},"isDefault":{"type":"boolean"}}},"UpdateRunDto":{"type":"object","properties":{}},"UpdateRunStepDto":{"type":"object","properties":{}},"CreateTemplateDto":{"type":"object","properties":{}},"UpdateTemplateDto":{"type":"object","properties":{}},"StepDto":{"type":"object","properties":{}},"UpdateStepDto":{"type":"object","properties":{}},"CreateRunDto":{"type":"object","properties":{}},"CreateActivityDto":{"type":"object","properties":{"type":{"type":"string","description":"Activity type"},"subject":{"type":"string","description":"Activity subject"},"description":{"type":"string","description":"Activity description"},"dueDate":{"type":"string","description":"Due date"},"isDone":{"type":"boolean","description":"Is done"},"leadId":{"type":"string","description":"Lead id"},"contactId":{"type":"string","description":"Contact id"},"companyId":{"type":"string","description":"Company id"}},"required":["type"]},"UpdateActivityDto":{"type":"object","properties":{"isDone":{"type":"boolean","description":"Is done"},"subject":{"type":"string","description":"Activity subject"},"description":{"type":"string","description":"Activity description"},"dueDate":{"type":"string","description":"Due date"}}},"RpaCreateKeyDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100}},"required":["name"]},"RpaGlobalAccessDto":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"]},"RpaTraceDto":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"]},"RpaGrantDto":{"type":"object","properties":{"tenantId":{"type":"string","minLength":1,"maxLength":128},"userId":{"type":"string","minLength":1,"maxLength":128},"enabled":{"type":"boolean"}},"required":["tenantId","userId","enabled"]},"AccountTransferPlanDto":{"type":"object","properties":{"sourceEmails":{"minItems":1,"maxItems":10,"type":"array","items":{"type":"string","format":"email"}},"targetEmail":{"type":"string","format":"email"},"resources":{"minItems":1,"maxItems":4,"type":"array","items":{"type":"object"}}},"required":["sourceEmails","targetEmail","resources"]},"AccountTransferApplyDto":{"type":"object","properties":{"sourceEmails":{"minItems":1,"maxItems":10,"type":"array","items":{"type":"string","format":"email"}},"targetEmail":{"type":"string","format":"email"},"resources":{"minItems":1,"maxItems":4,"type":"array","items":{"type":"object"}},"planHash":{"type":"string","minLength":64,"maxLength":64,"pattern":"/^[a-f0-9]{64}$/"},"operationId":{"type":"string","pattern":"/^[a-zA-Z0-9][a-zA-Z0-9._:-]{7,99}$/"},"reason":{"type":"string"}},"required":["sourceEmails","targetEmail","resources","planHash","operationId"]},"AccountTransferDeactivateSourcesDto":{"type":"object","properties":{"sourceEmails":{"minItems":1,"maxItems":10,"type":"array","items":{"type":"string","format":"email"}},"targetEmail":{"type":"string","format":"email"},"reason":{"type":"string"}},"required":["sourceEmails","targetEmail"]},"ConnectInboxCheckTenantDto":{"type":"object","properties":{}},"CreateTestTaskDto":{"type":"object","properties":{"requestKey":{"type":"string","maxLength":200,"description":"Stable retry key; Idempotency-Key header takes precedence when present"},"intendedRecipientId":{"type":"string","maxLength":128,"description":"Existing CampaignRecipient id from this DRAFT campaign"}}},"CampaignPreparationConfigDto":{"type":"object","properties":{"maxInFlight":{"type":"number","description":"Maximum unique unsent touches across preparation, audit and delivery. Not a batch size.","minimum":1,"maximum":50,"default":50},"maxPendingPlacement":{"type":"number","description":"Maximum sent touches awaiting placement feedback before new preparation pauses.","minimum":1,"maximum":50,"default":50}}},"CampaignPacingConfigDto":{"type":"object","properties":{"dailyTarget":{"type":"number","minimum":1,"maximum":1000000,"description":"Maximum unique REAL campaign recipients admitted in the campaign calendar day."},"bestTimeMode":{"type":"string","enum":["advisory"],"default":"advisory","description":"best_send_time is a recommendation; the send point may ignore it to meet the daily target."}}},"CampaignSenderConfigDto":{"type":"object","properties":{"deliveryMode":{"type":"string","enum":["SMTP","RPA","MIX"],"description":"RPA is strict: it never falls back to SMTP. MIX uses the selected eligible relay method."},"senderAssignment":{"type":"string","description":"When to bind a sender. send (default) selects an eligible account at send time with failover; dispatch is an explicit legacy opt-in that pins READY rows in advance.","enum":["send","dispatch"],"default":"send"},"preparation":{"$ref":"#/components/schemas/CampaignPreparationConfigDto"},"pacing":{"$ref":"#/components/schemas/CampaignPacingConfigDto"}}},"CampaignSendWindowDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"true = bounded calendar window; false = explicit 24/7"},"workDays":{"description":"ISO weekdays: 1 Monday … 7 Sunday","type":"array","items":{"type":"number","maximum":7,"minimum":1}},"startTime":{"type":"string","pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d","description":"Local start time, HH:MM"},"endTime":{"type":"string","pattern":"^(?:[01]\\d|2[0-3]):[0-5]\\d","description":"Local end time, HH:MM (exclusive)"},"timezone":{"type":"string","description":"IANA timezone, for example Europe/Moscow"}}},"CreateCampaignDto":{"type":"object","properties":{"name":{"type":"string","description":"Campaign name"},"description":{"type":"string","description":"Campaign description"},"sourceType":{"type":"string","description":"Source type","enum":["API","LIST","CRM_TRIGGER"]},"sourceConfig":{"type":"object","description":"Source configuration"},"creativeIds":{"description":"Creative ids","type":"array","items":{"type":"string"}},"creativeRouting":{"type":"object","description":"Creative routing"},"briefId":{"type":"string","description":"Brief id"},"authorConfig":{"type":"object","description":"Author config"},"auditorConfig":{"type":"object","description":"Auditor config"},"senderConfig":{"description":"Sender config. senderAssignment defaults to send for new campaigns; dispatch must be selected explicitly.","allOf":[{"$ref":"#/components/schemas/CampaignSenderConfigDto"}]},"sendWindow":{"description":"Campaign-owned send window. Omitted fields use the safe initial default; explicit enabled:false means 24/7.","allOf":[{"$ref":"#/components/schemas/CampaignSendWindowDto"}]},"canvas":{"type":"object","description":"Canvas config"},"renderMode":{"type":"string","description":"Render mode","enum":["PLATFORM","BYOC"]}},"required":["name"]},"MoveRecipientsStageFilterDto":{"type":"object","properties":{"stage":{"type":"string"},"search":{"type":"string"},"canvasStage":{"type":"string"},"finalStatus":{"type":"string"},"emailValid":{"type":"string"},"auditLevel":{"type":"string"},"inboxPlacement":{"type":"string"},"sentFrom":{"type":"string"},"sentTo":{"type":"string"}}},"MoveRecipientsStageDto":{"type":"object","properties":{"toStage":{"type":"string","description":"Целевая стадия канваса: STEP:n | WAIT:n | COMPLETED | STOPPED | __none__"},"recipientIds":{"type":"array","items":{"type":"string"}},"filter":{"$ref":"#/components/schemas/MoveRecipientsStageFilterDto"}},"required":["toStage"]},"RerenderRecipientsDto":{"type":"object","properties":{"recipientIds":{"type":"array","items":{"type":"string"}},"stages":{"type":"array","items":{"type":"string"}},"force":{"type":"boolean","description":"#531: явный грант нового окна платных аудит-попыток"}}},"RepairUnsubscribeDto":{"type":"object","properties":{"recipientIds":{"type":"array","items":{"type":"string"}},"stages":{"type":"array","items":{"type":"string"}}}},"PourCampaignDto":{"type":"object","properties":{"listId":{"type":"string","description":"Contact-list id; required unless allContacts:true (#565)"},"allContacts":{"type":"boolean","description":"Pour to all contacts"},"companyListId":{"type":"string","description":"#1221: Company-list id — pour live contacts of ALL companies in this COMPANY list (not a contact list). Mutually exclusive with listId/allContacts."}}},"PushAttachmentDto":{"type":"object","properties":{"filename":{"type":"string"},"contentBase64":{"type":"string"},"contentType":{"type":"string"}}},"PushRowDto":{"type":"object","properties":{"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"contactId":{"type":"string"},"companyId":{"type":"string"},"leadId":{"type":"string"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/PushAttachmentDto"}}}},"PushContactsDto":{"type":"object","properties":{"rows":{"type":"array","items":{"$ref":"#/components/schemas/PushRowDto"}}},"required":["rows"]},"PourFromLeadsDto":{"type":"object","properties":{"pipelineId":{"type":"string"},"stageId":{"type":"string"},"interestStatus":{"type":"string"},"limit":{"type":"number"}}},"UpdateCampaignDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"status":{"type":"string","enum":["DRAFT","ACTIVE","PAUSED","DONE","ERROR"]},"sourceType":{"type":"string","enum":["API","LIST","CRM_TRIGGER"]},"sourceConfig":{"type":"object"},"creativeIds":{"type":"array","items":{"type":"string"}},"creativeRouting":{"type":"object"},"briefId":{"type":"object","nullable":true},"authorConfig":{"type":"object"},"auditorConfig":{"type":"object"},"senderConfig":{"nullable":true,"description":"Partial sender config. Changing dispatch→send atomically unpins sender/From only for READY rows and preserves scheduledAt; SENDING/SENT/outbox are never rewritten.","allOf":[{"$ref":"#/components/schemas/CampaignSenderConfigDto"}]},"sendWindow":{"nullable":true,"description":"Partial campaign-owned send-window patch. Omitted fields are preserved; null is rejected. enabled:false is explicit 24/7.","allOf":[{"$ref":"#/components/schemas/CampaignSendWindowDto"}]},"canvas":{"type":"object"},"groupId":{"type":"object","nullable":true},"renderMode":{"type":"string","enum":["PLATFORM","BYOC"]},"acknowledgeUngroundedAudience":{"type":"boolean","description":"Explicit acknowledgement for a high ungrounded-audience ratio."}}},"SubmitRenderedContentItemDto":{"type":"object","properties":{"recipientId":{"type":"string"},"subject":{"type":"string"},"bodyHtml":{"type":"string"},"bodyText":{"type":"string"}},"required":["recipientId","subject"]},"SubmitRenderedContentDto":{"type":"object","properties":{"items":{"description":"batch <=100, bodyHtml <=256KB","type":"array","items":{"$ref":"#/components/schemas/SubmitRenderedContentItemDto"}}},"required":["items"]},"CampaignPreparationRequestDto":{"type":"object","properties":{"limit":{"type":"number","minimum":1,"maximum":50,"description":"Requested preparation batch, bounded by remaining preparation and relay capacity.","default":50}}},"RestoreInfraFailedDto":{"type":"object","properties":{"dryRun":{"type":"boolean","description":"По умолчанию true — только показать, кого вернёт (#765)"}}},"PauseCampaignDto":{"type":"object","properties":{"reason":{"type":"string","description":"Идёт в событие PAUSED в ленте кампании (#514)"}}},"BestSendTimeDto":{"type":"object","properties":{"contactId":{"type":"string"},"leadId":{"type":"string"},"dossier":{"type":"object","description":"Pre-built dossier (same shape as LeadsService.getDossier returns)."},"dialogId":{"type":"string","description":"If provided, enables Tier 0 (\"mirror reply time\"): the analyzer reads this\ninbound dialog's createdAt, projects its (weekday, hour, minute) into the\ncontact's local TZ, and returns the next future occurrence of that slot.\nFalls back to lower tiers when the dialog is auto-reply / non-email / OUT.\nCombine with contactId/leadId to also fetch the dossier for TZ resolution."},"now":{"type":"string","description":"Optional reference moment (ISO). Used as \"now\" when computing the next\nTue/Wed/Thu × hour slot. Defaults to current time. Useful for tests and\nfor asking \"what would best-send-time recommend if I asked yesterday\"."}}},"AgentGuideOverridesDto":{"type":"object","properties":{"domains":{"type":"object","description":"Domain overrides"},"operations":{"type":"object","description":"Operation overrides"},"controllerDomain":{"type":"object","description":"Controller-domain override"}}},"DetectFormsDto":{"type":"object","properties":{"html":{"type":"string"},"pageUrl":{"type":"string","maxLength":2000}},"required":["html"]},"CreateSiteEnrichmentTaskDto":{"type":"object","properties":{"companyIds":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string"}},"listId":{"type":"string","maxLength":100},"domainField":{"type":"string","maxLength":150},"limit":{"type":"number","minimum":1,"maximum":500},"timeoutMs":{"type":"number","minimum":1000,"maximum":120000},"maxAttempts":{"type":"number","minimum":1,"maximum":5},"saveScreenshot":{"type":"boolean"},"loadImages":{"type":"boolean"},"pageConcurrency":{"type":"number","minimum":1,"maximum":4},"visitPages":{"type":"object"},"scoringTaskId":{"type":"string","maxLength":100}}},"CreateAgentNoteDto":{"type":"object","properties":{"text":{"type":"string","maxLength":4000}},"required":["text"]},"CreateIssueFromFindingDto":{"type":"object","properties":{"projectId":{"type":"string","pattern":"/^\\d+$/"}},"required":["projectId"]},"AppendJournalFindingDto":{"type":"object","properties":{"line":{"type":"string","minLength":1,"maxLength":500}},"required":["line"]},"SetPausedDto":{"type":"object","properties":{"paused":{"type":"boolean"},"projectId":{"type":"string","pattern":"/^\\d+$/"}},"required":["paused"]},"PriorityTriageDto":{"type":"object","properties":{"dryRun":{"type":"boolean","description":"Preview the plan only, no write to GitLab"},"projectId":{"type":"string","description":"GitLab project ID (defaults to primary)"}}},"SetPriorityDto":{"type":"object","properties":{"priority":{"type":"object"},"projectId":{"type":"string","pattern":"/^\\d+$/"}},"required":["priority"]},"SetModelDto":{"type":"object","properties":{"model":{"type":"object"},"projectId":{"type":"string","pattern":"/^\\d+$/"}},"required":["model"]},"ProjectScopedDto":{"type":"object","properties":{"projectId":{"type":"string","pattern":"/^\\d+$/"}}},"CreateConveyorIssueDto":{"type":"object","properties":{"description":{"type":"string","minLength":1},"priority":{"type":"string"},"slug":{"type":"string"}},"required":["description"]},"SetConveyorPriorityDto":{"type":"object","properties":{"priority":{"type":"string"}},"required":["priority"]},"SetConveyorPausedDto":{"type":"object","properties":{"paused":{"type":"boolean"}},"required":["paused"]},"ConveyorIssueActionDto":{"type":"object","properties":{"action":{"type":"object"}},"required":["action"]},"CreateManualBlockRuleDto":{"type":"object","properties":{"relayAccountId":{"type":"string","description":"Relay EmailAccount id (isRelay=true) within the tenant"},"provider":{"type":"string","description":"Canonical name of the recipient provider. A domain (\"gmail.com\") or an address (\"lead@gmail.com\") is accepted and canonicalized; an unknown value → 400.","example":"gmail"},"category":{"type":"string","enum":["cannot_deliver","should_not_send","marginal"],"default":"should_not_send"},"reason":{"type":"string","description":"Sub-code; defaults to \"manual\"","default":"manual"},"expiresAtIso":{"type":"object","nullable":true,"description":"ISO time of auto-release; null/absent = indefinite"},"campaignId":{"type":"string","description":"#509: attribute the block to this campaign in the feed"}},"required":["relayAccountId","provider"]},"ExportParamsDto":{"type":"object","properties":{"taskId":{"type":"string","description":"mailing_csv: обязателен — воркер бросает `taskId is required` без него.","pattern":"UUID_SHAPE"},"listId":{"type":"string","description":"contacts_csv / companies_csv: идентификатор списка — строка, не число.","pattern":"UUID_SHAPE"},"status":{"type":"string"},"entity":{"type":"object","description":"entity_table: воркер сам проверяет этот набор — держим его в ОДНОМ месте."},"columns":{"minItems":1,"type":"array","items":{"type":"string"}},"filters":{"type":"object"}}},"CreateExportDto":{"type":"object","properties":{"type":{"type":"string","description":"Export type","enum":["mailing_csv","contacts_csv","companies_csv","entity_table","combined"],"example":"contacts_csv"},"params":{"description":"Export parameters, dependent on the type","allOf":[{"$ref":"#/components/schemas/ExportParamsDto"}]}},"required":["type"]},"A2ABodyDto":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"],"description":"JSON-RPC 2.0 protocol marker"},"id":{"type":"object","description":"Request id: string, number, or null (JSON-RPC 2.0)","nullable":true},"method":{"type":"string","description":"A2A JSON-RPC method, e.g. message/send, tasks/get, tasks/cancel"},"params":{"type":"object","description":"Method-specific params object"}},"required":["jsonrpc","id","method"]},"CreateIcpTaskDto":{"type":"object","properties":{"title":{"type":"string","description":"ICP task title"},"description":{"type":"string"},"config":{"type":"object","description":"Free-form configuration payload"}},"required":["title"]},"ScrapeCompaniesDto":{"type":"object","properties":{"companyIds":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string"}},"listId":{"type":"string","maxLength":100},"domainField":{"type":"string","maxLength":150},"limit":{"type":"number","minimum":1,"maximum":200},"timeoutMs":{"type":"number","minimum":1000,"maximum":120000},"maxAttempts":{"type":"number","minimum":1,"maximum":5},"saveScreenshot":{"type":"boolean"},"loadImages":{"type":"boolean"},"pageConcurrency":{"type":"number","minimum":1,"maximum":4},"visitPages":{"type":"object"},"scoringTaskId":{"type":"string","maxLength":100}}},"UpdateIcpTaskDto":{"type":"object","properties":{"title":{"type":"string","description":"ICP task title"},"description":{"type":"string"},"status":{"type":"string","description":"ICP task status"},"config":{"type":"object","description":"Free-form configuration payload"}}},"ExtractRuleDto":{"type":"object","properties":{"type":{"type":"object"},"keywords":{"type":"array","items":{"type":"string"}},"matchMode":{"type":"object"},"caseSensitive":{"type":"boolean"},"pattern":{"type":"string","maxLength":300},"query":{"type":"string","maxLength":2000},"promptOverride":{"type":"string","maxLength":8000}},"required":["type"]},"CustomExtractRequestDto":{"type":"object","properties":{"material":{"type":"string"},"rule":{"$ref":"#/components/schemas/ExtractRuleDto"},"context":{"type":"string","maxLength":100},"contextId":{"type":"string","maxLength":200}},"required":["rule"]},"DetectTemplateDto":{"type":"object","properties":{"headers":{"description":"CSV/sheet column headers to match against known templates","type":"array","items":{"type":"string"}}},"required":["headers"]},"ApplyTemplateDto":{"type":"object","properties":{"templateId":{"type":"string","description":"Id of the template to apply"},"headers":{"description":"CSV/sheet column headers to map via the template","type":"array","items":{"type":"string"}}},"required":["templateId","headers"]},"ImportTaskConfigDto":{"type":"object","properties":{"sourceType":{"type":"string","enum":["csv","google-sheets"]},"sourceUrl":{"type":"string"},"entity":{"type":"string","enum":["companies","contacts"]},"combinedMode":{"type":"boolean","description":"Combined companies + contacts import mode"},"sourceFileId":{"type":"string","description":"Library file id — alternative to inline headers/rows (#805 B3)"},"headers":{"description":"CSV/sheet column headers. Pass [] when using sourceFileId.","type":"array","items":{"type":"string"}},"rows":{"description":"CSV/sheet rows, each an array of cell values. Pass [] when using sourceFileId.","type":"array","items":{"type":"string"}},"templateId":{"type":"string"},"mapping":{"type":"object","description":"Column -> field mapping (csvColumn -> target field). Contact fields are prefixed with \"c:\" (e.g. \"c:firstName\", \"c:email\", \"c:phone\"). Company fields have no prefix (e.g. \"name\", \"domain\", \"industry\"). Custom fields use \"customField:\". An unknown value (e.g. bare \"email\" instead of \"c:email\", or \"cf:key\" — a prefix from a DIFFERENT import path) is rejected with 400 BEFORE the task is queued (#1064)."},"transforms":{"type":"object","description":"Per-column value transforms"},"listId":{"type":"string","description":"Company-list id for company-only or combined-mode imports"},"contactListId":{"type":"string","description":"Contact-list id for combined-mode imports (company list goes in listId)"},"newListName":{"type":"string"},"createLeads":{"type":"boolean","description":"Also create a lead per imported row"},"pipelineId":{"type":"string"},"newPipelineName":{"type":"string"},"stageId":{"type":"string"},"leadTitleTemplate":{"type":"string"},"leadPriority":{"type":"string"},"leadSource":{"type":"string"},"duplicateHandling":{"type":"string","enum":["skip","update","mark_duplicate","create"]},"deduplicateBy":{"type":"string","enum":["domain","name","email","both","socials"]},"tagIds":{"type":"array","items":{"type":"string"}},"userId":{"type":"string"}},"required":["sourceType","entity","combinedMode","headers","rows","templateId","mapping","transforms","createLeads","duplicateHandling","deduplicateBy"]},"ImportFromUrlDto":{"type":"object","properties":{"url":{"type":"string","description":"Google Sheets URL or a direct .csv/.xlsx URL"},"listId":{"type":"string","description":"Tenant file library id — save the fetched file there too"}},"required":["url"]},"GenerateOverridesDto":{"type":"object","properties":{"subjectPrompt":{"type":"string"},"bodyPrompt":{"type":"string"},"model":{"type":"string"},"temperature":{"type":"number","minimum":0,"maximum":2}}},"GenerateRequestDto":{"type":"object","properties":{"contactId":{"type":"string"},"source":{"type":"string"},"overrides":{"$ref":"#/components/schemas/GenerateOverridesDto"},"saveAsVersion":{"type":"boolean"}},"required":["contactId"]},"QcConfigDto":{"type":"object","properties":{"tier1":{"type":"object"},"tier2":{"type":"object"}},"required":["tier1","tier2"]},"PipelineTaskEventDto":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"tier":{"type":"string"},"round":{"type":"number"},"branch":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","slug","title","status"]},"PipelineStepEventDto":{"type":"object","properties":{"id":{"type":"string"},"taskId":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"startedAt":{"type":"string"},"finishedAt":{"type":"string"},"exitCode":{"type":"number"},"meta":{"type":"object"}},"required":["id","taskId","kind","name","status"]},"PipelineLogEventDto":{"type":"object","properties":{"stepId":{"type":"string"},"ts":{"type":"string"},"level":{"type":"string"},"message":{"type":"string"}},"required":["stepId","level","message"]},"PipelineFileEventDto":{"type":"object","properties":{"name":{"type":"string"},"content":{"type":"string"}},"required":["name","content"]},"PipelineEventDto":{"type":"object","properties":{"type":{"type":"object"},"task":{"$ref":"#/components/schemas/PipelineTaskEventDto"},"step":{"$ref":"#/components/schemas/PipelineStepEventDto"},"log":{"$ref":"#/components/schemas/PipelineLogEventDto"},"file":{"$ref":"#/components/schemas/PipelineFileEventDto"}},"required":["type"]}}}}