{"openapi":"3.0.0","paths":{"/":{"get":{"operationId":"AppController_getHello","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"string"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Health"],"summary":"Health Check"}},"/health":{"get":{"operationId":"HealthController_getLiveness","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"object"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Health"],"summary":"Get Liveness"}},"/health/ready":{"get":{"operationId":"HealthController_getReadiness","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"object"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Health"],"summary":"Get Readiness"}},"/organization":{"get":{"operationId":"OrganizationController_getById","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/OrganizationResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Get Organization By ID"},"patch":{"operationId":"OrganizationController_update","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Deliberately NO @RequireEntitlement spec — same reasoning as the billing\nroutes: completing the organization profile is the FIRST onboarding step\n(`business_profile`) and must be reachable before a plan is ever bought.\nA bare `requiresWrite: true` gate made this fail with 50005\n(SUBSCRIPTION_NOT_FOUND) for every brand-new org, since the guard cannot\nresolve an entitlement for an org the billing runtime has never seen.\n\nNothing here is metered: the update writes org fields and invalidates two\ncaches, and the logo is a bounded single-file replace with no storage\ndebit. Authorization is unchanged — `organization:update` still applies.","tags":["Organization"]},"post":{"operationId":"OrganizationController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrganizationDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CreateOrganizationResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Create an additional organization from the org switcher. Owner-only, per\nthe permission catalog. Signup is unaffected — registration creates the\nfirst organization through `OrganizationService.create` directly, not\nthrough this route.","tags":["Organization"]}},"/organization/all":{"get":{"operationId":"OrganizationController_getAll","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The organizations this user belongs to — the org switcher's own list.\nDeliberately not permission-gated: it is scoped to the caller's own\nmemberships, and gating it on `organization:read` would strand a member\nwhose current org denies that permission with no way to switch out.","tags":["Organization"]}},"/organization/sample-data":{"get":{"operationId":"OrganizationController_getSampleDataStatus","parameters":[],"responses":{"200":{"description":"Whether the org still has sample data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Whether this org still holds day-one sample data — drives the \"Remove\nsample data\" banner. Any member may read it; it leaks nothing.","tags":["Organization"]},"delete":{"operationId":"OrganizationController_removeSampleData","parameters":[],"responses":{"200":{"description":"Sample data removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Delete the seeded sample data. Hard delete, and irreversible — but it only\never touches rows the seeder created (`isSample = true`), never anything\nthe user made. Owner-only, same permission as editing the org itself.","tags":["Organization"]}},"/organization/switch":{"post":{"operationId":"OrganizationController_switch","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SwitchOrganizationDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Switch Organization"}},"/organization/contact-card":{"get":{"operationId":"ContactCardController_get","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ContactCardResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Get the organization's contact card","tags":["Organization — Contact Card"]},"put":{"operationId":"ContactCardController_save","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactCardDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ContactCardResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Save the contact card and regenerate its vCard","tags":["Organization — Contact Card"]}},"/organization/business-hours":{"get":{"operationId":"OrganizationBusinessHoursController_get","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/OrganizationBusinessHoursResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Get the organization's business hours and current open/closed state","tags":["Organization — Business Hours"]},"put":{"operationId":"OrganizationBusinessHoursController_save","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrganizationBusinessHoursDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/OrganizationBusinessHoursResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Replace the organization's weekly hours and date overrides","tags":["Organization — Business Hours"]}},"/role":{"post":{"operationId":"RoleController_createRole","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRoleDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Create Role"},"get":{"operationId":"RoleController_getRoles","parameters":[{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":40,"type":"number"}},{"name":"excludeOwner","required":false,"in":"query","description":"When `true`, the OWNER system role is filtered out of results.\nUsed by the invite drawer and change-role dropdowns where Owner\nis intentionally not assignable.","schema":{"type":"boolean"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Get Roles"}},"/role/permissions/me":{"get":{"operationId":"RoleController_getMyPermissions","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Effective permissions for the currently authenticated user — used by\nthe frontend to gate UI elements (sidebar items, action buttons, etc).\nRequires only authentication, not a specific permission.","tags":["Organization"]}},"/role/{id}":{"get":{"operationId":"RoleController_getRoleById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Get Role By ID"},"patch":{"operationId":"RoleController_updateRole","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRoleDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Update Role"},"delete":{"operationId":"RoleController_deleteRole","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Delete Role"}},"/role/{id}/members":{"get":{"operationId":"RoleController_getRoleMembers","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Get Role Members"}},"/role/transfer-ownership":{"post":{"operationId":"RoleController_transferOwnership","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferOwnershipDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Hand the OWNER role to another member (caller steps down to ADMIN).\nGated on `organization:update` — an OWNER-only permission — and the\nservice re-verifies the caller's LIVE role is the system OWNER.","tags":["Organization"]}},"/role/assign":{"patch":{"operationId":"RoleController_assign","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignRoleDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Assign Role"}},"/role/member":{"delete":{"operationId":"RoleController_removeMember","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveMemberDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Remove Member"}},"/billing/subscription":{"get":{"operationId":"BillingController_getSubscription","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Local display snapshot — works even when the SA is briefly down.","tags":["Billing"]}},"/billing/entitlements":{"get":{"operationId":"BillingController_getEntitlements","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Micro-cached effective entitlement (R1).","tags":["Billing"]}},"/billing/usage":{"get":{"operationId":"BillingController_getUsage","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Live one-call billing page (B1). Each resource entry is stamped with\nthe product-side `isEnforced` flag — the SA knows the limit, but only\nthe product knows whether the key is live in BILLING_ENFORCED_RESOURCES.","tags":["Billing"]}},"/billing/limits":{"get":{"operationId":"BillingController_getLimits","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Slim per-resource limits for pervasive UI gating. Deliberately carries\nNO @RequirePermissions — every authenticated org member may read it\n(precedent: GET /user in user.controller.ts; the global Auth +\nActiveMembership guards still apply). Exposes only limit/used/remaining\nper resource — no prices, invoices, wallet or subscription state — so\nthe pre-emptive limit-lock works for roles without billing:read.","tags":["Billing"]}},"/billing/usage/history":{"get":{"operationId":"BillingController_getUsageHistory","parameters":[{"name":"resource","required":false,"in":"query","schema":{"type":"string"}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Ledger-backed usage history (B2).","tags":["Billing"]}},"/billing/usage/daily":{"get":{"operationId":"BillingController_getUsageDaily","parameters":[{"name":"resource","required":false,"in":"query","schema":{"maxLength":80,"type":"string"}},{"name":"days","required":false,"in":"query","schema":{"minimum":1,"maximum":90,"type":"number"}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Ledger daily aggregates for the usage trend chart (B7).","tags":["Billing"]}},"/billing/invoices":{"get":{"operationId":"BillingController_getInvoices","parameters":[{"name":"cursor","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Live Stripe invoice list (B6) — cursor paging, not page numbers.","tags":["Billing"]}},"/billing/credits":{"get":{"operationId":"BillingController_getCredits","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Wallet section of the live summary (B1).","tags":["Billing"]}},"/billing/credits/transactions":{"get":{"operationId":"BillingController_getCreditTransactions","parameters":[{"name":"page","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Credit transaction history (B3).","tags":["Billing"]}},"/billing/add-ons":{"get":{"operationId":"BillingController_getAddOns","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Purchasable + active add-ons (B4).","tags":["Billing"]}},"/billing/plans":{"get":{"operationId":"BillingController_getPlans","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Plans this org may see/purchase — B5 private-plan visibility rule.","tags":["Billing"]}},"/billing/subscription/checkout":{"post":{"operationId":"BillingController_checkoutSubscription","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionCheckoutDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Billing"],"summary":"Checkout Subscription"}},"/billing/add-ons/{key}/checkout":{"post":{"operationId":"BillingController_checkoutAddOn","parameters":[{"name":"key","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddOnCheckoutDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Billing"],"summary":"Checkout Add On"}},"/billing/subscription/cancel":{"post":{"operationId":"BillingController_cancelSubscription","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Cancel at period end (P10) — stays active until currentPeriodEnd.","tags":["Billing"]}},"/billing/subscription/reactivate":{"post":{"operationId":"BillingController_reactivateSubscription","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Undo a pending cancellation before the period ends (P10).","tags":["Billing"]}},"/billing/portal":{"post":{"operationId":"BillingController_createPortalSession","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingPortalDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Stripe billing portal (P8) — change/cancel plan, update card, invoices.","tags":["Billing"]}},"/billing/add-ons/{key}/purchase":{"post":{"operationId":"BillingController_purchaseAddOn","parameters":[{"name":"key","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddOnPurchaseDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Off-session add-on purchase (P9) — charges the saved card with no\nredirect. Returns {status:'PAID'} (grant lands via the SA webhook) or\n{status:'REQUIRES_ACTION', checkoutUrl} when the card needs 3-D Secure /\nno card is saved, so the frontend can fall back to a hosted checkout.","tags":["Billing"]}},"/billing/add-ons/{key}/auto-refill":{"post":{"operationId":"BillingController_updateAutoRefill","parameters":[{"name":"key","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoRefillUpdateDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Manage the threshold auto-refill policy for a purchased add-on (P9).","tags":["Billing"]}},"/billing/credits/checkout":{"post":{"operationId":"BillingController_checkoutCredits","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditPackCheckoutDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Billing"],"summary":"Checkout Credits"}},"/user":{"get":{"operationId":"UserController_getMe","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/UserResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Users"],"summary":"Get Current User"},"patch":{"operationId":"UserController_update","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Users"],"summary":"Update User"},"delete":{"operationId":"UserController_remove","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Users"],"summary":"Delete User"}},"/user/all":{"get":{"operationId":"UserController_getAll","parameters":[{"name":"search","required":false,"in":"query","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","INACTIVE","SUSPENDED"]}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["firstName","lastName","email","status","createdAt","updatedAt"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"populate","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["memberships"]}}},{"name":"includeOwners","required":false,"in":"query","description":"Include OWNER-role members, who are otherwise hidden from non-owners.\n\nThat exclusion exists so non-owners can't *manage* owners from the user\nadmin screens. It is wrong for read-only pickers: an IVR \"Ring Teammates\"\nconfig can already name the owner's id, and hiding them from the roster\nonly meant the UI rendered a raw UUID it couldn't resolve to a name.","schema":{"type":"boolean"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/UserResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Users"],"summary":"List Users"}},"/user/password":{"patch":{"operationId":"UserController_changePassword","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Users"],"summary":"Change Password"}},"/notifications":{"get":{"operationId":"NotificationsController_list","parameters":[{"name":"type","required":false,"in":"query","schema":{"type":"string","enum":["MESSAGE","ALERT"]}},{"name":"unreadOnly","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"cursor","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":50,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/NotificationListResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List notifications","tags":["Notifications"]}},"/notifications/unread-count":{"get":{"operationId":"NotificationsController_unreadCount","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/UnreadCountsResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get unread notification counts","tags":["Notifications"]}},"/notifications/sync":{"get":{"operationId":"NotificationsController_sync","parameters":[{"name":"since","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/NotificationSyncResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Sync notifications since a timestamp","tags":["Notifications"]}},"/notifications/{id}/read":{"post":{"operationId":"NotificationsController_markRead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Mark a notification read","tags":["Notifications"]}},"/notifications/read-all":{"post":{"operationId":"NotificationsController_markAllRead","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkReadDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/MarkAllReadResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Mark all notifications read","tags":["Notifications"]}},"/organizations/me/staff-notifications":{"get":{"operationId":"StaffNotificationSettingsController_get","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Get the team's alert settings (shared by every AI employee)","tags":["Staff notifications"]},"put":{"operationId":"StaffNotificationSettingsController_update","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStaffNotificationsDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Save the team's alert settings (shared by every AI employee)","tags":["Staff notifications"]}},"/public/email-preferences/unsubscribe":{"get":{"operationId":"PublicEmailPreferencesController_unsubscribe","parameters":[{"name":"token","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Email Preferences"],"summary":"Unsubscribe Public Email Preference"}},"/opt-out/keywords":{"get":{"operationId":"OptOutController_listKeywords","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":64,"type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","keyword"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-Out"],"summary":"List Keywords"},"post":{"operationId":"OptOutController_createKeyword","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOptOutKeywordDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-Out"],"summary":"Create Keyword"}},"/opt-out/reply-message":{"get":{"operationId":"OptOutController_getReplyMessage","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-Out"],"summary":"Get Reply Message"},"patch":{"operationId":"OptOutController_updateReplyMessage","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReplyMessageDto"}}}},"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-Out"],"summary":"Update Reply Message"}},"/opt-out/keywords/{id}":{"patch":{"operationId":"OptOutController_updateKeyword","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOptOutKeywordDto"}}}},"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-Out"],"summary":"Update Keyword"},"delete":{"operationId":"OptOutController_deleteKeyword","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-Out"],"summary":"Delete Keyword"}},"/opt-out/provider-sync-status":{"get":{"operationId":"OptOutController_getProviderSyncStatus","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-Out"],"summary":"Get Provider Sync Status"}},"/opt-out/provider-sync-status/resync":{"post":{"operationId":"OptOutController_resyncProviderStatus","parameters":[],"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-Out"],"summary":"Resync Provider Status"}},"/contacts":{"post":{"operationId":"ContactsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Create Contact"},"get":{"operationId":"ContactsController_findAll","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"name","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"phone","required":false,"in":"query","schema":{"maxLength":50,"type":"string"}},{"name":"email","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["ACTIVE","INVALID","ARCHIVED"]}}},{"name":"source","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["TEXT_LINK","JOIN_KEYWORD","CSV_IMPORT","MANUAL","WEB_FORM","INBOUND_SMS","INBOUND_CALL","GOOGLE_ADS","META_ADS","INBOUND_EMAIL","INBOUND_WHATSAPP","LEAD_FORM","WEB_CHAT"]}}},{"name":"stage","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["ARCHIVED","NEW_LEAD","ENGAGED","QUALIFIED","APPOINTMENT_BOOKED","CUSTOMER","LOST","BOOKING_PENDING","ESTIMATE_GIVEN","DECIDING","NOT_QUALIFIED"]}}},{"name":"leadScore","required":false,"in":"query","description":"Hot / Warm / Cold — e.g. `?leadScore=HOT` for the \"Hot leads\" filter.","schema":{"type":"array","items":{"type":"string","enum":["HOT","WARM","COLD"]}}},{"name":"isOptedOut","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"emailSubscribed","required":false,"in":"query","description":"EMAIL subscription state — deliberately SEPARATE from `isOptedOut`, which\nis the SMS opt-out flag. A contact can be reachable by SMS and\nunsubscribed from email, or the reverse; collapsing them would silently\nfilter out contacts the user still wants.\n\n`true` = still emailable, `false` = on the org's suppression list.","schema":{"type":"boolean"}},{"name":"optedOutChannel","required":false,"in":"query","description":"Opted out: `ALL_CHANNELS` (= `isOptedOut`, the global opt-out), `WHATSAPP`\n(`whatsappOptIn === false`, set by a WhatsApp STOP) or `ANY`.","schema":{"type":"string","enum":["ANY","ALL_CHANNELS","WHATSAPP"]}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"sample","required":false,"in":"query","description":"`sample=1` (or `true`) → only sample-data contacts.","schema":{"type":"boolean"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"excludeSegmentId","required":false,"in":"query","description":"Hide contacts that are already members of this segment. Used by the\nsegment \"Add Contacts\" picker so an existing member can't be selected\nand re-added (the insert is idempotent, but offering it reads as a bug).","schema":{"format":"uuid","type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","firstName","lastName","phone","email","status","leadScore"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"customFieldFilters","required":false,"in":"query","description":"Custom-field filters (module-builder bridge), passed as a JSON-encoded\narray keyed by field name, e.g.\n`?customFieldFilters=[{\"field\":\"company\",\"operator\":\"contains\",\"value\":\"acme\"}]`.\nUnknown fields/operators are ignored by the resolver.","schema":{"type":"array","items":{"$ref":"#/components/schemas/Object"}}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"List Contacts"}},"/contacts/ids":{"get":{"operationId":"ContactsController_getAllIds","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"name","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"phone","required":false,"in":"query","schema":{"maxLength":50,"type":"string"}},{"name":"email","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["ACTIVE","INVALID","ARCHIVED"]}}},{"name":"source","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["TEXT_LINK","JOIN_KEYWORD","CSV_IMPORT","MANUAL","WEB_FORM","INBOUND_SMS","INBOUND_CALL","GOOGLE_ADS","META_ADS","INBOUND_EMAIL","INBOUND_WHATSAPP","LEAD_FORM","WEB_CHAT"]}}},{"name":"stage","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["ARCHIVED","NEW_LEAD","ENGAGED","QUALIFIED","APPOINTMENT_BOOKED","CUSTOMER","LOST","BOOKING_PENDING","ESTIMATE_GIVEN","DECIDING","NOT_QUALIFIED"]}}},{"name":"leadScore","required":false,"in":"query","description":"Hot / Warm / Cold — e.g. `?leadScore=HOT` for the \"Hot leads\" filter.","schema":{"type":"array","items":{"type":"string","enum":["HOT","WARM","COLD"]}}},{"name":"isOptedOut","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"emailSubscribed","required":false,"in":"query","description":"EMAIL subscription state — deliberately SEPARATE from `isOptedOut`, which\nis the SMS opt-out flag. A contact can be reachable by SMS and\nunsubscribed from email, or the reverse; collapsing them would silently\nfilter out contacts the user still wants.\n\n`true` = still emailable, `false` = on the org's suppression list.","schema":{"type":"boolean"}},{"name":"optedOutChannel","required":false,"in":"query","description":"Opted out: `ALL_CHANNELS` (= `isOptedOut`, the global opt-out), `WHATSAPP`\n(`whatsappOptIn === false`, set by a WhatsApp STOP) or `ANY`.","schema":{"type":"string","enum":["ANY","ALL_CHANNELS","WHATSAPP"]}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"sample","required":false,"in":"query","description":"`sample=1` (or `true`) → only sample-data contacts.","schema":{"type":"boolean"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"excludeSegmentId","required":false,"in":"query","description":"Hide contacts that are already members of this segment. Used by the\nsegment \"Add Contacts\" picker so an existing member can't be selected\nand re-added (the insert is idempotent, but offering it reads as a bug).","schema":{"format":"uuid","type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","firstName","lastName","phone","email","status","leadScore"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"customFieldFilters","required":false,"in":"query","description":"Custom-field filters (module-builder bridge), passed as a JSON-encoded\narray keyed by field name, e.g.\n`?customFieldFilters=[{\"field\":\"company\",\"operator\":\"contains\",\"value\":\"acme\"}]`.\nUnknown fields/operators are ignored by the resolver.","schema":{"type":"array","items":{"$ref":"#/components/schemas/Object"}}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Get All Ids"}},"/contacts/export":{"get":{"operationId":"ContactsController_exportCsv","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"name","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"phone","required":false,"in":"query","schema":{"maxLength":50,"type":"string"}},{"name":"email","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["ACTIVE","INVALID","ARCHIVED"]}}},{"name":"source","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["TEXT_LINK","JOIN_KEYWORD","CSV_IMPORT","MANUAL","WEB_FORM","INBOUND_SMS","INBOUND_CALL","GOOGLE_ADS","META_ADS","INBOUND_EMAIL","INBOUND_WHATSAPP","LEAD_FORM","WEB_CHAT"]}}},{"name":"stage","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["ARCHIVED","NEW_LEAD","ENGAGED","QUALIFIED","APPOINTMENT_BOOKED","CUSTOMER","LOST","BOOKING_PENDING","ESTIMATE_GIVEN","DECIDING","NOT_QUALIFIED"]}}},{"name":"leadScore","required":false,"in":"query","description":"Hot / Warm / Cold — e.g. `?leadScore=HOT` for the \"Hot leads\" filter.","schema":{"type":"array","items":{"type":"string","enum":["HOT","WARM","COLD"]}}},{"name":"isOptedOut","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"emailSubscribed","required":false,"in":"query","description":"EMAIL subscription state — deliberately SEPARATE from `isOptedOut`, which\nis the SMS opt-out flag. A contact can be reachable by SMS and\nunsubscribed from email, or the reverse; collapsing them would silently\nfilter out contacts the user still wants.\n\n`true` = still emailable, `false` = on the org's suppression list.","schema":{"type":"boolean"}},{"name":"optedOutChannel","required":false,"in":"query","description":"Opted out: `ALL_CHANNELS` (= `isOptedOut`, the global opt-out), `WHATSAPP`\n(`whatsappOptIn === false`, set by a WhatsApp STOP) or `ANY`.","schema":{"type":"string","enum":["ANY","ALL_CHANNELS","WHATSAPP"]}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"sample","required":false,"in":"query","description":"`sample=1` (or `true`) → only sample-data contacts.","schema":{"type":"boolean"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"excludeSegmentId","required":false,"in":"query","description":"Hide contacts that are already members of this segment. Used by the\nsegment \"Add Contacts\" picker so an existing member can't be selected\nand re-added (the insert is idempotent, but offering it reads as a bug).","schema":{"format":"uuid","type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","firstName","lastName","phone","email","status","leadScore"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"customFieldFilters","required":false,"in":"query","description":"Custom-field filters (module-builder bridge), passed as a JSON-encoded\narray keyed by field name, e.g.\n`?customFieldFilters=[{\"field\":\"company\",\"operator\":\"contains\",\"value\":\"acme\"}]`.\nUnknown fields/operators are ignored by the resolver.","schema":{"type":"array","items":{"$ref":"#/components/schemas/Object"}}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Contacts CSV, STREAMED. Honours the same query the list does, so the file\nmatches what the operator is looking at.\n\nLiteral route declared before `:id`, or 'export' is captured as a contact\nid and answered with a 404 — the same ordering the lead-forms export\nneeds.\n\nGated on `CONTACTS_READ` rather than a dedicated export permission, which\nis how all four pre-existing exports are gated. A separate permission\nwould be a stronger PII control, but adding one later is additive whereas\nshipping one now silently 403s every existing role until it is granted.\n\nNo row cap: `streamCsv` writes cursor pages as they arrive, so peak memory\nis one batch regardless of org size. The cap the other synchronous\nexports carry exists only because they build the whole file in memory\nfirst.","tags":["Contacts"]}},"/contacts/{id}":{"get":{"operationId":"ContactsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ContactResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Get Contact By ID"},"patch":{"operationId":"ContactsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Update Contact"},"delete":{"operationId":"ContactsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Delete Contact"}},"/contacts/{id}/activity":{"get":{"operationId":"ContactsController_getActivity","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"type":"number"}},{"name":"cursor","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Get Activity"}},"/contacts/{id}/emails":{"get":{"operationId":"ContactsController_getEmails","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"statuses","required":false,"in":"query","description":"Display statuses to keep. Absent means \"no status filter\"; an explicitly\nempty value (`?statuses=`) means the user unchecked every box and so\nmatches nothing — the two are deliberately distinguishable.","schema":{"type":"array","items":{"type":"string","enum":["DELIVERED","OPENED","CLICKED","SENT","SCHEDULED","QUEUED","FAILED","CANCELLED"]}}},{"name":"q","required":false,"in":"query","description":"Substring match over the resolved subject and recipient address.","schema":{"maxLength":255,"type":"string"}},{"name":"page","required":false,"in":"query","description":"1-based page for \"Load more\". `@Max` bounds how deep an OFFSET can go.","schema":{"minimum":1,"maximum":200,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Contact detail: emails sent to this contact (campaign + sequence/workflow).","tags":["Contacts"]}},"/contacts/{id}/link-analytics":{"get":{"operationId":"ContactsController_getLinkAnalytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Link engagement summary (smart-link + email clicks) for the profile panel.","tags":["Contacts"]}},"/contacts/{id}/preferred-caller-id":{"put":{"operationId":"ContactsController_setPreferredCallerId","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPreferredCallerIdDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Set Preferred Caller ID"}},"/contacts/{id}/stage":{"patch":{"operationId":"ContactsController_updateStage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactStageDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Update Stage"}},"/contacts/{id}/mark-won":{"post":{"operationId":"ContactsController_markWon","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkWonDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Manual \"closed won\" action: advances the contact to CUSTOMER (unless\n already there) and records a manual conversion for revenue reporting.","tags":["Contacts"]}},"/contacts/{id}/sales":{"get":{"operationId":"ContactsController_getSales","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The contact's recorded sales (every conversion source): totals plus the latest few.","tags":["Contacts"]}},"/contacts/{id}/tags":{"post":{"operationId":"ContactsController_addTags","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageTagsDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Add Tags"}},"/contacts/{id}/tags/{tagId}":{"delete":{"operationId":"ContactsController_removeTag","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"tagId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Remove Tag"}},"/contacts/{id}/notes":{"get":{"operationId":"ContactNotesController_listNotes","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"List Notes"},"post":{"operationId":"ContactNotesController_createNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactNoteDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Create Note"}},"/contacts/{id}/notes/{noteId}":{"delete":{"operationId":"ContactNotesController_deleteNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"noteId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Delete Note"}},"/contacts/{id}/estimates":{"post":{"operationId":"EstimatesController_create","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEstimateDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Record an estimate given to this lead","tags":["Contacts"]}},"/contacts/{id}/estimates/{estimateId}":{"patch":{"operationId":"EstimatesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"estimateId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEstimateDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Edit an estimate, or record that it was accepted or declined","tags":["Contacts"]}},"/contacts/{id}/decision/undo":{"post":{"operationId":"EstimatesController_undoDecision","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Undo an AI-recorded decision (within 7 days)","tags":["Contacts"]}},"/tags":{"post":{"operationId":"TagsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTagDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Create Tag"},"get":{"operationId":"TagsController_findAll","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","name"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"List Tags"}},"/tags/export":{"get":{"operationId":"TagsController_exportCsv","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","name"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Tags CSV, STREAMED, honouring the list's search filter.\n\nDeclared before `:id` so 'export' is not captured as a tag id.","tags":["Contacts"]}},"/tags/{id}":{"get":{"operationId":"TagsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Get Tag By ID"},"patch":{"operationId":"TagsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTagDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Update Tag"},"delete":{"operationId":"TagsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Delete Tag"}},"/modules":{"post":{"operationId":"ModulesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateModuleDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Create Module"},"get":{"operationId":"ModulesController_findAll","parameters":[{"name":"includeInactive","required":false,"in":"query","description":"Include disabled (`isActive = false`) modules. Defaults to false so\nnav-facing consumers only see enabled modules; the builder admin UI\npasses `true` to keep managing disabled ones.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"List Modules"}},"/modules/reorder":{"post":{"operationId":"ModulesController_reorder","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Reorder Module"}},"/modules/{id}":{"get":{"operationId":"ModulesController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Get Module"},"patch":{"operationId":"ModulesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateModuleDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Update Module"},"delete":{"operationId":"ModulesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Delete Module"}},"/modules/{moduleId}/sections":{"post":{"operationId":"SectionsController_create","parameters":[{"name":"moduleId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSectionDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Create Section"}},"/modules/{moduleId}/sections/reorder":{"post":{"operationId":"SectionsController_reorder","parameters":[{"name":"moduleId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Reorder Section"}},"/modules/{moduleId}/sections/{sectionId}":{"patch":{"operationId":"SectionsController_update","parameters":[{"name":"sectionId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSectionDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Update Section"},"delete":{"operationId":"SectionsController_remove","parameters":[{"name":"sectionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Delete Section"}},"/modules/{moduleId}/fields":{"post":{"operationId":"FieldsController_create","parameters":[{"name":"moduleId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFieldDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Create Field"}},"/modules/{moduleId}/fields/reorder":{"post":{"operationId":"FieldsController_reorder","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderFieldsDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Reorder Field"}},"/modules/{moduleId}/fields/{fieldId}":{"patch":{"operationId":"FieldsController_update","parameters":[{"name":"fieldId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFieldDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Update Field"},"delete":{"operationId":"FieldsController_remove","parameters":[{"name":"fieldId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Delete Field"}},"/modules/{moduleId}/fields/{fieldId}/move":{"post":{"operationId":"FieldsController_move","parameters":[{"name":"fieldId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveFieldDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Move Field"}},"/modules/{moduleId}/records":{"post":{"operationId":"RecordsController_create","parameters":[{"name":"moduleId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRecordDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Create Record"},"get":{"operationId":"RecordsController_findAll","parameters":[{"name":"moduleId","required":true,"in":"path","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"cursor","required":false,"in":"query","description":"Opaque keyset cursor from a previous page's `nextCursor`.","schema":{"maxLength":512,"type":"string"}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"sortBy","required":false,"in":"query","description":"Sort target: a field id (uuid) or `createdAt` | `updatedAt` |\n`displayTitle`. Unknown/unsortable values fall back to `createdAt`.","schema":{"maxLength":64,"type":"string"}},{"name":"filters","required":false,"in":"query","description":"Snapshot-based filters, passed as a JSON-encoded array, e.g.\n`?filters=[{\"fieldId\":\"…\",\"operator\":\"is\",\"value\":\"x\"}]`.\nUnknown/invalid filters are ignored by the predicate builder.","schema":{"type":"array","items":{"$ref":"#/components/schemas/Object"}}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"List Records"}},"/modules/{moduleId}/records/{recordId}":{"get":{"operationId":"RecordsController_findOne","parameters":[{"name":"recordId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Get Record"},"patch":{"operationId":"RecordsController_update","parameters":[{"name":"moduleId","required":true,"in":"path","schema":{"type":"string"}},{"name":"recordId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRecordDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Update Record"},"delete":{"operationId":"RecordsController_remove","parameters":[{"name":"recordId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Delete Record"}},"/modules/{moduleId}/layouts":{"get":{"operationId":"ModuleLayoutsController_findAll","parameters":[{"name":"moduleId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"List Module Layouts"}},"/modules/{moduleId}/layouts/{layoutId}":{"patch":{"operationId":"ModuleLayoutsController_update","parameters":[{"name":"moduleId","required":true,"in":"path","schema":{"type":"string"}},{"name":"layoutId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateModuleLayoutDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Update Module Layout"}},"/contacts/{contactId}/custom-fields":{"get":{"operationId":"SystemEntityValuesController_get","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Get System Entity Value"},"put":{"operationId":"SystemEntityValuesController_set","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSystemEntityValuesDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Set System Entity Value"}},"/tickets/{ticketId}/custom-fields":{"get":{"operationId":"TicketCustomFieldsController_get","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Get Ticket Custom Field"},"put":{"operationId":"TicketCustomFieldsController_set","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSystemEntityValuesDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Set Ticket Custom Field"}},"/opportunities/{opportunityId}/custom-fields":{"get":{"operationId":"OpportunityCustomFieldsController_get","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Get Opportunity Custom Field"},"put":{"operationId":"OpportunityCustomFieldsController_set","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSystemEntityValuesDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Module Builder"],"summary":"Set Opportunity Custom Field"}},"/opportunity-fields":{"get":{"operationId":"OpportunityFieldsController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"List Opportunity Fields"},"post":{"operationId":"OpportunityFieldsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickCreateOpportunityFieldDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Create Opportunity Field"}},"/opportunity-fields/reorder":{"put":{"operationId":"OpportunityFieldsController_reorder","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderOpportunityFieldsDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Reorder Opportunity Field"}},"/opportunity-fields/{fieldId}":{"patch":{"operationId":"OpportunityFieldsController_update","parameters":[{"name":"fieldId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOpportunityFieldDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Update Opportunity Field"},"delete":{"operationId":"OpportunityFieldsController_remove","parameters":[{"name":"fieldId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Delete Opportunity Field"}},"/conversions/{id}":{"delete":{"operationId":"ConversionsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Void a manually-recorded conversion (`mark-won` undo). All guard logic\n(org scoping, `MANUAL_WON`-only, already-voided no-op) lives in\n`ConversionsService.voidManualConversion` — the controller just parses\nthe request and returns 204.","tags":["Conversions"]}},"/advertising/connections/{provider}/authorize-url":{"post":{"operationId":"AdConnectionsController_createAuthorizationUrl","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAuthorizationUrlDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Create Authorization URL","tags":["Advertising"]}},"/advertising/providers":{"get":{"operationId":"AdConnectionsController_listProviders","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Providers","tags":["Advertising"]}},"/advertising/connections/{id}/lead-webhook":{"get":{"operationId":"AdConnectionsController_getLeadWebhook","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Lead Webhook","tags":["Advertising"],"description":"paste into Google Ads for lead delivery. The key lets anyone post leads into this workspace, so this needs `advertising:manage`, not `read`."}},"/advertising/connections":{"get":{"operationId":"AdConnectionsController_listConnections","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Connections","tags":["Advertising"]}},"/advertising/connections/{id}":{"delete":{"operationId":"AdConnectionsController_disconnect","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Disconnect Ad Connection","tags":["Advertising"]}},"/advertising/connections/{id}/accounts":{"get":{"operationId":"AdConnectionsController_listAccounts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Accounts","tags":["Advertising"]},"patch":{"operationId":"AdConnectionsController_updateAccountSelection","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAdAccountSelectionDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Update Account Selection","tags":["Advertising"]}},"/advertising/{provider}/callback":{"get":{"operationId":"AdsOAuthCallbackController_handleCallback","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"error","required":false,"in":"query","schema":{}},{"name":"state","required":false,"in":"query","schema":{}},{"name":"code","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Advertising"],"summary":"Handle Callback"}},"/advertising/webhooks/meta":{"get":{"operationId":"AdsWebhookController_handleMetaChallenge","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Handle Meta Challenge","tags":["Webhooks"],"description":"handshake. Echoes `hub.challenge` as plain text on success; 403 otherwise (mode/token mismatch)."},"post":{"operationId":"AdsWebhookController_handleMetaWebhook","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Handle Meta Webhook","tags":["Webhooks"],"description":"Signature failure is fatal (403); everything else (unknown page, malformed entry) is logged and skipped so the response always resolves 200 — Meta retries any non-2xx."}},"/advertising/webhooks/google/{connectionId}":{"post":{"operationId":"AdsWebhookController_handleGoogleWebhook","parameters":[{"name":"connectionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Handle Google Webhook","tags":["Webhooks"],"description":"lead-form push (per-connection opaque key, no HMAC). Fields arrive inline (`user_column_data`) — no fetch API round-trip needed."}},"/advertising/dev/simulate-lead":{"post":{"operationId":"AdsDevSimulationController_simulateLead","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimulateLeadDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Simulate Lead","tags":["Advertising"]}},"/advertising/analytics/campaigns":{"get":{"operationId":"AdvertisingAnalyticsController_getCampaignPerformance","parameters":[{"name":"provider","required":false,"in":"query","schema":{"type":"string","enum":["GOOGLE_ADS","META_ADS"]}},{"name":"adAccountId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"attributionModel","required":true,"in":"query","schema":{"default":"first","type":"string","enum":["first","last"]}},{"name":"from","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":true,"in":"query","schema":{"format":"date-time","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Campaign Performance","tags":["Advertising"]}},"/advertising/analytics/lead-sources":{"get":{"operationId":"AdvertisingAnalyticsController_getLeadSources","parameters":[{"name":"from","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":true,"in":"query","schema":{"format":"date-time","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Lead Sources","tags":["Advertising"]}},"/advertising/analytics/funnel":{"get":{"operationId":"AdvertisingAnalyticsController_getFunnel","parameters":[{"name":"from","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"provider","required":false,"in":"query","schema":{"type":"string","enum":["GOOGLE_ADS","META_ADS"]}},{"name":"campaignId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Funnel","tags":["Advertising"]}},"/advertising/campaigns":{"get":{"operationId":"AdCampaignsController_listCampaigns","parameters":[{"name":"provider","required":false,"in":"query","schema":{"type":"string","enum":["GOOGLE_ADS","META_ADS"]}},{"name":"adAccountId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Campaigns","tags":["Advertising"]}},"/advertising/lead-forms":{"get":{"operationId":"AdCampaignsController_listLeadForms","parameters":[{"name":"provider","required":false,"in":"query","schema":{"type":"string","enum":["GOOGLE_ADS","META_ADS"]}},{"name":"adAccountId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Lead Forms","tags":["Advertising"]}},"/advertising/leads":{"get":{"operationId":"AdCampaignsController_listLeads","parameters":[{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["FAILED","PROCESSED","RECEIVED","DUPLICATE","SKIPPED_ENTITLEMENT","SKIPPED_NO_PHONE"]}},{"name":"provider","required":false,"in":"query","schema":{"type":"string","enum":["GOOGLE_ADS","META_ADS"]}},{"name":"campaignId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"from","required":false,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":false,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Leads","tags":["Advertising"],"description":"`rawPayload` (see `AdLeadListView`) — use the detail endpoint for that."}},"/advertising/accounts/{id}":{"get":{"operationId":"AdCampaignsController_getAccount","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Account","tags":["Advertising"],"description":"status. Database only (unlike `GET connections/:id/accounts`, which asks the provider), so the connect wizard can poll it while a sync runs."}},"/advertising/leads/{id}":{"get":{"operationId":"AdCampaignsController_getLead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Lead","tags":["Advertising"]}},"/pipelines":{"get":{"operationId":"PipelinesController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"List Pipelines"},"post":{"operationId":"PipelinesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePipelineDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Create Pipeline"}},"/pipelines/lost-reasons":{"get":{"operationId":"PipelinesController_listLostReasons","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"List Lost Reasons"},"post":{"operationId":"PipelinesController_createLostReason","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLostReasonDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Create Lost Reason"}},"/pipelines/lost-reasons/{id}":{"patch":{"operationId":"PipelinesController_updateLostReason","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLostReasonDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Update Lost Reason"},"delete":{"operationId":"PipelinesController_removeLostReason","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Remove Lost Reason"}},"/pipelines/{id}":{"get":{"operationId":"PipelinesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Get Pipeline By ID"},"patch":{"operationId":"PipelinesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePipelineDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Update Pipeline"},"delete":{"operationId":"PipelinesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Delete Pipeline"}},"/pipelines/{id}/stages":{"post":{"operationId":"PipelinesController_addStage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateStageDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Add Stage"}},"/pipelines/{id}/stages/reorder":{"put":{"operationId":"PipelinesController_reorderStages","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderStagesDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Reorder Stages"}},"/pipelines/{id}/stages/{stageId}":{"patch":{"operationId":"PipelinesController_updateStage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stageId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStageDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Update Stage"},"delete":{"operationId":"PipelinesController_removeStage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stageId","required":true,"in":"path","schema":{"type":"string"}},{"name":"moveToStageId","required":false,"in":"query","description":"Required when the stage still holds opportunities.","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Pipelines"],"summary":"Remove Stage"}},"/opportunities":{"post":{"operationId":"OpportunitiesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOpportunityDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Create Opportunity"},"get":{"operationId":"OpportunitiesController_findAll","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"pipelineId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"stageIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"status","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["OPEN","LOST","WON"]}}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","updatedAt","expectedCloseAt","value","name","priority","stageEnteredAt"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"search","required":false,"in":"query","description":"Matches name / company / contact name, email, phone.","schema":{"maxLength":200,"type":"string"}},{"name":"ownerIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string"}}},{"name":"contactId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"priority","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["LOW","HIGH","MEDIUM"]}}},{"name":"source","required":false,"in":"query","description":"Any of these (comma-separated); `Other` also matches every custom source.","schema":{"maxItems":20,"maxLength":100,"type":"array","items":{"type":"string"}}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"valueMin","required":false,"in":"query","schema":{"minimum":0,"type":"number"}},{"name":"valueMax","required":false,"in":"query","schema":{"minimum":0,"type":"number"}},{"name":"closeFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"closeTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"attention","required":false,"in":"query","schema":{"type":"string","enum":["at_risk","stale","no_next_step","closing_soon","overdue"]}},{"name":"staleDays","required":false,"in":"query","schema":{"minimum":3,"maximum":90,"type":"number"}},{"name":"closedFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"closedTo","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"List Opportunities"}},"/opportunities/export":{"get":{"operationId":"OpportunitiesController_exportCsv","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"pipelineId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"stageIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"status","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["OPEN","LOST","WON"]}}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","updatedAt","expectedCloseAt","value","name","priority","stageEnteredAt"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"search","required":false,"in":"query","description":"Matches name / company / contact name, email, phone.","schema":{"maxLength":200,"type":"string"}},{"name":"ownerIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string"}}},{"name":"contactId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"priority","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["LOW","HIGH","MEDIUM"]}}},{"name":"source","required":false,"in":"query","description":"Any of these (comma-separated); `Other` also matches every custom source.","schema":{"maxItems":20,"maxLength":100,"type":"array","items":{"type":"string"}}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"valueMin","required":false,"in":"query","schema":{"minimum":0,"type":"number"}},{"name":"valueMax","required":false,"in":"query","schema":{"minimum":0,"type":"number"}},{"name":"closeFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"closeTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"attention","required":false,"in":"query","schema":{"type":"string","enum":["at_risk","stale","no_next_step","closing_soon","overdue"]}},{"name":"staleDays","required":false,"in":"query","schema":{"minimum":3,"maximum":90,"type":"number"}},{"name":"closedFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"closedTo","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Opportunities CSV, STREAMED, honouring the current list filters.\n\nDeclared before any `:id` route so 'export' is not captured as an\nopportunity id. OPPORTUNITIES_READ, matching every other read here.","tags":["Opportunities"]}},"/opportunities/board":{"get":{"operationId":"OpportunitiesController_getBoard","parameters":[{"name":"pipelineId","required":false,"in":"query","description":"Defaults to the org default pipeline.","schema":{"format":"uuid","type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":50,"default":25,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Matches name / company / contact name, email, phone.","schema":{"maxLength":200,"type":"string"}},{"name":"ownerIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string"}}},{"name":"contactId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"priority","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["LOW","HIGH","MEDIUM"]}}},{"name":"source","required":false,"in":"query","description":"Any of these (comma-separated); `Other` also matches every custom source.","schema":{"maxItems":20,"maxLength":100,"type":"array","items":{"type":"string"}}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"valueMin","required":false,"in":"query","schema":{"minimum":0,"type":"number"}},{"name":"valueMax","required":false,"in":"query","schema":{"minimum":0,"type":"number"}},{"name":"closeFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"closeTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"attention","required":false,"in":"query","schema":{"type":"string","enum":["at_risk","stale","no_next_step","closing_soon","overdue"]}},{"name":"staleDays","required":false,"in":"query","schema":{"minimum":3,"maximum":90,"type":"number"}},{"name":"closedFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"closedTo","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Get Board"}},"/opportunities/summary":{"get":{"operationId":"OpportunitiesController_getSummary","parameters":[{"name":"pipelineId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"ownerIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string"}}},{"name":"closingSoonBefore","required":false,"in":"query","description":"Cut-off for the `closingSoon` count. The window itself is owned by the\nclient (it already computes it for the matching list filter), so the\nserver just takes the date.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Get Summary"}},"/opportunities/reports":{"get":{"operationId":"OpportunitiesController_getReports","parameters":[{"name":"pipelineId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"from","required":false,"in":"query","description":"ISO date or date-time; the period start (inclusive).","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"ISO date (inclusive day) or date-time (exclusive instant); the period end.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Pipeline analytics (Phase II §7). Registered above `:id` so \"reports\" is never read as an id.","tags":["Opportunities"]}},"/opportunities/analytics":{"get":{"operationId":"OpportunitiesController_getAnalytics","parameters":[{"name":"pipelineId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"from","required":false,"in":"query","description":"ISO date or date-time; the period start (inclusive).","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"ISO date (inclusive day) or date-time (exclusive instant); the period end.","schema":{"type":"string"}},{"name":"ownerIds","required":false,"in":"query","description":"Owner ids, comma-separated or repeated; `unassigned` matches deals without an owner.","schema":{"type":"array","items":{"type":"string"}}},{"name":"staleDays","required":false,"in":"query","schema":{"minimum":3,"maximum":90,"type":"number"}},{"name":"granularity","required":false,"in":"query","schema":{"type":"string","enum":["week","month","quarter"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Pipeline Analytics dashboard (spec §5.1). Registered above `:id` like `reports`.","tags":["Opportunities"]}},"/opportunities/source-suggestions":{"get":{"operationId":"OpportunitiesController_getSourceSuggestions","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Get Source Suggestions"}},"/opportunities/bulk":{"post":{"operationId":"OpportunitiesController_bulk","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkOpportunityActionDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Bulk Opportunity"}},"/opportunities/bulk-delete":{"post":{"operationId":"OpportunitiesController_bulkDelete","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeleteOpportunitiesDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Bulk Delete"}},"/opportunities/mention-candidates":{"get":{"operationId":"OpportunitiesController_listMentionCandidates","parameters":[{"name":"search","required":false,"in":"query","description":"Optional name/email filter for the dropdown search.","schema":{"maxLength":100,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"List teammates eligible to be @-mentioned in a deal comment","tags":["Opportunities"]}},"/opportunities/{id}":{"get":{"operationId":"OpportunitiesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Get Opportunity By ID"},"patch":{"operationId":"OpportunitiesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOpportunityDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Update Opportunity"},"delete":{"operationId":"OpportunitiesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Delete Opportunity"}},"/opportunities/{id}/activity":{"get":{"operationId":"OpportunitiesController_getActivity","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"types","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["LOST","TAG_ADDED","TAG_REMOVED","STAGE_CHANGED","REOPENED","WON","OPPORTUNITY_CREATED","OPPORTUNITY_UPDATED","OWNER_CHANGED","VALUE_CHANGED","CLOSE_DATE_CHANGED","PRIORITY_CHANGED","CONTACT_CHANGED","COMMENT_ADDED","COMMENT_UPDATED","COMMENT_DELETED","ATTACHMENT_ADDED","ATTACHMENT_REMOVED","CUSTOM_FIELDS_UPDATED","TASK_CREATED","TASK_COMPLETED","TASK_ASSIGNED","TASK_DELETED","OPPORTUNITY_DELETED"]}}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Get Activity"}},"/opportunities/{id}/stage":{"patch":{"operationId":"OpportunitiesController_changeStage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOpportunityStageDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Change Stage"}},"/opportunities/{id}/tags":{"post":{"operationId":"OpportunitiesController_addTags","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageOpportunityTagsDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Add Tags"}},"/opportunities/{id}/tags/{tagId}":{"delete":{"operationId":"OpportunitiesController_removeTag","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"tagId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Remove Tag"}},"/opportunities/{opportunityId}/comments":{"get":{"operationId":"OpportunityCommentsController_findAll","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"order","required":false,"in":"query","schema":{"default":"asc","type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"List Opportunity Comments"},"post":{"operationId":"OpportunityCommentsController_create","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOpportunityCommentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Create Opportunity Comment"}},"/opportunities/{opportunityId}/comments/{commentId}":{"patch":{"operationId":"OpportunityCommentsController_update","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"commentId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOpportunityCommentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Update Opportunity Comment"},"delete":{"operationId":"OpportunityCommentsController_remove","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"commentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Delete Opportunity Comment"}},"/opportunities/{opportunityId}/attachments/upload-url":{"post":{"operationId":"OpportunityAttachmentsController_getUploadUrl","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOpportunityAttachmentUploadUrlDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Get Upload URL"}},"/opportunities/{opportunityId}/attachments":{"post":{"operationId":"OpportunityAttachmentsController_confirm","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmOpportunityAttachmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Confirm Opportunity Attachment"},"get":{"operationId":"OpportunityAttachmentsController_findAll","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"List Opportunity Attachments"}},"/opportunities/{opportunityId}/attachments/{attachmentId}/download-url":{"get":{"operationId":"OpportunityAttachmentsController_getDownloadUrl","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"attachmentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Get Download URL"}},"/opportunities/{opportunityId}/attachments/{attachmentId}":{"delete":{"operationId":"OpportunityAttachmentsController_remove","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"attachmentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Delete Opportunity Attachment"}},"/opportunities/{opportunityId}/tasks":{"get":{"operationId":"OpportunityTasksController_list","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"List Opportunity Tasks"},"post":{"operationId":"OpportunityTasksController_create","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOpportunityTaskDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Create Opportunity Task"}},"/opportunities/{opportunityId}/tasks/{taskId}":{"patch":{"operationId":"OpportunityTasksController_update","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOpportunityTaskDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Update Opportunity Task"},"delete":{"operationId":"OpportunityTasksController_remove","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Delete Opportunity Task"}},"/opportunities/{opportunityId}/tasks/{taskId}/complete":{"post":{"operationId":"OpportunityTasksController_complete","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Complete Opportunity Task"}},"/opportunities/{opportunityId}/tasks/{taskId}/reopen":{"post":{"operationId":"OpportunityTasksController_reopen","parameters":[{"name":"opportunityId","required":true,"in":"path","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Opportunities"],"summary":"Reopen Opportunity Task"}},"/opt-in/keywords":{"get":{"operationId":"OptInController_listKeywords","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":64,"type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","keyword"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-In"],"summary":"List Keywords"},"post":{"operationId":"OptInController_createKeyword","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOptInKeywordDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-In"],"summary":"Create Keyword"}},"/opt-in/reply-message":{"get":{"operationId":"OptInController_getReplyMessage","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-In"],"summary":"Get Reply Message"},"patch":{"operationId":"OptInController_updateReplyMessage","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateReplyMessageDto"}}}},"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-In"],"summary":"Update Reply Message"}},"/opt-in/keywords/{id}":{"patch":{"operationId":"OptInController_updateKeyword","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOptInKeywordDto"}}}},"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-In"],"summary":"Update Keyword"},"delete":{"operationId":"OptInController_deleteKeyword","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-In"],"summary":"Delete Keyword"}},"/opt-in/provider-sync-status":{"get":{"operationId":"OptInController_getProviderSyncStatus","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-In"],"summary":"Get Provider Sync Status"}},"/opt-in/provider-sync-status/resync":{"post":{"operationId":"OptInController_resyncProviderStatus","parameters":[],"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Compliance — Opt-In"],"summary":"Resync Provider Status"}},"/quick-messages":{"post":{"operationId":"QuickMessagesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateQuickMessageDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Quick Messages"],"summary":"Create Quick Message"},"get":{"operationId":"QuickMessagesController_findAll","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","name"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Quick Messages"],"summary":"List Quick Messages"}},"/quick-messages/{id}":{"get":{"operationId":"QuickMessagesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Quick Messages"],"summary":"Get Quick Message By ID"},"patch":{"operationId":"QuickMessagesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateQuickMessageDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Quick Messages"],"summary":"Update Quick Message"},"delete":{"operationId":"QuickMessagesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Quick Messages"],"summary":"Delete Quick Message"}},"/media-assets/presign":{"post":{"operationId":"MediaAssetsController_presign","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresignMediaAssetDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/PresignMediaAssetResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Media Assets"],"summary":"Presign Media Asset"}},"/media-assets":{"post":{"operationId":"MediaAssetsController_confirm","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmMediaAssetDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/MediaAssetResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Media Assets"],"summary":"Confirm Media Asset"},"get":{"operationId":"MediaAssetsController_list","parameters":[{"name":"search","required":false,"in":"query","description":"Case-insensitive filename search (`ILIKE %search%`).","schema":{"maxLength":200,"type":"string"}},{"name":"profile","required":false,"in":"query","description":"Which profile's rows to list. Defaults to `IMAGE_LIBRARY` so the email\nbuilder's existing query keeps returning only builder images now that\nMMS attachments share the table.","schema":{"type":"string","enum":["IMAGE_LIBRARY","MMS","WHATSAPP_HEADER","WHATSAPP_MESSAGE"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/MediaAssetResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Media Assets"],"summary":"List Media Assets"}},"/media-assets/{id}":{"delete":{"operationId":"MediaAssetsController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Media Assets"],"summary":"Delete Media Asset"}},"/channels/sms/connect":{"post":{"operationId":"SmsChannelController_connect","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateCredentialsDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Channel"],"summary":"Connect SMS Channel"}},"/channels/sms/disconnect":{"post":{"operationId":"SmsChannelController_disconnect","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Disconnect SMS Channel","tags":["SMS Channel"],"description":"Disconnect the SMS channel for the current organization."}},"/channels/sms/state":{"get":{"operationId":"SmsChannelController_loadState","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Channel"],"summary":"Load State"}},"/channels/sms/sender-identities/{id}/members":{"get":{"operationId":"SmsChannelController_listIdentityMembers","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"List Identity Members","tags":["SMS Channel"],"description":"Paginated, searchable list of channel identities for use as campaign senders. Backs the sender-selection step of the campaign creation wizard."},"post":{"operationId":"SmsChannelController_addIdentityMember","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddIdentityMemberDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Channel"],"summary":"Add Identity Member"}},"/channels/sms/sender-identities/{id}/members/{userId}":{"delete":{"operationId":"SmsChannelController_removeIdentityMember","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"userId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Channel"],"summary":"Remove Identity Member"}},"/channels/sms/sender-identities":{"get":{"operationId":"SmsChannelController_listSenderIdentities","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"type":"number"}},{"name":"q","required":false,"in":"query","schema":{"maxLength":255,"type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["identity","displayName","createdAt"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","INACTIVE","SUSPENDED"]}},{"name":"smsOnly","required":true,"in":"query","description":"Restricts the list to identities on the org's SMS channel. Defaults to\n`true`: this route is SMS-namespaced, and email senders share the\n`channel_identities` table, so an unfiltered list leaks email addresses\ninto every SMS sender picker.\n\nNOTE: a plain `@Type(() => Boolean)` cannot express this — query params\narrive as strings and `Boolean('false') === true`, which would make the\nopt-out unreachable.","schema":{"default":true,"type":"boolean"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Channel"],"summary":"List Sender Identities"}},"/channels/sms/select-resources":{"post":{"operationId":"SmsChannelController_selectResources","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectResourcesDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Select Resources","tags":["SMS Channel"],"description":"Finalize the post-connection wizard. Re-fetches live provider state, filters services / campaigns / phone numbers to the supplied `selectedServiceSids`, and persists exactly that slice (overwriting any prior selection). Materializes channel identities for in-scope numbers and soft-deletes any out-of-scope identities."}},"/channels/sms/discovery/refresh":{"post":{"operationId":"SmsChannelController_refreshDiscovery","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Refresh Discovery","tags":["SMS Channel"],"description":"Live provider discovery for the setup drawer. Returns the full provider inventory (brand, services, campaigns, phone numbers) without persisting services / campaigns / identities. Brand cache is refreshed as a side-effect so a freshly-registered brand becomes visible."}},"/channels/sms/provider/phone-numbers/{phoneNumberSid}/assign":{"post":{"operationId":"SmsChannelController_assignNumberLive","parameters":[{"name":"phoneNumberSid","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignNumberLiveDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Assign Number Live","tags":["SMS Channel"],"description":"Live per-number messaging-service reassignment for the setup drawer's step 4 dropdown. Calls the provider only — no DB writes happen here."}},"/channels/sms/brand":{"post":{"operationId":"SmsChannelController_registerBrand","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterBrandDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Channel"],"summary":"Register Brand"}},"/channels/sms/campaign":{"post":{"operationId":"SmsChannelController_createCampaign","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCampaignDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Channel"],"summary":"Create Campaign"}},"/channels/sms/campaign/{campaignSid}":{"delete":{"operationId":"SmsChannelController_deleteCampaign","parameters":[{"name":"campaignSid","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Delete Campaign","tags":["SMS Channel"],"description":"Remove a 10DLC campaign. Twilio campaigns in IN_PROGRESS are removed via the Usa2p delete endpoint; Telnyx campaigns are removed from local tracking only (Telnyx doesn't expose a TCR campaign delete)."}},"/channels/sms/brand/{brandSid}":{"delete":{"operationId":"SmsChannelController_deleteBrand","parameters":[{"name":"brandSid","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Delete Brand","tags":["SMS Channel"],"description":"Remove a 10DLC brand. Twilio brands are removed from local tracking only; Telnyx brands are fully deleted on the provider side."}},"/channels/sms/messaging-service":{"post":{"operationId":"SmsChannelController_createMessagingService","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMessagingServiceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Channel"],"summary":"Create Messaging Service"}},"/channels/sms/messaging-service/assignment":{"patch":{"operationId":"SmsChannelController_updateMessagingServiceAssignment","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMessagingServiceAssignmentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Update Messaging Service Assignment","tags":["SMS Channel"],"description":"Update the messaging service assignment for a phone number."}},"/channels/sms/phone-numbers/search":{"get":{"operationId":"SmsChannelController_searchNumbers","parameters":[{"name":"countryCode","required":true,"in":"query","schema":{"minLength":2,"maxLength":2,"type":"string"}},{"name":"type","required":false,"in":"query","schema":{"type":"string","enum":["local","mobile","toll-free"]}},{"name":"areaCode","required":false,"in":"query","schema":{"type":"string"}},{"name":"contains","required":false,"in":"query","schema":{"type":"string"}},{"name":"smsEnabled","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"mmsEnabled","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"voiceEnabled","required":false,"in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Channel"],"summary":"Search Numbers"}},"/channels/sms/phone-numbers/purchase":{"post":{"operationId":"SmsChannelController_purchaseNumber","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchasePhoneNumberDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Purchase Number","tags":["SMS Channel"],"description":"Purchase a single phone number from the SMS provider."}},"/webhooks/sms/twilio":{"post":{"operationId":"SmsWebhookController_handleTwilioInbound","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Twilio Inbound Webhook"}},"/webhooks/sms/twilio/status-callback":{"post":{"operationId":"SmsWebhookController_handleTwilioStatusCallback","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Twilio Status Callback","tags":["Webhooks"],"description":"Receives delivery status updates from Twilio for outbound messages."}},"/webhooks/sms/telnyx":{"post":{"operationId":"SmsWebhookController_handleTelnyxInbound","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Telnyx Inbound Webhook"}},"/join-keywords":{"post":{"operationId":"JoinKeywordsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJoinKeywordDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Create Join Keyword"},"get":{"operationId":"JoinKeywordsController_list","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","PAUSED"]}},{"name":"segmentId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"channelIdentityId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"List Join Keywords"}},"/join-keywords/availability":{"get":{"operationId":"JoinKeywordsController_availability","parameters":[{"name":"keyword","required":true,"in":"query","schema":{"minLength":1,"maxLength":64,"type":"string"}},{"name":"channelIdentityId","required":true,"in":"query","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Availability Join Keyword"}},"/join-keywords/dashboard":{"get":{"operationId":"JoinKeywordsController_dashboard","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Dashboard Join Keyword"}},"/join-keywords/analytics/compare":{"get":{"operationId":"JoinKeywordsController_compareAnalytics","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Compare Analytics"}},"/join-keywords/insights":{"get":{"operationId":"JoinKeywordsController_insights","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Insights Join Keyword"}},"/join-keywords/{id}":{"get":{"operationId":"JoinKeywordsController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Get Join Keyword By ID"},"patch":{"operationId":"JoinKeywordsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateJoinKeywordDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Update Join Keyword"},"delete":{"operationId":"JoinKeywordsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Delete Join Keyword"}},"/join-keywords/{id}/qr-design":{"put":{"operationId":"JoinKeywordsController_saveQrDesign","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QrDesignDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Save QR Design"}},"/join-keywords/{id}/pause":{"post":{"operationId":"JoinKeywordsController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Pause Join Keyword"}},"/join-keywords/{id}/resume":{"post":{"operationId":"JoinKeywordsController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Resume Join Keyword"}},"/join-keywords/{id}/duplicate":{"post":{"operationId":"JoinKeywordsController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateJoinKeywordDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Duplicate Join Keyword"}},"/join-keywords/{id}/subscribers/export":{"get":{"operationId":"JoinKeywordsController_exportSubscribersCsv","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"A keyword's subscribers as CSV, STREAMED. Declared before the paginated\n`:id/subscribers` so the literal `/export` suffix is matched first.","tags":["Join Keywords"]}},"/join-keywords/{id}/subscribers":{"get":{"operationId":"JoinKeywordsController_subscribers","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Subscribers Join Keyword"}},"/join-keywords/{id}/analytics":{"get":{"operationId":"JoinKeywordsController_keywordAnalytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"grain","required":false,"in":"query","description":"Defaults to `'daily'` in the service when omitted — see `IJoinKeywordAnalyticsService.getKeywordAnalytics`.","schema":{"type":"string","enum":["daily","weekly","monthly"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Keyword Analytics"}},"/join-keywords/{id}/activity":{"get":{"operationId":"JoinKeywordsController_activity","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"Activity Join Keyword"}},"/join-keywords/{id}/qr":{"get":{"operationId":"JoinKeywordsController_qr","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"format","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Keywords"],"summary":"QR Join Keyword"}},"/segments/preview":{"post":{"operationId":"SegmentsController_previewRules","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewRulesDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/SegmentRulesPreviewResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Preview Rules"}},"/segments":{"get":{"operationId":"SegmentsController_findAll","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"type","required":false,"in":"query","schema":{"type":"string","enum":["STATIC","DYNAMIC"]}},{"name":"minContacts","required":false,"in":"query","description":"Inclusive lower bound on the member count — `1` hides empty segments.","schema":{"minimum":0,"type":"number"}},{"name":"maxContacts","required":false,"in":"query","description":"Inclusive upper bound on the member count.","schema":{"minimum":0,"type":"number"}},{"name":"createdFrom","required":false,"in":"query","description":"Inclusive lower bound on the creation time (ISO 8601).","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","description":"Inclusive upper bound on the creation time (ISO 8601) — callers send the end of the day.","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["name","type","createdAt","contactCount","lastComputedAt"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/SegmentResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"List Segments"},"post":{"operationId":"ContactBulkSegmentsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSegmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Create Contact Bulk Segment"}},"/segments/{id}":{"get":{"operationId":"SegmentsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/SegmentResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Get Segment By ID"},"patch":{"operationId":"SegmentsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSegmentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Update Segment"},"delete":{"operationId":"SegmentsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Delete Segment"}},"/segments/{id}/stats":{"get":{"operationId":"SegmentsController_getStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"Growth-series window in days. Defaults to SEGMENT_STATS_DEFAULT_DAYS.\n\nWhitelisted rather than range-checked on purpose: it caps cache-key\ncardinality at one key per window per segment, which is what makes\neviction a handful of `delete` calls instead of a blocking Redis `KEYS`\nscan. Widening this list means widening\n`buildSegmentStatsKeysForSegment` too.","schema":{"type":"number","enum":[7,30,90]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/SegmentStatsResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Deliberately separate from `GET :id` rather than folded into it: that\nroute is on the hot path for the detail page, the campaign wizard and\nevery internal `findOrThrow`, and must stay a single indexed lookup. This\npayload is a four-query fan-out, and unlike the segment row it is\ncacheable.","tags":["Segments"]}},"/segments/{id}/clone":{"post":{"operationId":"SegmentsController_clone","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloneSegmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Clone Segment"}},"/segments/{id}/contacts/export":{"get":{"operationId":"SegmentsController_exportContactsCsv","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"A segment's members as CSV, STREAMED.\n\nLiteral sub-route declared BEFORE the paginated `:id/contacts` above it\nwould not clash — they differ by suffix, not by a param — but it is kept\nadjacent so the two stay in step.\n\nReuses `CONTACT_EXPORT_COLUMNS`, so a segment export and a contacts export\nproduce the same columns for the same people. Gated on `SEGMENTS_READ`,\nmatching every other read on this controller.","tags":["Segments"]}},"/segments/{id}/contacts":{"get":{"operationId":"SegmentsController_getContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","firstName","lastName","phone","email","status"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/SegmentContactResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Get Contacts"},"post":{"operationId":"ContactBulkSegmentsController_addContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageContactsSelectorDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"object"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Add Contacts"},"delete":{"operationId":"ContactBulkSegmentsController_removeContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageContactsSelectorDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"object"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Remove Contacts"}},"/segments/{id}/preview":{"get":{"operationId":"SegmentsController_previewSegment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","firstName","lastName","phone","email","status"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/SegmentContactResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Segments"],"summary":"Preview Segment"}},"/sequences/audience/estimate":{"post":{"operationId":"SequencesController_estimateAudience","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateAudienceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Live audience-size chip in the wizard. Static path — registered before :id routes.","tags":["Sequences"]}},"/sequences/bulk-enroll":{"post":{"operationId":"SequencesController_bulkEnroll","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkEnrollmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Bulk add: every contact × every sequence. Static path — before :id routes.","tags":["Sequences"]}},"/sequences/bulk-unenroll":{"post":{"operationId":"SequencesController_bulkUnenroll","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkEnrollmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Bulk remove: cancels the contacts' active runs in the selected sequences.","tags":["Sequences"]}},"/sequences/by-contact/{contactId}":{"get":{"operationId":"SequencesController_listByContact","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Contact detail: sequences the contact is (or was last) enrolled in.","tags":["Sequences"]}},"/sequences":{"post":{"operationId":"SequencesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSequenceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Create Sequence"},"get":{"operationId":"SequencesController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"List Sequences"}},"/sequences/{id}":{"get":{"operationId":"SequencesController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Get Sequence By ID"},"patch":{"operationId":"SequencesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSequenceDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Update Sequence"},"delete":{"operationId":"SequencesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Delete Sequence"}},"/sequences/{id}/validate":{"get":{"operationId":"SequencesController_validate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Validate Sequence"}},"/sequences/{id}/publish":{"post":{"operationId":"SequencesController_publish","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishSequenceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Publish Sequence"}},"/sequences/{id}/contacts/{contactId}":{"delete":{"operationId":"SequencesController_removeContact","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Remove Contact"}},"/sequences/{id}/pause":{"post":{"operationId":"SequencesController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Pause Sequence"}},"/sequences/{id}/resume":{"post":{"operationId":"SequencesController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Resume Sequence"}},"/sequences/{id}/archive":{"post":{"operationId":"SequencesController_archive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Archive Sequence"}},"/sequences/{id}/unarchive":{"post":{"operationId":"SequencesController_unarchive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Unarchive Sequence"}},"/sequences/{id}/steps/{stepId}/test-send":{"post":{"operationId":"SequencesController_stepTestSend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceTestSendDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Step Test Send"}},"/sequences/{id}/clone":{"post":{"operationId":"SequencesController_clone","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Sequences"],"summary":"Clone Sequence"}},"/sequences/{id}/analytics":{"get":{"operationId":"SequenceAnalyticsController_report","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["SequenceAnalytics"],"summary":"Report Sequence Analytic"}},"/sequences/{id}/analytics/contacts":{"get":{"operationId":"SequenceAnalyticsController_contacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["SequenceAnalytics"],"summary":"Contacts Sequence Analytic"}},"/sequences/{id}/analytics/steps/{stepId}/contacts":{"get":{"operationId":"SequenceAnalyticsController_listStepContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The contacts behind one step metric — Delivered, Opened, Clicked, Failed or Sent.","tags":["SequenceAnalytics"]}},"/sequences/{id}/analytics/steps/{stepId}/contacts/export":{"get":{"operationId":"SequenceAnalyticsController_exportStepContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"stepId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Every contact behind one step metric, as CSV — STREAMED, so a large step is not a\ndifferent code path from a small one. Same rows and order as the list above.","tags":["SequenceAnalytics"]}},"/sequence-templates":{"get":{"operationId":"SequenceTemplatesController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["SequenceTemplates"],"summary":"List Sequence Templates"}},"/sequence-templates/{key}":{"get":{"operationId":"SequenceTemplatesController_getByKey","parameters":[{"name":"key","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["SequenceTemplates"],"summary":"Get By Key"}},"/email/domains":{"post":{"operationId":"EmailDomainsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailDomainDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Domains"],"summary":"Create Email Domain"},"get":{"operationId":"EmailDomainsController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Domains"],"summary":"List Email Domains"}},"/email/domains/{id}/verify":{"post":{"operationId":"EmailDomainsController_verify","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Domains"],"summary":"Verify Email Domain"}},"/email/domains/{id}/inbound":{"post":{"operationId":"EmailDomainsController_enableInbound","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableInboundDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Turn on inbound receiving for this domain. Returns the MX record the\ncustomer must publish — sending verification (DKIM/SPF) says nothing\nabout whether an address can receive, so this is a separate opt-in.","tags":["Email Domains"]},"delete":{"operationId":"EmailDomainsController_disableInbound","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Domains"],"summary":"Disable Inbound"}},"/email/domains/{id}/inbound/verify":{"post":{"operationId":"EmailDomainsController_verifyInbound","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Re-resolve the MX record after the customer has updated their DNS.","tags":["Email Domains"]}},"/email/domains/{id}":{"delete":{"operationId":"EmailDomainsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Domains"],"summary":"Delete Email Domain"}},"/email/senders":{"post":{"operationId":"EmailSendersController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailSenderDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Senders"],"summary":"Create Email Sender"},"get":{"operationId":"EmailSendersController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Senders"],"summary":"List Email Senders"}},"/email/senders/{id}":{"patch":{"operationId":"EmailSendersController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailSenderDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Senders"],"summary":"Update Email Sender"},"delete":{"operationId":"EmailSendersController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Senders"],"summary":"Delete Email Sender"}},"/webhooks/email/sendgrid":{"post":{"operationId":"EmailWebhookController_handleSendgridEvents","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Handle Sendgrid Events"}},"/webhooks/email/inbound/{token}":{"post":{"operationId":"EmailInboundController_handleInboundParse","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Handle Inbound Parse"}},"/email/test-send":{"post":{"operationId":"TestSendController_send","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSendDto"}}}},"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Test Send"],"summary":"Send Test Send"}},"/email/suppressions/resubscribe":{"post":{"operationId":"EmailSuppressionsController_resubscribe","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSuppressionWriteDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Suppressions"],"summary":"Resubscribe Email Suppression"}},"/email/suppressions/unsubscribe":{"post":{"operationId":"EmailSuppressionsController_unsubscribe","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSuppressionWriteDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Suppressions"],"summary":"Unsubscribe Email Suppression"}},"/contacts/{contactId}/email-subscription":{"get":{"operationId":"ContactEmailSubscriptionController_get","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contact Email Subscription"],"summary":"Get Contact Email Subscription"},"patch":{"operationId":"ContactEmailSubscriptionController_update","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailSubscriptionDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contact Email Subscription"],"summary":"Update Contact Email Subscription"}},"/public/email/unsubscribe/{token}":{"post":{"operationId":"OneClickUnsubscribeController_unsubscribe","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"One-click unsubscribe (RFC 8058) — public, token-authenticated","tags":["Email Suppressions"]}},"/workflows":{"post":{"operationId":"WorkflowsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkflowDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Create Workflow"},"get":{"operationId":"WorkflowsController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The Automations list. With no `kind` it lists automations AND sequences:\none surface, one table — `/sequences` is the same rows filtered.","tags":["Workflows"]}},"/workflows/attachments/presign":{"post":{"operationId":"WorkflowsController_presignAttachment","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresignEmailAttachmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Presign an upload for a Send-email step's attachment.\n\nStatic path, registered before the `:id` routes below — same reason\n`by-contact/:contactId` is where it is.\n\nUses the DURABLE prefix, not the inbox composer's staging one: what this\nmints is referenced by a saved workflow definition and re-read on every\nrun. Validation (deny-list, per-file ceiling) is `MessageAttachmentService`'s,\nunchanged — only the lifetime differs.","tags":["Workflows"]}},"/workflows/catalog":{"get":{"operationId":"WorkflowsController_catalog","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Node-type catalog driving the builder's node library + config forms.","tags":["Workflows"]}},"/workflows/by-contact/{contactId}":{"get":{"operationId":"WorkflowsController_listByContact","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Contact detail: automations the contact is (or was last) enrolled in.\n Static path — registered before the :id route.","tags":["Workflows"]}},"/workflows/{id}":{"get":{"operationId":"WorkflowsController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Get Workflow By ID"},"patch":{"operationId":"WorkflowsController_updateDraft","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWorkflowDraftDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Update Draft"},"delete":{"operationId":"WorkflowsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Delete Workflow"}},"/workflows/{id}/readiness":{"get":{"operationId":"WorkflowsController_readiness","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Publish/test readiness checklist (validation + environment checks).","tags":["Workflows"]}},"/workflows/{id}/webhook-endpoints":{"get":{"operationId":"WorkflowsController_webhookEndpoints","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Inbound-webhook trigger URLs (issued at publish, stable across republish).","tags":["Workflows"]}},"/workflows/{id}/audit":{"get":{"operationId":"WorkflowsController_audit","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"\"What happened to this automation\" — the history drawer. Read-only, so\nit carries the plain read permission; the lifecycle commands behind the\nentries are permissioned where they are performed.","tags":["Workflows"]}},"/workflows/{id}/validate":{"post":{"operationId":"WorkflowsController_validate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Validate Workflow"}},"/workflows/{id}/publish":{"post":{"operationId":"WorkflowsController_publish","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Publish Workflow"}},"/workflows/{id}/unpublish":{"post":{"operationId":"WorkflowsController_unpublish","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Unpublish Workflow"}},"/workflows/{id}/pause":{"post":{"operationId":"WorkflowsController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Pause / resume — the same permission `unpublish` carries, because both\ndecide whether an automation is allowed to be reaching contacts. Works\nfor sequences too: the row is a workflow either way.","tags":["Workflows"]}},"/workflows/{id}/resume":{"post":{"operationId":"WorkflowsController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Resume Workflow"}},"/workflows/{id}/archive":{"post":{"operationId":"WorkflowsController_archive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Archive Workflow"}},"/workflows/{id}/unarchive":{"post":{"operationId":"WorkflowsController_unarchive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Unarchive Workflow"}},"/workflows/{id}/clone":{"post":{"operationId":"WorkflowsController_clone","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Clone Workflow"}},"/workflows/{id}/execute":{"post":{"operationId":"WorkflowsController_execute","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteWorkflowDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Workflows"],"summary":"Execute Workflow"}},"/workflows/{id}/versions":{"get":{"operationId":"WorkflowsController_listVersions","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Published version history (builder history panel).","tags":["Workflows"]}},"/workflows/{id}/versions/{versionId}/restore":{"post":{"operationId":"WorkflowsController_restoreVersion","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"versionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Copy a published version's graph back into the draft.","tags":["Workflows"]}},"/workflows/{id}/backfill":{"post":{"operationId":"WorkflowsController_backfill","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Enroll contacts who ALREADY match the published tag/segment trigger.","tags":["Workflows"]}},"/workflows/{id}/analytics":{"get":{"operationId":"WorkflowAnalyticsController_report","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Summary counters + per-day run timeline + per-node funnel (LIVE runs).","tags":["WorkflowAnalytics"]}},"/workflows/{workflowId}/runs":{"get":{"operationId":"WorkflowRunsController_list","parameters":[{"name":"workflowId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WorkflowRuns"],"summary":"List Workflow Runs"}},"/workflows/{workflowId}/runs/export":{"get":{"operationId":"WorkflowRunsController_exportCsv","parameters":[{"name":"workflowId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Run history download (CSV attachment, newest first, capped).","tags":["WorkflowRuns"]}},"/workflow-runs/{runId}":{"get":{"operationId":"WorkflowRunsController_getById","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WorkflowRuns"],"summary":"Get Workflow Run By ID"}},"/workflow-runs/{runId}/steps":{"get":{"operationId":"WorkflowRunsController_listSteps","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Step-by-step execution trace for the run timeline drawer.","tags":["WorkflowRuns"]}},"/workflow-runs/{runId}/cancel":{"post":{"operationId":"WorkflowRunsController_cancel","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WorkflowRuns"],"summary":"Cancel Workflow Run"}},"/workflow-templates":{"get":{"operationId":"WorkflowTemplatesController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Gallery: built-in system templates + this org's saved templates.","tags":["WorkflowTemplates"]},"post":{"operationId":"WorkflowTemplatesController_save","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveTemplateDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Save a workflow's current draft as a reusable org template.","tags":["WorkflowTemplates"]}},"/workflow-templates/{templateId}/use":{"post":{"operationId":"WorkflowTemplatesController_use","parameters":[{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UseTemplateDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Create a draft workflow from a template (system key or org UUID).","tags":["WorkflowTemplates"]}},"/workflow-templates/{id}":{"delete":{"operationId":"WorkflowTemplatesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WorkflowTemplates"],"summary":"Delete Workflow Template"}},"/workflows/{id}/nodes/{nodeId}/test-send":{"post":{"operationId":"WorkflowTestController_sendNodeTest","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"nodeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"\"Send me a test\": deliver a send_email node's draft to the caller.","tags":["WorkflowTest"]}},"/workflows/{id}/test-runs":{"post":{"operationId":"WorkflowTestController_start","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartTestRunDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WorkflowTest"],"summary":"Start Workflow Test"}},"/workflow-runs/{runId}/test-state":{"get":{"operationId":"WorkflowTestController_state","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Poll target for the playground: status + pending wait + variables.","tags":["WorkflowTest"]}},"/workflow-runs/{runId}/skip-wait":{"post":{"operationId":"WorkflowTestController_skipWait","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Skip the pending wait — timers elapse; event waits take the timeout path.","tags":["WorkflowTest"]}},"/workflow-runs/{runId}/simulate-event":{"post":{"operationId":"WorkflowTestController_simulate","parameters":[{"name":"runId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimulateEventDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WorkflowTest"],"summary":"Simulate Workflow Test"}},"/hooks/workflows/{token}":{"post":{"operationId":"WorkflowHooksController_receive","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"202":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WorkflowHooks"],"summary":"Receive Workflow Hook"}},"/polls":{"post":{"operationId":"PollsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePollDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/PollCreateResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"Create Poll"},"get":{"operationId":"PollsController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/PollListItemDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"List Polls"}},"/polls/{id}":{"get":{"operationId":"PollsController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/PollDetailDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"Get Poll By ID"},"delete":{"operationId":"PollsController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"Delete Poll"}},"/polls/{id}/close":{"post":{"operationId":"PollsController_close","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"Close Poll"}},"/polls/{id}/cancel":{"post":{"operationId":"PollsController_cancel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"Cancel Poll"}},"/polls/{id}/messages":{"get":{"operationId":"PollsController_listMessages","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/PollMessageDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"List Messages"}},"/polls/{id}/analytics":{"get":{"operationId":"PollsController_analytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/PollAnalyticsDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"Get Poll Analytics"}},"/polls/{id}/create-segment":{"post":{"operationId":"PollsController_createSegment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSegmentFromPollDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/PollSegmentResultDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"Create Segment"}},"/polls/{pollId}/votes":{"get":{"operationId":"PollVotesController_list","parameters":[{"name":"pollId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/PollVoteDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"List Poll Votes"}},"/polls/{pollId}/votes/export":{"get":{"operationId":"PollVotesController_exportCsv","parameters":[{"name":"pollId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The poll's results as CSV, STREAMED — every live vote matching the vote\nlist's filters (option, search, tags), never just the page on screen.\nWith no filter set that is the whole poll.","tags":["Polls"]}},"/polls/{pollId}/votes/record":{"post":{"operationId":"PollVotesController_record","parameters":[{"name":"pollId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollVoteRecordDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Polls"],"summary":"Record Vote"}},"/campaigns":{"post":{"operationId":"CampaignsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCampaignDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignCreateResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Create Campaign"},"get":{"operationId":"CampaignsController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CampaignListItemDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"List Campaigns"}},"/campaigns/analytics/summary":{"get":{"operationId":"CampaignsController_getAnalyticsSummary","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignAnalyticsSummaryDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Get Analytics Summary"}},"/campaigns/{id}":{"get":{"operationId":"CampaignsController_getDetail","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignDetailDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Get Campaign"},"patch":{"operationId":"CampaignsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCampaignDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Update Campaign"},"delete":{"operationId":"CampaignsController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Delete Campaign"}},"/campaigns/{id}/pause":{"post":{"operationId":"CampaignsController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseCampaignDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Pause Campaign"}},"/campaigns/{id}/resume":{"post":{"operationId":"CampaignsController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Resume Campaign"}},"/campaigns/{id}/send":{"post":{"operationId":"CampaignsController_send","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Promote a DRAFT into its target status — the send a draft deferred.\n\n`CAMPAIGNS_SEND` rather than `CAMPAIGNS_UPDATE`: this is the moment messages\nstart costing money and reaching contacts, which is exactly the boundary that\npermission exists to draw. Saving a draft needs only CREATE/UPDATE, so a role\ncan be allowed to compose campaigns without being allowed to send them.\n\nThe entitlement decorator mirrors `POST /campaigns` because this is where the\n`campaigns` gauge unit is finally consumed.","tags":["Campaigns"]}},"/campaigns/{id}/duplicate":{"post":{"operationId":"CampaignsController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateCampaignDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Copy a campaign into a fresh DRAFT. `CAMPAIGNS_CREATE` because it creates a\ncampaign; no `SMS_SENDS` entitlement because a draft sends nothing and takes\nno gauge unit until it is sent.","tags":["Campaigns"]}},"/campaigns/{id}/cancel":{"post":{"operationId":"CampaignsController_cancel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Cancel Campaign"}},"/campaigns/{id}/end-recurrence":{"post":{"operationId":"CampaignsController_endRecurrence","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"End Recurrence"}},"/campaigns/{id}/estimate":{"post":{"operationId":"CampaignsController_estimateById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignCostEstimateDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Estimate By ID"}},"/campaigns/estimate":{"post":{"operationId":"CampaignsController_estimateInline","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateCampaignDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignCostEstimateDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Estimate Inline"}},"/campaigns/{id}/validate":{"post":{"operationId":"CampaignsController_validate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignValidationReportDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Validate Campaign"}},"/campaigns/recurrence/preview":{"post":{"operationId":"CampaignsController_previewRecurrence","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurrencePreviewDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignRecurrencePreviewDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Preview Recurrence"}},"/campaigns/{id}/analytics":{"get":{"operationId":"CampaignsController_analytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignAnalyticsDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Get Campaign Analytics"}},"/campaigns/{id}/action-results":{"get":{"operationId":"CampaignsController_actionResults","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"What the campaign's contact actions (the wizard's Actions step) actually\ndid — per-action totals and the per-run breakdown.","tags":["Campaigns"]}},"/campaigns/{id}/click-analytics":{"get":{"operationId":"CampaignsController_clickAnalytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Click Analytics"}},"/campaigns/{id}/links-analytics":{"get":{"operationId":"CampaignsController_linksAnalytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Channel-unified per-link + aggregate click analytics (Links tab).","tags":["Campaigns"]}},"/campaigns/{id}/link-analytics":{"get":{"operationId":"CampaignsController_linkAnalytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Link Analytics"}},"/campaigns/{id}/recipient-timeline/{contactId}":{"get":{"operationId":"CampaignsController_recipientTimeline","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Recipient Timeline"}},"/campaigns/{id}/messages":{"get":{"operationId":"CampaignsController_getMessages","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CampaignMessageDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Get Messages"}},"/campaigns/experiments/generate-variants":{"post":{"operationId":"CampaignsController_generateExperimentVariants","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateVariantsDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Generate Experiment Variants"}},"/campaigns/{id}/experiment":{"get":{"operationId":"CampaignsController_getExperiment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ExperimentResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Get Experiment"}},"/campaigns/{id}/experiment/winner":{"post":{"operationId":"CampaignsController_approveExperimentWinner","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveWinnerDto"}}}},"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Approve Experiment Winner"}},"/campaigns/{id}/experiment/cancel-promotion":{"post":{"operationId":"CampaignsController_cancelExperimentPromotion","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Cancel Experiment Promotion"}},"/campaigns/{campaignId}/executions":{"get":{"operationId":"CampaignExecutionsController_list","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CampaignExecutionDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"List Campaign Executions"}},"/campaigns/{campaignId}/executions/{executionId}":{"get":{"operationId":"CampaignExecutionsController_getDetail","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignExecutionDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Get Campaign Execution"}},"/campaigns/{campaignId}/executions/{executionId}/analytics":{"get":{"operationId":"CampaignExecutionsController_analytics","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CampaignExecutionAnalyticsDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Get Execution Analytics"}},"/campaigns/{campaignId}/executions/{executionId}/click-analytics":{"get":{"operationId":"CampaignExecutionsController_clickAnalytics","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Click Analytics"}},"/campaigns/{campaignId}/executions/{executionId}/contact-clicks":{"get":{"operationId":"CampaignExecutionsController_contactClicks","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Contact Clicks"}},"/campaigns/{campaignId}/executions/{executionId}/messages":{"get":{"operationId":"CampaignExecutionsController_getMessages","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CampaignMessageDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Get Messages"}},"/campaigns/{campaignId}/executions/{executionId}/remove-from-segment":{"post":{"operationId":"CampaignExecutionsController_removeFromSegment","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveFromSegmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Remove From Segment"}},"/campaigns/{campaignId}/executions/{executionId}/add-to-segment":{"post":{"operationId":"CampaignExecutionsController_addToSegment","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddRecipientsToSegmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Add To Segment"}},"/campaigns/{campaignId}/executions/{executionId}/add-tags":{"post":{"operationId":"CampaignExecutionsController_addTags","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddTagsToRecipientsDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Tag the selected recipients' contacts. Needs contact-edit on top of campaign\nread — the same permission (and write entitlement) as tagging from the\ncontacts list, since that is the code path it writes through.","tags":["Campaigns"]}},"/campaigns/{campaignId}/executions/{executionId}/messages/export":{"post":{"operationId":"CampaignExecutionsController_exportMessages","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportRecipientsDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"string"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Recipient CSV. Returns the raw body rather than the `ApiResponse` envelope\n— the browser downloads it directly. The BOM makes Excel read it as UTF-8\ninstead of mangling non-ASCII names.","tags":["Campaigns"]}},"/campaigns/{campaignId}/executions/{executionId}/cancel":{"post":{"operationId":"CampaignExecutionsController_cancel","parameters":[{"name":"campaignId","required":true,"in":"path","schema":{"type":"string"}},{"name":"executionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Campaigns"],"summary":"Cancel Campaign Execution"}},"/email-templates":{"post":{"operationId":"EmailTemplatesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailTemplateDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"Create Email Template"},"get":{"operationId":"EmailTemplatesController_list","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"category","required":false,"in":"query","schema":{"type":"string","enum":["MARKETING","WELCOME","GENERAL","NEWSLETTER","PROMOTIONAL","ANNOUNCEMENT","TRANSACTIONAL","EVENT"]}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","ARCHIVED","DRAFT"]}},{"name":"favoriteOnly","required":false,"in":"query","description":"Restricts the list to templates the caller has favorited. Defaults to\n `false` (all accessible templates) when omitted.","schema":{"type":"boolean"}},{"name":"includeSystem","required":true,"in":"query","description":"Defaults to `true`: most callers (e.g. the campaign composer's template\npicker) want system templates folded into the result set. Pass\n`?includeSystem=false` to scope results to the org's own templates only.","schema":{"default":true,"type":"boolean"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailTemplateListResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"List Email Templates"}},"/email-templates/categories":{"get":{"operationId":"EmailTemplatesController_listCategories","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"List Categories"}},"/email-templates/preview":{"post":{"operationId":"EmailTemplatesController_preview","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewEmailTemplateDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"Preview Email Template"}},"/email-templates/{id}":{"get":{"operationId":"EmailTemplatesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/EmailTemplateDetailResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"Get Email Template By ID"},"patch":{"operationId":"EmailTemplatesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailTemplateDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"Update Email Template"},"delete":{"operationId":"EmailTemplatesController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"Delete Email Template"}},"/email-templates/{id}/duplicate":{"post":{"operationId":"EmailTemplatesController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateEmailTemplateDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"Duplicate Email Template"}},"/email-templates/{id}/favorite":{"put":{"operationId":"EmailTemplatesController_favorite","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"Favorite Email Template"},"delete":{"operationId":"EmailTemplatesController_unfavorite","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Email Templates"],"summary":"Unfavorite Email Template"}},"/short-links":{"post":{"operationId":"ShortLinksController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateShortLinkDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Create Short Link"},"get":{"operationId":"ShortLinksController_list","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","EXPIRED"]}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["title","originalUrl","clickCount","uniqueClickCount","createdAt","expiresAt"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"List Short Links"}},"/short-links/stats":{"get":{"operationId":"ShortLinksController_stats","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Stats Short Link"}},"/short-links/{id}":{"get":{"operationId":"ShortLinksController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Get Short Link By ID"},"patch":{"operationId":"ShortLinksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateShortLinkDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Update Short Link"},"delete":{"operationId":"ShortLinksController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Delete Short Link"}},"/short-links/{id}/analytics":{"get":{"operationId":"ShortLinksController_analytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"range","required":true,"in":"query","schema":{"default":"7d","type":"string","enum":["all","7d","30d","2mo"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Analytics Short Link"}},"/short-links/{id}/qr":{"post":{"operationId":"ShortLinksController_generateQr","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Generate QR"}},"/short-links/{id}/qr-url":{"get":{"operationId":"ShortLinksController_getQrUrl","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Get QR URL"}},"/short-links/{id}/qr-download":{"get":{"operationId":"ShortLinksController_downloadQr","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Download QR"}},"/short-links/{id}/qr-stats":{"get":{"operationId":"ShortLinksController_getQrStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Short Links"],"summary":"Get QR Stats"}},"/short-links/resolve/{code}":{"get":{"operationId":"ShortLinksResolveController_resolve","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}},{"name":"v","required":false,"in":"query","schema":{}},{"name":"qr","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Short Links"],"summary":"Resolve Short Links Resolve"}},"/short-links/resolve/{code}/{token}":{"get":{"operationId":"ShortLinksResolveController_resolveWithToken","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}},{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"v","required":false,"in":"query","schema":{}},{"name":"qr","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Short Links"],"summary":"Resolve With Token"}},"/tickets":{"post":{"operationId":"TicketsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTicketDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Create Ticket"},"get":{"operationId":"TicketsController_findAll","parameters":[{"name":"search","required":false,"in":"query","description":"Matches subject/description; `TCK-123` / `#123` / `123` also match the ticket number.","schema":{"maxLength":200,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["OPEN","CLOSED","IN_PROGRESS","REOPENED","RESOLVED"]}}},{"name":"priority","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["LOW","HIGH","URGENT","MEDIUM"]}}},{"name":"assigneeIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string"}}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"dueFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"dueTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"overdue","required":false,"in":"query","description":"dueAt < now AND status NOT IN (RESOLVED, CLOSED).","schema":{"type":"boolean"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","updatedAt","dueAt","priority","status","ticketNumber","subject"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"List Tickets"}},"/tickets/escalate":{"post":{"operationId":"TicketsController_escalate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalateTicketDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Escalate Ticket"}},"/tickets/export":{"get":{"operationId":"TicketsController_exportCsv","parameters":[{"name":"search","required":false,"in":"query","description":"Matches subject/description; `TCK-123` / `#123` / `123` also match the ticket number.","schema":{"maxLength":200,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["OPEN","CLOSED","IN_PROGRESS","REOPENED","RESOLVED"]}}},{"name":"priority","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["LOW","HIGH","URGENT","MEDIUM"]}}},{"name":"assigneeIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string"}}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"dueFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"dueTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"overdue","required":false,"in":"query","description":"dueAt < now AND status NOT IN (RESOLVED, CLOSED).","schema":{"type":"boolean"}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","updatedAt","dueAt","priority","status","ticketNumber","subject"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Tickets CSV, STREAMED, honouring the current list filters.\n\nDeclared before any `:id` route so 'export' is not captured as a ticket\nid. Gated on TICKETS_READ, matching every other read here and the same\nrule the contacts and segments exports follow.","tags":["Tickets"]}},"/tickets/board":{"get":{"operationId":"TicketsController_getBoard","parameters":[{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":50,"default":25,"type":"number"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"priority","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["LOW","HIGH","URGENT","MEDIUM"]}}},{"name":"assigneeIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string"}}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"dueFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"dueTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"createdTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"overdue","required":false,"in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Get Board"}},"/tickets/{id}":{"get":{"operationId":"TicketsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Get Ticket By ID"},"patch":{"operationId":"TicketsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTicketDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Update Ticket"},"delete":{"operationId":"TicketsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Delete Ticket"}},"/tickets/{id}/activity":{"get":{"operationId":"TicketsController_getActivity","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"types","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["TAG_ADDED","TAG_REMOVED","STATUS_CHANGED","PRIORITY_CHANGED","COMMENT_ADDED","COMMENT_UPDATED","COMMENT_DELETED","ATTACHMENT_ADDED","ATTACHMENT_REMOVED","CUSTOM_FIELDS_UPDATED","TICKET_CREATED","TICKET_UPDATED","ASSIGNEE_CHANGED","DUE_DATE_CHANGED","TICKET_DELETED"]}}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Get Activity"}},"/tickets/{id}/status":{"patch":{"operationId":"TicketsController_changeStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeTicketStatusDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Change Status"}},"/tickets/{id}/tags":{"post":{"operationId":"TicketsController_addTags","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageTicketTagsDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Add Tags"}},"/tickets/{id}/tags/{tagId}":{"delete":{"operationId":"TicketsController_removeTag","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"tagId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Remove Tag"}},"/tickets/{ticketId}/comments":{"get":{"operationId":"TicketCommentsController_findAll","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"List Ticket Comments"},"post":{"operationId":"TicketCommentsController_create","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTicketCommentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Create Ticket Comment"}},"/tickets/{ticketId}/comments/{commentId}":{"patch":{"operationId":"TicketCommentsController_update","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}},{"name":"commentId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTicketCommentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Update Ticket Comment"},"delete":{"operationId":"TicketCommentsController_remove","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}},{"name":"commentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Delete Ticket Comment"}},"/tickets/{ticketId}/attachments/upload-url":{"post":{"operationId":"TicketAttachmentsController_getUploadUrl","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAttachmentUploadUrlDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Get Upload URL"}},"/tickets/{ticketId}/attachments":{"post":{"operationId":"TicketAttachmentsController_confirm","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmAttachmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Confirm Ticket Attachment"},"get":{"operationId":"TicketAttachmentsController_findAll","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"List Ticket Attachments"}},"/tickets/{ticketId}/attachments/{attachmentId}/download-url":{"get":{"operationId":"TicketAttachmentsController_getDownloadUrl","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}},{"name":"attachmentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Get Download URL"}},"/tickets/{ticketId}/attachments/{attachmentId}":{"delete":{"operationId":"TicketAttachmentsController_remove","parameters":[{"name":"ticketId","required":true,"in":"path","schema":{"type":"string"}},{"name":"attachmentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Tickets"],"summary":"Delete Ticket Attachment"}},"/meeting-types":{"post":{"operationId":"MeetingTypesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMeetingTypeDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"Create Meeting Type"},"get":{"operationId":"MeetingTypesController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","ARCHIVED"]}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/MeetingTypeResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"List Meeting Types"}},"/meeting-types/host-conferencing":{"get":{"operationId":"MeetingTypesController_hostConferencing","parameters":[{"name":"userIds","required":true,"in":"query","schema":{"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"What the given hosts' calendars allow — read by the meeting type form so\na Google Meet / Teams location the hosts cannot serve is caught as it is\nchosen, not with \"no connected calendar\" at the final Save.","tags":["Meeting Types"]}},"/meeting-types/slug-availability":{"get":{"operationId":"MeetingTypesController_slugAvailability","parameters":[{"name":"slug","required":true,"in":"query","schema":{"maxLength":100,"type":"string"}},{"name":"excludeId","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"Slug Availability"}},"/meeting-types/{id}":{"get":{"operationId":"MeetingTypesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/MeetingTypeResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"Get Meeting Type By ID"},"patch":{"operationId":"MeetingTypesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMeetingTypeDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"Update Meeting Type"},"delete":{"operationId":"MeetingTypesController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"Delete Meeting Type"}},"/meeting-types/{id}/archive":{"post":{"operationId":"MeetingTypesController_archive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"Archive Meeting Type"}},"/meeting-types/{id}/activate":{"post":{"operationId":"MeetingTypesController_activate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"Activate Meeting Type"}},"/meeting-types/{id}/duplicate":{"post":{"operationId":"MeetingTypesController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"Duplicate Meeting Type"}},"/availability/schedules":{"get":{"operationId":"AvailabilityController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/AvailabilityScheduleResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Availability"],"summary":"List Availabilities"},"post":{"operationId":"AvailabilityController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAvailabilityScheduleDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Availability"],"summary":"Create Availability"}},"/availability/schedules/{id}":{"get":{"operationId":"AvailabilityController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/AvailabilityScheduleResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Availability"],"summary":"Get Availability By ID"},"patch":{"operationId":"AvailabilityController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAvailabilityScheduleDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Availability"],"summary":"Update Availability"},"delete":{"operationId":"AvailabilityController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Availability"],"summary":"Delete Availability"}},"/availability/schedules/{id}/overrides":{"put":{"operationId":"AvailabilityController_replaceOverrides","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertOverridesDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Availability"],"summary":"Replace Overrides"}},"/bookings/export":{"get":{"operationId":"BookingsController_exportCsv","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["SCHEDULED","CANCELLED","COMPLETED","CONFIRMED","RESCHEDULED","NO_SHOW"]}},{"name":"hostUserId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"meetingTypeId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"contactId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"from","required":false,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":false,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"outcomeCategory","required":false,"in":"query","schema":{"type":"string","enum":["PENDING","LOST","NOT_QUALIFIED","NO_SHOW","PRESENTED_NO_SALE","WON"]}},{"name":"outcomeId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Bookings CSV, STREAMED, on the current list filters.\n\nDeclared before `:id` so 'export' is not captured as a booking id.\nBOOKINGS_READ, matching every other read here.","tags":["Bookings"]}},"/bookings/slots":{"get":{"operationId":"BookingsController_staffSlots","parameters":[{"name":"meetingTypeId","required":true,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"from","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"timezone","required":true,"in":"query","schema":{"maxLength":50,"type":"string"}},{"name":"hostUserId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Suggested times for \"Add appointment\". Declared before `:id` so 'slots'\nis not captured as a booking id.","tags":["Bookings"]}},"/bookings":{"post":{"operationId":"BookingsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateStaffBookingDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/BookingResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"A team member adds an appointment for a customer (no public page involved).","tags":["Bookings"]},"get":{"operationId":"BookingsController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["SCHEDULED","CANCELLED","COMPLETED","CONFIRMED","RESCHEDULED","NO_SHOW"]}},{"name":"hostUserId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"meetingTypeId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"contactId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"from","required":false,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":false,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"outcomeCategory","required":false,"in":"query","schema":{"type":"string","enum":["PENDING","LOST","NOT_QUALIFIED","NO_SHOW","PRESENTED_NO_SALE","WON"]}},{"name":"outcomeId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/BookingResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bookings"],"summary":"List Bookings"}},"/bookings/{id}":{"get":{"operationId":"BookingsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/BookingResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bookings"],"summary":"Get Booking By ID"}},"/bookings/{id}/reschedule-slots":{"get":{"operationId":"BookingsController_rescheduleSlots","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"timezone","required":true,"in":"query","schema":{"maxLength":50,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Slot options for rescheduling this booking. Distinct from the public\n`/book/:orgSlug/:meetingSlug/slots` listing: that one has no idea which\nbooking is being moved, so it counts it as busy and offers a grid the\nreschedule then rejects. This one excludes it.","tags":["Bookings"]}},"/bookings/{id}/cancel":{"post":{"operationId":"BookingsController_cancel","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBookingDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bookings"],"summary":"Cancel Booking"}},"/bookings/{id}/complete":{"post":{"operationId":"BookingsController_complete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteBookingDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bookings"],"summary":"Complete Booking"}},"/bookings/{id}/outcome":{"post":{"operationId":"BookingsController_markOutcome","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkOutcomeDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bookings"],"summary":"Mark Outcome"}},"/bookings/{id}/no-show":{"post":{"operationId":"BookingsController_markNoShow","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bookings"],"summary":"Mark No Show"}},"/bookings/{id}/reschedule":{"post":{"operationId":"BookingsController_reschedule","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageRescheduleDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bookings"],"summary":"Reschedule Booking"}},"/calendar/events":{"get":{"operationId":"CalendarFeedController_events","parameters":[{"name":"from","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"userIds","required":false,"in":"query","description":"Comma-separated user ids (`?userIds=a,b`) or repeated params.","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Show exactly these statuses (`?status=A,B`, or a single one). Omitted means\nthe ACTIVE calendar — cancelled and superseded meetings are hidden until\nasked for by name.","schema":{"type":"array","items":{"type":"string","enum":["SCHEDULED","CANCELLED","COMPLETED","CONFIRMED","RESCHEDULED","NO_SHOW"]}}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Calendar"],"summary":"Events Calendar Feed"}},"/calendar/blocks":{"get":{"operationId":"CalendarBlocksController_list","parameters":[{"name":"from","required":true,"in":"query","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/CalendarBlockResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Calendar"],"summary":"List Calendar Blocks"},"post":{"operationId":"CalendarBlocksController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCalendarBlockDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CalendarBlockResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Calendar"],"summary":"Create Calendar Block"}},"/calendar/blocks/{id}":{"patch":{"operationId":"CalendarBlocksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCalendarBlockDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/CalendarBlockResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Calendar"],"summary":"Update Calendar Block"},"delete":{"operationId":"CalendarBlocksController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Calendar"],"summary":"Delete Calendar Block"}},"/book/manage/{token}":{"get":{"operationId":"SchedulingPublicController_getManageView","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Booking"],"summary":"Get Manage View"}},"/book/manage/{token}/slots":{"get":{"operationId":"SchedulingPublicController_getManagedSlots","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"timezone","required":true,"in":"query","schema":{"maxLength":50,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Slot options for the invitee's own reschedule. Distinct from the\n`:orgSlug/:meetingSlug` listing, which counts this booking as busy and\ntherefore hides the times around it — including its own current slot.","tags":["Public — Booking"]}},"/book/manage/{token}/calendar.ics":{"get":{"operationId":"SchedulingPublicController_downloadIcs","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Raw RFC5545 bytes — skips the JSON envelope. Declared alongside the other\n`manage/:token` literals so it never binds as an org slug.","tags":["Public — Booking"]}},"/book/manage/{token}/cancel":{"post":{"operationId":"SchedulingPublicController_cancelByToken","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageCancelDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Booking"],"summary":"Cancel By Token"}},"/book/manage/{token}/reschedule":{"post":{"operationId":"SchedulingPublicController_rescheduleByToken","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManageRescheduleDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Booking"],"summary":"Reschedule By Token"}},"/book/{orgSlug}/{meetingSlug}":{"get":{"operationId":"SchedulingPublicController_getConfig","parameters":[{"name":"orgSlug","required":true,"in":"path","schema":{"type":"string"}},{"name":"meetingSlug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/PublicBookingConfigDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Booking"],"summary":"Get Config"},"post":{"operationId":"SchedulingPublicController_createBooking","parameters":[{"name":"orgSlug","required":true,"in":"path","schema":{"type":"string"}},{"name":"meetingSlug","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePublicBookingDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Booking"],"summary":"Create Booking"}},"/book/{orgSlug}/{meetingSlug}/slots":{"get":{"operationId":"SchedulingPublicController_getSlots","parameters":[{"name":"orgSlug","required":true,"in":"path","schema":{"type":"string"}},{"name":"meetingSlug","required":true,"in":"path","schema":{"type":"string"}},{"name":"from","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"to","required":true,"in":"query","schema":{"format":"date-time","type":"string"}},{"name":"timezone","required":true,"in":"query","schema":{"maxLength":50,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Booking"],"summary":"Get Slots"}},"/book/{orgSlug}/{meetingSlug}/service-area":{"get":{"operationId":"SchedulingPublicController_checkServiceArea","parameters":[{"name":"orgSlug","required":true,"in":"path","schema":{"type":"string"}},{"name":"meetingSlug","required":true,"in":"path","schema":{"type":"string"}},{"name":"postalCode","required":true,"in":"query","schema":{"minLength":1,"maxLength":20,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Is this ZIP inside the type's accepted areas? `inside: null` means it\ncould not be decided — the page lets the visitor through. Which area\nmatched stays server-side.","tags":["Public — Booking"]}},"/book/{orgSlug}/{meetingSlug}/outside-area":{"post":{"operationId":"SchedulingPublicController_requestOutsideArea","parameters":[{"name":"orgSlug","required":true,"in":"path","schema":{"type":"string"}},{"name":"meetingSlug","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutsideAreaRequestDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Booking"],"summary":"Request Outside Area"}},"/calendar-integrations/providers":{"get":{"operationId":"CalendarIntegrationsController_listProviders","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Providers","tags":["Calendar Integrations"]}},"/calendar-integrations/{provider}/authorize":{"get":{"operationId":"CalendarIntegrationsController_getAuthorizeUrl","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Authorize URL","tags":["Calendar Integrations"],"description":"Entitlement-gated up front so a plan without calendar_connections (or at its cap) is told BEFORE being bounced through the provider's OAuth flow."}},"/calendar-integrations/connections":{"get":{"operationId":"CalendarIntegrationsController_listConnections","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Connections","tags":["Calendar Integrations"]}},"/calendar-integrations/connections/{id}/refresh-calendars":{"post":{"operationId":"CalendarIntegrationsController_refreshCalendars","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Refresh Calendars","tags":["Calendar Integrations"]}},"/calendar-integrations/connections/{id}/calendars":{"patch":{"operationId":"CalendarIntegrationsController_updateSelection","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCalendarSelectionDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Update Selection","tags":["Calendar Integrations"]}},"/calendar-integrations/connections/{id}":{"delete":{"operationId":"CalendarIntegrationsController_disconnect","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Disconnect Calendar Integration","tags":["Calendar Integrations"]}},"/calendar-integrations/{provider}/callback":{"get":{"operationId":"CalendarOAuthCallbackController_handleCallback","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"error","required":false,"in":"query","schema":{}},{"name":"state","required":false,"in":"query","schema":{}},{"name":"code","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Calendar Integrations"],"summary":"Handle Callback"}},"/webhooks/calendar/google":{"post":{"operationId":"CalendarWebhookController_handleGoogle","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Handle Google"}},"/webhooks/calendar/microsoft":{"post":{"operationId":"CalendarWebhookController_handleMicrosoft","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Handle Microsoft"}},"/outcome-sets":{"get":{"operationId":"OutcomeSetsController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/OutcomeSetResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Outcome Sets"],"summary":"List Outcome Sets"},"post":{"operationId":"OutcomeSetsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOutcomeSetDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/OutcomeSetResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Outcome Sets"],"summary":"Create Outcome Set"}},"/outcome-sets/{id}":{"patch":{"operationId":"OutcomeSetsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOutcomeSetDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/OutcomeSetResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Outcome Sets"],"summary":"Update Outcome Set"},"delete":{"operationId":"OutcomeSetsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Outcome Sets"],"summary":"Delete Outcome Set"}},"/outcome-sets/{id}/outcomes":{"put":{"operationId":"OutcomeSetsController_replaceOutcomes","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceOutcomesDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/OutcomeSetResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Outcome Sets"],"summary":"Replace Outcomes"}},"/service-areas":{"get":{"operationId":"ServiceAreasController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/ServiceAreaResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Service Areas"],"summary":"List Service Areas"},"post":{"operationId":"ServiceAreasController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertServiceAreaDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ServiceAreaResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Service Areas"],"summary":"Create Service Area"}},"/service-areas/{id}":{"patch":{"operationId":"ServiceAreasController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertServiceAreaDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ServiceAreaResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Service Areas"],"summary":"Update Service Area"},"delete":{"operationId":"ServiceAreasController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Service Areas"],"summary":"Delete Service Area"}},"/ai-employees":{"post":{"operationId":"AiAgentsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"No `resource: AI_AGENTS` gate — deliberately. An employee is created DRAFT\nand the `ai_agents` gauge counts ACTIVE only, so this route occupies\nnothing; the coarse remaining-check would reject a free draft with 50002\nonce an org's live slots are full (or 50003 on a plan carrying no\n`ai_agents` limit at all). The slot is gated where it is actually taken,\nin `activate()`. Same shape as the free-draft create in\n`lead-forms.controller.ts`. `requiresWrite` stays, so the LOCKED/PAUSED\nstatus gate and the breaker's fail-closed behaviour are unchanged.","tags":["AiAgents"]},"get":{"operationId":"AiAgentsController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","DRAFT","DISABLED"]}},{"name":"search","required":false,"in":"query","schema":{"maxLength":120,"type":"string"}},{"name":"templateKey","required":false,"in":"query","description":"Employee type filter — a job-template key (`?templateKey=receptionist`).","schema":{"type":"string","enum":["receptionist","sales_representative","lead_qualification","customer_support","follow_up_specialist","appointment_scheduler","marketing_assistant","collections_officer","faq_assistant","review_collector","lead_responder","custom"]}},{"name":"kind","required":false,"in":"query","description":"Chat or voice employees only (`?kind=CHAT`) — what assignment pickers ask for.","schema":{"type":"string","enum":["VOICE","CHAT"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"List Ai Agents"}},"/ai-employees/catalog/templates":{"get":{"operationId":"AiAgentsController_catalogTemplates","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Catalog Templates"}},"/ai-employees/assist":{"post":{"operationId":"AiAgentsController_assist","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeAssistDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Ask AI on the employee setup: one field written or rewritten for the owner.","tags":["AiAgents"]}},"/ai-employees/catalog/goals":{"get":{"operationId":"AiAgentsController_catalogGoals","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The goal cards the Name & Goal step offers, with each goal's starting settings.","tags":["AiAgents"]}},"/ai-employees/catalog/follow-up-templates":{"get":{"operationId":"AiAgentsController_catalogFollowUpTemplates","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The built-in follow-up sequences Follow-ups offers to start from.","tags":["AiAgents"]}},"/ai-employees/catalog/models":{"get":{"operationId":"AiAgentsController_catalogModels","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Catalog Models"}},"/ai-employees/catalog/skills":{"get":{"operationId":"AiAgentsController_catalogSkills","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Catalog Skills"}},"/ai-employees/catalog/follow-up-sequences":{"get":{"operationId":"AiAgentsController_catalogFollowUpSequences","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The org's published, running sequences — the Start follow-up skill's\npicker (2026-10-01). Served here, under the AI-employee read permission,\nso configuring an employee needs no separate Sequences permission.","tags":["AiAgents"]}},"/ai-employees/default-assignment":{"get":{"operationId":"AiAgentsController_getDefaultAssignment","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Get Default Assignment"},"put":{"operationId":"AiAgentsController_setDefaultAssignment","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDefaultAssignmentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Set Default Assignment"}},"/ai-employees/channel-assignments/{channelIdentityId}":{"put":{"operationId":"AiAgentsController_setChannelAssignment","parameters":[{"name":"channelIdentityId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelAssignmentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Attach an AI employee to one phone number / sending address, through the\nsingle writer of who answers a channel (a stale `expectedHolderId` is a\n409). Declared BEFORE `@Get(':id')` — Nest matches routes in declaration\norder, and a literal segment registered after a `:id` param route would be\nswallowed by it.","tags":["AiAgents"]}},"/ai-employees/{id}":{"get":{"operationId":"AiAgentsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"include","required":false,"in":"query","description":"The lifetime card metrics cost four queries, so only the Overview asks for them.","schema":{"type":"string","enum":["metrics"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Get Ai Agent By ID"},"patch":{"operationId":"AiAgentsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAgentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Update Ai Agent"},"delete":{"operationId":"AiAgentsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Delete Ai Agent"}},"/ai-employees/{id}/booking-readiness":{"get":{"operationId":"AiAgentsController_bookingReadiness","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Advisory facts about whether this employee can really book today.","tags":["AiAgents"]}},"/ai-employees/{id}/setup-step":{"put":{"operationId":"AiAgentsController_saveSetupStep","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSetupStepDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The hiring wizard's progress on a draft — see `AiAgentService.saveSetupStep`.","tags":["AiAgents"]}},"/ai-employees/{id}/activate":{"post":{"operationId":"AiAgentsController_activate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivateAgentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Activate Ai Agent"}},"/ai-employees/{id}/disable":{"post":{"operationId":"AiAgentsController_disable","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Disable Ai Agent"}},"/ai-employees/{id}/pause":{"post":{"operationId":"AiAgentsController_pause","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Plain-language alias for `disable` (§12).","tags":["AiAgents"]}},"/ai-employees/{id}/resume":{"post":{"operationId":"AiAgentsController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Plain-language alias for `activate` (§12).","tags":["AiAgents"]}},"/ai-employees/{id}/duplicate":{"post":{"operationId":"AiAgentsController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Free like `create()` — the copy is inserted DRAFT and occupies no slot.","tags":["AiAgents"]}},"/ai-employees/{id}/advanced":{"get":{"operationId":"AiAgentsController_getAdvanced","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Get Advanced"},"patch":{"operationId":"AiAgentsController_updateAdvanced","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdvancedConfigDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiAgents"],"summary":"Update Advanced"}},"/ai-employees/{id}/test-chat":{"post":{"operationId":"AiAgentsController_testChat","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestChatDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Run the deep-agent sandbox against the agent's current config (§3.3).\nRead-gated: it is a dry run on an ephemeral thread — no state change, no\nsend. Returns the {@link AgentReply} + its Langfuse trace id.","tags":["AiAgents"]}},"/ai-employees/{id}/knowledge/documents-base":{"post":{"operationId":"AiEmployeeKnowledgeController_ensureDocumentsBase","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Idempotent: the employee's own documents base, created and linked on the first call.","tags":["AiEmployeeKnowledge"]}},"/ai-conversations/messages/{messageId}/feedback":{"put":{"operationId":"AiConversationsController_setMessageFeedback","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetMessageFeedbackDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Tell us an AI message was wrong (or helpful) — the one-click control on\nthe AI bubble (R7). One verdict per teammate per message: sending it\nagain is that person changing their mind, not a second opinion.\n\nGated on `inbox:reply`, not on AI control: anyone who works the inbox\nsees these messages and is exactly who knows whether the answer was\nright. No entitlement — telling us something is wrong must never depend\non a plan. A message belonging to another organisation reads as a plain\n404 (the service checks before anything is written).","tags":["AiConversations"]},"delete":{"operationId":"AiConversationsController_clearMessageFeedback","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Take that verdict back. Clearing nothing is not an error.","tags":["AiConversations"]}},"/ai-conversations/{unifiedId}/assign-agent":{"post":{"operationId":"AiConversationsController_assignAgent","parameters":[{"name":"unifiedId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignAgentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Assign (or reassign) an agent and force the conversation to AI_ACTIVE.","tags":["AiConversations"]}},"/ai-conversations/{unifiedId}/unassign-agent":{"post":{"operationId":"AiConversationsController_unassignAgent","parameters":[{"name":"unifiedId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Remove the assigned employee → `agentId` NULL + HUMAN_CONTROLLED.\n\nNo `@RequireEntitlement`, matching `pause` rather than `assign-agent`:\nturning an employee OFF must stay reachable on a lapsed plan. Gating it\nwould strand a conversation with an employee nobody can detach.","tags":["AiConversations"]}},"/ai-conversations/{unifiedId}/pause":{"post":{"operationId":"AiConversationsController_pause","parameters":[{"name":"unifiedId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Pause = human takeover → HUMAN_CONTROLLED (§7.4).","tags":["AiConversations"]}},"/ai-conversations/{unifiedId}/resume":{"post":{"operationId":"AiConversationsController_resume","parameters":[{"name":"unifiedId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Resume = manual re-enable → AI_ACTIVE, resetting the error budget (§7.4).","tags":["AiConversations"]}},"/ai-conversations/{unifiedId}/autopilot":{"post":{"operationId":"AiConversationsController_setAutopilot","parameters":[{"name":"unifiedId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAutopilotDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The composer's AI Autopilot toggle: `enabled` → AI_ACTIVE (agent replies\nautomatically); `false` → AI_SUPERVISED (replies wait for approval).\nSame-state is an idempotent no-op. Entitlement on BOTH directions\n(mirrors `resume`, not `pause`): supervised mode still runs the model on\nevery inbound — the entitlement-free kill switch remains `pause`.","tags":["AiConversations"]}},"/ai-conversations/{unifiedId}/pending-reply":{"get":{"operationId":"AiConversationsController_getPendingReply","parameters":[{"name":"unifiedId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The conversation's supervised-mode reply awaiting approval — `null` when\nnothing is pending. Same guard shape as `getState` (a read); serialized\nas the same snapshot the `inbox:ai:pending-reply` socket event carries.","tags":["AiConversations"]}},"/ai-conversations/pending-replies/{id}/approve":{"post":{"operationId":"AiConversationsController_approvePendingReply","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Approve & Send a parked reply — sends as the AI agent through the normal\ninbox send path, on the draft's own channel (SMS or WhatsApp). 409\n(`AI_PENDING_REPLY_NOT_PENDING`) when someone already handled it.\n\nGuards mirror the channel-generic human send route: `INBOX_REPLY` plus\nthe write-block only. The per-channel quota (sms_sends, whatsapp_sends)\nis consumed INSIDE the send service by the channel billing hooks — a\nstatic `sms_sends` guard here rejected WhatsApp drafts on plans with no\nSMS quota. Plus the AI control permission; no `feature` entitlement — a\nlapsed org may still flush already-generated drafts.","tags":["AiConversations"]}},"/ai-conversations/pending-replies/{id}/discard":{"post":{"operationId":"AiConversationsController_discardPendingReply","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscardPendingReplyDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Discard a parked reply, saying which decision it was: `EDITED` (the\nbanner's Edit action, after the text lands in the composer) or `REJECTED`\n(the draft was wrong). No entitlement — mirrors `pause`: dismissing must\nstay available with a lapsed entitlement.","tags":["AiConversations"]}},"/ai-conversations/{unifiedId}/state":{"get":{"operationId":"AiConversationsController_getState","parameters":[{"name":"unifiedId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Current AI state for a conversation (null if AI was never engaged).","tags":["AiConversations"]}},"/ai-conversations/{unifiedId}/goal":{"get":{"operationId":"AiConversationsController_getGoal","parameters":[{"name":"unifiedId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The conversation's latest goal state (spec §5.4/§7), any status — `null`\nwhen no goal was ever started. Same permission/entitlement shape as\n`getState` (a read).","tags":["AiConversations"]}},"/ai-conversations/{unifiedId}/goal/complete":{"post":{"operationId":"AiConversationsController_completeGoal","parameters":[{"name":"unifiedId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Human \"Mark complete\" (spec §5.4) — completes the conversation's active\ngoal (`GoalCompletionSource.HUMAN`). No `@RequireEntitlement`: mirrors\n`pause`, not `resume`/`assignAgent` — closing out an existing goal is an\noperator action, not re-enabling the paid AI capability, so it must stay\navailable even if entitlement has lapsed. Throws a friendly 409 when the\ngoal is already finished (`GoalStateService.completeByHuman`).","tags":["AiConversations"]}},"/ai-handover-rules":{"get":{"operationId":"AiHandoverRulesController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"agentId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"enabled","required":false,"in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiHandoverRules"],"summary":"List Ai Handover Rules"},"post":{"operationId":"AiHandoverRulesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateHandoverRuleDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiHandoverRules"],"summary":"Create Ai Handover Rule"}},"/ai-handover-rules/{id}":{"patch":{"operationId":"AiHandoverRulesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateHandoverRuleDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiHandoverRules"],"summary":"Update Ai Handover Rule"},"delete":{"operationId":"AiHandoverRulesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiHandoverRules"],"summary":"Delete Ai Handover Rule"}},"/ai-runs":{"get":{"operationId":"AiRunsController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"agentId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"conversationId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["QUEUED","FAILED","COMPLETED","RUNNING","SKIPPED","HANDED_OVER"]}},{"name":"outcome","required":false,"in":"query","schema":{"type":"string","enum":["HANDOVER","REPLY","NOOP"]}},{"name":"from","required":false,"in":"query","description":"Inclusive lower bound on the run's `createdAt`.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Inclusive upper bound on the run's `createdAt`.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Free text matched against the customer's message and the contact.","schema":{"maxLength":200,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiRuns"],"summary":"List Ai Runs"}},"/ai-runs/{id}":{"get":{"operationId":"AiRunsController_getOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"One run's full execution record — the exchange, the goal, the skills\nfired, the knowledge sources, and the error. Fetched lazily by the\nActivity drawer so a page of list rows stays light.","tags":["AiRuns"]}},"/ai-employees/{id}/monitor/summary":{"get":{"operationId":"AiEmployeeMonitorController_summary","parameters":[{"name":"id","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":"channel","required":false,"in":"query","schema":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiEmployeeMonitor"],"summary":"Summary Ai Employee Monitor"}},"/ai-employees/{id}/monitor/conversations":{"get":{"operationId":"AiEmployeeMonitorController_conversations","parameters":[{"name":"id","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":"channel","required":false,"in":"query","schema":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]}},{"name":"search","required":false,"in":"query","schema":{"maxLength":100,"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AiEmployeeMonitor"],"summary":"Conversations Ai Employee Monitor"}},"/knowledge-bases":{"post":{"operationId":"KnowledgeBasesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKnowledgeBaseDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KnowledgeBases"],"summary":"Create Knowledge Base"},"get":{"operationId":"KnowledgeBasesController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KnowledgeBases"],"summary":"List Knowledge Bases"}},"/knowledge-bases/{kbId}":{"get":{"operationId":"KnowledgeBasesController_findById","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KnowledgeBases"],"summary":"Get Knowledge Base By ID"},"patch":{"operationId":"KnowledgeBasesController_update","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKnowledgeBaseDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KnowledgeBases"],"summary":"Update Knowledge Base"},"delete":{"operationId":"KnowledgeBasesController_remove","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KnowledgeBases"],"summary":"Delete Knowledge Base"}},"/knowledge-bases/{kbId}/search-preview":{"post":{"operationId":"KnowledgeBasesController_searchPreview","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchPreviewDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Retrieval preview — run a question through this KB's own retrieval and see\nthe passages an AI employee would get, with scores.\n\nPOST because the body carries a question, not because it mutates: it is a\nread, gated on `KNOWLEDGE_BASES_READ`, and declared ABOVE the `:kbId`\nPATCH/DELETE handlers for the same declaration-order reason\n`kb-sources.controller.ts` documents.","tags":["KnowledgeBases"]}},"/knowledge-bases/{kbId}/sources/upload-url":{"post":{"operationId":"KbSourcesController_getUploadUrl","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSourceUploadUrlDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Get Upload URL"}},"/knowledge-bases/{kbId}/sources/file":{"post":{"operationId":"KbSourcesController_createFile","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFileSourceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Create File"}},"/knowledge-bases/{kbId}/sources/text":{"post":{"operationId":"KbSourcesController_createText","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTextSourceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Create Text"}},"/knowledge-bases/{kbId}/sources/website":{"post":{"operationId":"KbSourcesController_createWebsite","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebsiteSourceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Create Website"}},"/knowledge-bases/{kbId}/sources":{"get":{"operationId":"KbSourcesController_list","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"List Kb Sources"}},"/knowledge-bases/{kbId}/sources/{sourceId}/content":{"get":{"operationId":"KbSourcesController_getContent","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}},{"name":"sourceId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Get Content"}},"/knowledge-bases/{kbId}/sources/{sourceId}/download-url":{"get":{"operationId":"KbSourcesController_getDownloadUrl","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}},{"name":"sourceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Get Download URL"}},"/knowledge-bases/{kbId}/sources/{sourceId}":{"get":{"operationId":"KbSourcesController_findById","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}},{"name":"sourceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Get Kb Source By ID"},"patch":{"operationId":"KbSourcesController_update","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}},{"name":"sourceId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKbSourceDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Update Kb Source"},"delete":{"operationId":"KbSourcesController_remove","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}},{"name":"sourceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Delete Kb Source"}},"/knowledge-bases/{kbId}/sources/{sourceId}/resync":{"post":{"operationId":"KbSourcesController_resync","parameters":[{"name":"kbId","required":true,"in":"path","schema":{"type":"string"}},{"name":"sourceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["KbSources"],"summary":"Resync Kb Source"}},"/inbox/unified-conversations":{"get":{"operationId":"InboxController_list","parameters":[{"name":"tab","required":false,"in":"query","schema":{"type":"string","enum":["all","read","unread","archived","assigned_to_me"]}},{"name":"channel","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]}}},{"name":"assignedTo","required":false,"in":"query","description":"Either a real user UUID or the literal `'unassigned'` (filters to rows\nwith no assignee). `@IsUUID()` alone would reject the sentinel, so we\naccept both via a regex.","schema":{"pattern":"^(unassigned|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$","type":"string"}},{"name":"tagIds","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"contactIds","required":false,"in":"query","description":"Narrow to specific contacts (the drawer's email / number pickers resolve\nwhat the user typed to contact ids before it reaches the wire). Capped\nbecause each id widens an `IN (…)` list.","schema":{"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"dateFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"hasUnread","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"status","required":false,"in":"query","description":"Lifecycle status, multi-select (OR within the group). Accepts a repeated\n`status=` param or one comma-joined value — same shape the contacts list\nuses for `stage`.","schema":{"type":"array","items":{"type":"string","enum":["OPEN","PENDING","CLOSED","SNOOZED","SPAM","TRASH"]}}},{"name":"stage","required":false,"in":"query","description":"Contact sales stage, multi-select (OR within the group). Filters through\nthe `contact` relation — see the repository's note on merging into\n`where.contact` rather than assigning it.","schema":{"type":"array","items":{"type":"string","enum":["ARCHIVED","NEW_LEAD","ENGAGED","QUALIFIED","APPOINTMENT_BOOKED","CUSTOMER","LOST","BOOKING_PENDING","ESTIMATE_GIVEN","DECIDING","NOT_QUALIFIED"]}}},{"name":"isPinned","required":false,"in":"query","description":"Pinned-only view. `false` is accepted and means \"unpinned only\".","schema":{"type":"boolean"}},{"name":"isStarred","required":false,"in":"query","description":"Starred-only view: conversations holding a message the REQUESTING user\nstarred. Stars are per user, so teammates get different rows. Only\n`true` filters; `false` is accepted and ignored.","schema":{"type":"boolean"}},{"name":"replyState","required":false,"in":"query","schema":{"type":"string","enum":["needs_reply","waiting_for_customer"]}},{"name":"q","required":false,"in":"query","schema":{"minLength":2,"maxLength":255,"type":"string"}},{"name":"cursor","required":false,"in":"query","schema":{"maxLength":255,"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"type":"number"}},{"name":"sortOrder","required":false,"in":"query","description":"Direction of the `lastMessageAt` ordering on the list. `'newest'` (default)\nsurfaces the most recently active conversation at the top; `'oldest'`\nsurfaces the least recently active conversation at the top. The cursor\npredicate is flipped accordingly in the repository.","schema":{"type":"string","enum":["newest","oldest"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/UnifiedConversationListResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List unified conversations","tags":["Inbox"]}},"/inbox/muted-conversation-ids":{"get":{"operationId":"InboxController_listMutedConversationIds","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"type":"string"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List the current user's muted conversation ids","tags":["Inbox"]}},"/inbox/unified-conversations/by-contact/{contactId}":{"get":{"operationId":"InboxController_getUnifiedByContact","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/UnifiedByContactResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Look up a contact's unified conversation","tags":["Inbox"]}},"/inbox/unified-conversations/resolve":{"post":{"operationId":"InboxController_resolveUnifiedConversation","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveUnifiedConversationDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ResolveUnifiedResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Find or create the unified conversation for a contact","tags":["Inbox"]}},"/inbox/unified-conversations/{id}":{"get":{"operationId":"InboxController_getDetail","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/UnifiedConversationDetailDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get a unified conversation with notes","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/messages":{"get":{"operationId":"InboxController_listMessages","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"before","required":false,"in":"query","schema":{"maxLength":255,"type":"string"}},{"name":"after","required":false,"in":"query","description":"Forward keyset cursor, same `<createdAt iso>|<messageId>` encoding as\n`before`. Returns messages strictly NEWER than the cursor.","schema":{"maxLength":255,"type":"string"}},{"name":"anchor","required":false,"in":"query","description":"Centre the page on this message (search \"jump to result\").","schema":{"format":"uuid","type":"string"}},{"name":"q","required":false,"in":"query","description":"Search within the thread. Matches body, email subject and attachment names.","schema":{"minLength":2,"maxLength":255,"type":"string"}},{"name":"channel","required":false,"in":"query","description":"Restrict to one channel. Used by thread search: the thread shows one\nchannel tab at a time, so matching across all of them would return\nresults the UI then hides — and `totalCount` would disagree with the\nlist on screen.","schema":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":200,"type":"number"}},{"name":"emailThreadId","required":false,"in":"query","description":"Narrow the read to one email subject chain (Gmail-style thread view).","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/MessageListResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List messages in a conversation","tags":["Inbox"]},"post":{"operationId":"InboxController_sendMessage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/SendMessageResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Send a message in a conversation","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/starred-messages":{"get":{"operationId":"InboxController_listStarredMessages","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/StarredMessageDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List the current user's starred messages in a conversation","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/email-threads":{"get":{"operationId":"InboxController_listEmailThreads","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/EmailThreadListResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List email subject chains in a conversation","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/messages/schedule":{"post":{"operationId":"InboxController_scheduleMessage","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleMessageDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/SendMessageResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Schedule a message for a future time","tags":["Inbox"]}},"/inbox/messages/{messageId}/schedule":{"patch":{"operationId":"InboxController_rescheduleMessage","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RescheduleMessageDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Reschedule or edit a scheduled message","tags":["Inbox"]},"delete":{"operationId":"InboxController_cancelScheduledMessage","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Cancel a scheduled message","tags":["Inbox"]}},"/inbox/messages/{messageId}/reaction":{"put":{"operationId":"InboxController_reactToMessage","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReactToMessageDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Set the workspace reaction on a WhatsApp message","tags":["Inbox"]},"delete":{"operationId":"InboxController_removeMessageReaction","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Remove the workspace reaction from a WhatsApp message","tags":["Inbox"]}},"/inbox/messages/{messageId}/star":{"put":{"operationId":"InboxController_starMessage","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Star a message for the current user","tags":["Inbox"]},"delete":{"operationId":"InboxController_unstarMessage","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Unstar a message for the current user","tags":["Inbox"]}},"/inbox/messages/{messageId}/send-now":{"post":{"operationId":"InboxController_sendScheduledNow","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Send a scheduled message immediately","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/scheduled-messages/send-now":{"post":{"operationId":"InboxController_sendAllScheduled","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Send all scheduled messages in a conversation now","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/scheduled-messages":{"delete":{"operationId":"InboxController_cancelAllScheduled","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Cancel all scheduled messages in a conversation","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/notes":{"post":{"operationId":"InboxController_sendInternalNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendInternalNoteDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ConversationNoteDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Add an internal note to a conversation","tags":["Inbox"]}},"/inbox/notes/{id}":{"patch":{"operationId":"InboxController_updateInternalNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateInternalNoteDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Edit an internal note","tags":["Inbox"]},"delete":{"operationId":"InboxController_deleteInternalNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Delete an internal note","tags":["Inbox"]}},"/inbox/note-mention-candidates":{"get":{"operationId":"InboxController_listMentionCandidates","parameters":[{"name":"search","required":false,"in":"query","description":"Optional name/email filter for the dropdown search.","schema":{"maxLength":100,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/MentionCandidateDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List teammates eligible to be @-mentioned in a note","tags":["Inbox"]}},"/inbox/contact-filter-candidates":{"get":{"operationId":"InboxController_listContactFilterCandidates","parameters":[{"name":"email","required":false,"in":"query","description":"Substring match on the contact's email. Floors at 3 characters: pg_trgm\nneeds three to build a complete trigram, so a shorter pattern cannot use\n`contacts_email_trgm_idx` and would degrade to a sequential scan.","schema":{"minLength":3,"maxLength":200,"type":"string"}},{"name":"phone","required":false,"in":"query","description":"Substring match on the contact's phone. The client sends the *national*\ndigits (dial code stripped) so a number stored as `+919875050087` is\nfound even while the picker's country selector shows a different flag.","schema":{"minLength":3,"maxLength":50,"type":"string"}},{"name":"ids","required":false,"in":"query","description":"Resolve already-selected ids back to names (chip hydration on drawer open).","schema":{"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":50,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactFilterCandidateDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Look up contacts for the filter drawer's email / number pickers","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/note-attachments/presigned-upload":{"post":{"operationId":"InboxController_createNoteAttachmentUpload","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNoteAttachmentUploadDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/NoteAttachmentUploadUrlDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get a presigned URL to upload a note attachment","tags":["Inbox"]}},"/inbox/note-attachments/{id}/presigned-url":{"get":{"operationId":"InboxController_getNoteAttachmentPresignedUrl","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/NoteAttachmentUrlResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get a presigned download URL for a note attachment","tags":["Inbox"]}},"/inbox/note-attachments/{id}/preview":{"get":{"operationId":"InboxController_getNoteAttachmentPreview","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/NoteAttachmentPreviewDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Server-rendered preview payload for a note attachment","tags":["Inbox"]}},"/inbox/email-threads/{id}/read":{"patch":{"operationId":"InboxController_markEmailThreadRead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Mark an email thread read","tags":["Inbox"]}},"/inbox/conversations/{id}/read":{"patch":{"operationId":"InboxController_markConversationRead","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkConversationReadDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Mark a conversation read","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/pin":{"patch":{"operationId":"InboxController_pin","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinUnifiedDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/PinResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Pin or unpin a conversation","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/mute":{"patch":{"operationId":"InboxController_mute","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MuteUnifiedDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/MuteResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Mute or unmute a conversation for the current user","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/archive":{"patch":{"operationId":"InboxController_archive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArchiveUnifiedDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ArchiveResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Archive or unarchive a conversation","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/assign":{"patch":{"operationId":"InboxController_assign","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignUnifiedDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/AssignResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Assign or unassign a conversation","tags":["Inbox"]}},"/inbox/unified-conversations/{id}/status":{"patch":{"operationId":"InboxController_setStatus","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetStatusDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/StatusResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Change a conversation status","tags":["Inbox"]}},"/inbox/sync":{"post":{"operationId":"InboxController_sync","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncRequestDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/InboxSyncResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Sync inbox changes since a timestamp","tags":["Inbox"]}},"/inbox/email/drafts":{"get":{"operationId":"InboxEmailController_listDrafts","parameters":[{"name":"unifiedConversationId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"origin","required":false,"in":"query","description":"Omitted means INBOX — see `EmailDraftsRepository.listForUser` for why\n that default is a safety property and not a convenience.","schema":{"default":"INBOX","type":"string","enum":["INBOX","CONTACT_COMPOSER"]}},{"name":"contactId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailDraftViewDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List the current user's email drafts (newest first)","tags":["Inbox Email"]}},"/inbox/email/drafts/{id}":{"put":{"operationId":"InboxEmailController_upsertDraft","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertEmailDraftDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Upsert an email draft (client-minted UUID id)","tags":["Inbox Email"]},"delete":{"operationId":"InboxEmailController_deleteDraft","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Delete an email draft","tags":["Inbox Email"]}},"/inbox/email/compose":{"post":{"operationId":"InboxEmailController_composeEmail","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComposeEmailDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ComposeEmailResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Compose a new email to up to 50 recipients — one email each (send or schedule)","tags":["Inbox Email"]}},"/inbox/email/subject-suggest":{"post":{"operationId":"InboxEmailController_suggestSubject","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestEmailSubjectDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/SuggestedEmailSubjectDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Write a subject line for the drafted email body (AI)","tags":["Inbox Email"]}},"/inbox/email/attachments/presign":{"post":{"operationId":"InboxEmailController_presignAttachment","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresignEmailAttachmentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/EmailAttachmentUploadUrlDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get a presigned URL to upload an outbound email attachment","tags":["Inbox Email"]}},"/inbox/messages/{id}/attachments":{"get":{"operationId":"InboxEmailController_listAttachments","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/MessageAttachmentViewDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List a message's attachments with fresh presigned GET URLs","tags":["Inbox Email"]}},"/inbox/contact-drafts":{"get":{"operationId":"ContactDraftsController_getContactDrafts","parameters":[{"name":"contactId","required":true,"in":"query","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ContactDraftsViewDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"This user's unsent drafts for one contact, both channels","tags":["Contact Drafts"]}},"/inbox/contact-drafts/{id}":{"put":{"operationId":"ContactDraftsController_upsertDraft","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertContactMessageDraftDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Upsert a text-channel contact draft (client-minted UUID id)","tags":["Contact Drafts"]},"delete":{"operationId":"ContactDraftsController_deleteDraft","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Discard a text-channel contact draft","tags":["Contact Drafts"]}},"/inbox/sms/compose":{"post":{"operationId":"InboxComposeController_composeSms","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComposeSmsDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ComposeSmsResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Send an SMS to up to 50 recipients — contacts and/or raw numbers","tags":["Inbox Compose"]}},"/inbox/whatsapp/compose":{"post":{"operationId":"InboxComposeController_composeWhatsApp","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComposeWhatsAppDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ComposeWhatsAppResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Send a WhatsApp message to up to 50 contacts","tags":["Inbox Compose"]}},"/inbox/unified-conversations/{id}/insight":{"get":{"operationId":"InboxInsightsController_getInsight","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Read this conversation's AI insight (null if never generated)","tags":["Inbox Insights"]}},"/inbox/unified-conversations/{id}/insight/refresh":{"post":{"operationId":"InboxInsightsController_refreshInsight","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Generate a fresh AI insight for this conversation (AI)","tags":["Inbox Insights"]}},"/routing-forms":{"get":{"operationId":"RoutingFormsController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","ARCHIVED"]}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/RoutingFormResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Routing Forms"],"summary":"List Routing Forms"},"post":{"operationId":"RoutingFormsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertRoutingFormDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Routing Forms"],"summary":"Create Routing Form"}},"/routing-forms/slug-availability":{"get":{"operationId":"RoutingFormsController_slugAvailability","parameters":[{"name":"slug","required":true,"in":"query","schema":{"maxLength":100,"type":"string"}},{"name":"excludeId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Routing Forms"],"summary":"Slug Availability"}},"/routing-forms/{id}":{"get":{"operationId":"RoutingFormsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/RoutingFormResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Routing Forms"],"summary":"Get Routing Form By ID"},"patch":{"operationId":"RoutingFormsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertRoutingFormDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Routing Forms"],"summary":"Update Routing Form"},"delete":{"operationId":"RoutingFormsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Routing Forms"],"summary":"Delete Routing Form"}},"/routing-forms/{id}/archive":{"post":{"operationId":"RoutingFormsController_archive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Routing Forms"],"summary":"Archive Routing Form"}},"/routing-forms/{id}/activate":{"post":{"operationId":"RoutingFormsController_activate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Routing Forms"],"summary":"Activate Routing Form"}},"/routing-forms/{id}/duplicate":{"post":{"operationId":"RoutingFormsController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Routing Forms"],"summary":"Duplicate Routing Form"}},"/book/{orgSlug}/r/{slug}":{"get":{"operationId":"RoutingFormsPublicController_getRoutingForm","parameters":[{"name":"orgSlug","required":true,"in":"path","schema":{"type":"string"}},{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/PublicRoutingFormDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Booking"],"summary":"Get Routing Form"}},"/api-keys":{"post":{"operationId":"ApiKeysController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ApiKeyCreatedDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["API Keys"],"summary":"Create API Key"},"get":{"operationId":"ApiKeysController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["API Keys"],"summary":"List API Keys"}},"/api-keys/{id}":{"get":{"operationId":"ApiKeysController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ApiKeyDetailDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["API Keys"],"summary":"Get API Key By ID"},"patch":{"operationId":"ApiKeysController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateApiKeyDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ApiKeyResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["API Keys"],"summary":"Update API Key"},"delete":{"operationId":"ApiKeysController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["API Keys"],"summary":"Delete API Key"}},"/api-keys/{id}/rotate":{"post":{"operationId":"ApiKeysController_rotate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ApiKeyCreatedDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["API Keys"],"summary":"Rotate API Key"}},"/api-keys/{id}/revoke":{"post":{"operationId":"ApiKeysController_revoke","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/ApiKeyResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["API Keys"],"summary":"Revoke API Key"}},"/auth/register":{"post":{"operationId":"AuthController_register","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterUserDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Authentication"],"summary":"Register"}},"/auth/register-via-invitation":{"post":{"operationId":"AuthController_registerViaInvitation","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterViaInvitationDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Register a brand-new user from an invitation link. Skips the personal\norg creation step that the standard /register path runs.","tags":["Authentication"]}},"/auth/login-via-invitation":{"post":{"operationId":"AuthController_loginViaInvitation","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginViaInvitationDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Sign an existing user in *and* accept their invitation in one call. Used\nby the accept-invitation page when the invited email already has an\naccount: the ordinary /login path refuses a user with no membership, so a\nuser removed from their last workspace could not otherwise sign in to\naccept.","tags":["Authentication"]}},"/auth/login":{"post":{"operationId":"AuthController_login","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginUserDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Authentication"],"summary":"Login"}},"/auth/oauth/exchange":{"post":{"operationId":"AuthController_oauthExchange","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthExchangeDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Final leg of Google / Microsoft sign-in: the SPA redeems the single-use\nticket the provider callback handed it. Lives here, not on the OAuth\ncontroller, so the session lands in the browser through the very same\ncookie helper as `/auth/login`. The `oauth_signin` browser-binding cookie\nis cleared once redeemed.","tags":["Authentication"]}},"/auth/logout":{"post":{"operationId":"AuthController_logout","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Authentication"],"summary":"Logout"}},"/auth/refresh":{"post":{"operationId":"AuthController_refresh","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Authentication"],"summary":"Refresh Access Token"}},"/auth/forgot-password":{"post":{"operationId":"AuthController_forgotPassword","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Deliberately not awaited: the reply must not vary with how long the user\nlookup and the SMTP round-trip take, or its timing tells an attacker\nwhether the address has an account. The service already swallows send\nfailures, but a throw before that point — token generation, say — would\notherwise escape as an unhandled rejection, so catch and log it here.","tags":["Authentication"]}},"/auth/reset-password/verify":{"post":{"operationId":"AuthController_verifyResetToken","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResetTokenDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Is a reset link still usable? Lets the reset screen show \"already used or\nexpired\" on open rather than a form that can only fail on submit.\n\nPOST with the token in the body, not a GET query like\n`invitations/public/verify`: this token is password-equivalent, and a\nquery string lands in access logs, proxy logs and `Referer` headers.\nThe response is a bare boolean, so it enumerates nothing.","tags":["Authentication"]}},"/auth/reset-password":{"post":{"operationId":"AuthController_resetPassword","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Authentication"],"summary":"Reset Password"}},"/auth/oauth/{provider}/start":{"get":{"operationId":"OAuthSignInController_start","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"billing","required":false,"in":"query","schema":{}},{"name":"plan","required":false,"in":"query","schema":{}},{"name":"remember","required":false,"in":"query","schema":{}},{"name":"intent","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Authentication"],"summary":"Start O Auth Sign In"}},"/auth/oauth/{provider}/callback":{"get":{"operationId":"OAuthSignInController_callback","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"error","required":false,"in":"query","schema":{}},{"name":"state","required":false,"in":"query","schema":{}},{"name":"code","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Authentication"],"summary":"Callback O Auth Sign In"}},"/invitations":{"post":{"operationId":"InvitationController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvitationDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Create Invitation"},"get":{"operationId":"InvitationController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["PENDING","EXPIRED","DECLINED","REVOKED","ACCEPTED"]}},{"name":"search","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"List Invitations"}},"/invitations/bulk":{"post":{"operationId":"InvitationController_bulk","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkCreateInvitationDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Bulk Invitation"}},"/invitations/verify":{"get":{"operationId":"InvitationController_verify","parameters":[{"name":"token","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Authenticated verify — the current user must be signed in and their\nemail must match. Used by the accept-invitation page once the visitor\nis logged in.","tags":["Organization"]}},"/invitations/public/verify":{"get":{"operationId":"InvitationController_verifyPublic","parameters":[{"name":"token","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Public verify — no authentication required. Returns the invitation\ndetails plus `userExists` so the frontend can route the visitor to\n/login (if registered) or /register?invitationToken=... (if new).","tags":["Organization"]}},"/invitations/public/decline":{"post":{"operationId":"InvitationController_declinePublic","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnswerInvitationDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Public decline — no authentication required, the emailed token is the\nauthorization. Needed because the people most likely to decline cannot\nsign in: a brand-new invitee has no account, and a user removed from\ntheir last org has no org context to authenticate with.\n\nDeclared before `@Post(':answer')` so the two-segment path is matched by\nthis handler rather than the catch-all.","tags":["Organization"]}},"/invitations/{id}":{"get":{"operationId":"InvitationController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Get Invitation By ID"}},"/invitations/{id}/resend":{"post":{"operationId":"InvitationController_resend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Resend Invitation"}},"/invitations/{id}/revoke":{"patch":{"operationId":"InvitationController_revoke","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Revoke Invitation"}},"/invitations/{answer}":{"post":{"operationId":"InvitationController_answer","parameters":[{"name":"answer","required":true,"in":"path","schema":{"type":"string","enum":["accept","decline"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnswerInvitationDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"object"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Organization"],"summary":"Answer Invitation"}},"/permission":{"get":{"operationId":"PermissionController_getAll","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The full permission catalog that backs the role editor's matrix. Gated on\n`roles:read` — its only consumer is the role editor, and the catalog\ndescribes the whole authorization surface of the app.","tags":["Organization"]}},"/agency":{"post":{"operationId":"AgencyController_createAgency","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgencyDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Any authenticated user may found an agency (they become its OWNER).","tags":["Agency"]}},"/agency/me":{"get":{"operationId":"AgencyController_getMyAgency","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Null (not 403) when the caller has no agency — the UI shows the empty state.","tags":["Agency"]}},"/agency/overview":{"get":{"operationId":"AgencyController_getOverview","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Agency"],"summary":"Get Overview"}},"/agency/clients":{"get":{"operationId":"AgencyController_listClients","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Agency"],"summary":"List Clients"},"post":{"operationId":"AgencyController_createClient","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateClientDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Agency"],"summary":"Create Client"}},"/agency/pricing":{"get":{"operationId":"AgencyController_getPlanPricing","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Agency"],"summary":"Get Plan Pricing"},"put":{"operationId":"AgencyController_updatePlanPricing","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePlanPricingDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Agency"],"summary":"Update Plan Pricing"}},"/agency/clients/{orgId}/setups/{setupId}/update-preview":{"get":{"operationId":"AgencyController_getSetupUpdatePreview","parameters":[{"name":"orgId","required":true,"in":"path","schema":{"type":"string"}},{"name":"setupId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"§36 update preview — what an additive update adds; nothing is overwritten.","tags":["Agency"]}},"/agency/clients/{orgId}/setups/{setupId}/install":{"post":{"operationId":"AgencyController_installSetupIntoClient","parameters":[{"name":"orgId","required":true,"in":"path","schema":{"type":"string"}},{"name":"setupId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Install a Setup into an EXISTING client (new clients install via the wizard).","tags":["Agency"]}},"/agency/activity":{"get":{"operationId":"AgencyController_listActivity","parameters":[{"name":"limit","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"§60 audit trail — plain-language activity, newest first.","tags":["Agency"]}},"/agency/settings":{"patch":{"operationId":"AgencyController_updateSettings","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAgencySettingsDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Suggested-pricing rule (§64: suggestion only — nothing is repriced).","tags":["Agency"]}},"/agency/clients/{orgId}/onboarding":{"get":{"operationId":"AgencyController_getOnboarding","parameters":[{"name":"orgId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"§59 onboarding checklist — auto items live, manual items stored.","tags":["Agency"]}},"/agency/clients/{orgId}/onboarding/{itemKey}/toggle":{"post":{"operationId":"AgencyController_toggleOnboarding","parameters":[{"name":"orgId","required":true,"in":"path","schema":{"type":"string"}},{"name":"itemKey","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Toggle a MANUAL checklist item on the client's behalf (§59).","tags":["Agency"]}},"/agency/clients/{orgId}/pricing":{"put":{"operationId":"AgencyController_updateClientPricing","parameters":[{"name":"orgId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateClientPricingDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Agency"],"summary":"Update Client Pricing"}},"/agency/setups":{"get":{"operationId":"SetupsController_listSetups","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Setups"],"summary":"List Setups"},"post":{"operationId":"SetupsController_createSetup","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSetupDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"\"Save as Setup\" from a client workspace.","tags":["Setups"]}},"/agency/setups/shared/{code}":{"get":{"operationId":"SetupsController_getSharedPreview","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Preview a setup shared by another agency (§32). Declared before :id.","tags":["Setups"]}},"/agency/setups/shared/{code}/import":{"post":{"operationId":"SetupsController_importShared","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Setups"],"summary":"Import Shared"}},"/agency/setups/{id}/share":{"post":{"operationId":"SetupsController_shareSetup","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Setups"],"summary":"Share Setup"},"delete":{"operationId":"SetupsController_revokeShare","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Setups"],"summary":"Revoke Share"}},"/agency/setups/{id}":{"get":{"operationId":"SetupsController_getSetup","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Setups"],"summary":"Get Setup"},"patch":{"operationId":"SetupsController_updateSetup","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSetupDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"\"Edit\" of the [Use][Duplicate][Edit] triple — name/description/industry only.","tags":["Setups"]},"delete":{"operationId":"SetupsController_deleteSetup","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Setups"],"summary":"Delete Setup"}},"/agency/setups/{id}/duplicate":{"post":{"operationId":"SetupsController_duplicateSetup","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Setups"],"summary":"Duplicate Setup"}},"/agency/branding":{"get":{"operationId":"BrandingController_getBranding","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Branding"],"summary":"Get Branding"},"patch":{"operationId":"BrandingController_updateBranding","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBrandingDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Branding"],"summary":"Update Branding"}},"/agency/branding/logo":{"post":{"operationId":"BrandingController_uploadLogo","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Branding"],"summary":"Upload Logo"}},"/agency/branding/favicon":{"post":{"operationId":"BrandingController_uploadFavicon","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Branding"],"summary":"Upload Favicon"}},"/agency/branding/domain":{"post":{"operationId":"BrandingController_setDomain","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDomainDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Branding"],"summary":"Set Domain"},"delete":{"operationId":"BrandingController_removeDomain","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Branding"],"summary":"Remove Domain"}},"/agency/branding/domain/verify":{"post":{"operationId":"BrandingController_verifyDomain","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Branding"],"summary":"Verify Domain"}},"/branding":{"get":{"operationId":"ResolvedBrandingController_getResolvedBranding","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["ResolvedBranding"],"summary":"Get Resolved Branding"}},"/agency/billing/stripe":{"get":{"operationId":"AgencyRebillingController_getConnection","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AgencyRebilling"],"summary":"Get Connection"},"post":{"operationId":"AgencyRebillingController_connect","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectStripeDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AgencyRebilling"],"summary":"Connect Agency Rebilling"},"delete":{"operationId":"AgencyRebillingController_disconnect","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AgencyRebilling"],"summary":"Disconnect Agency Rebilling"}},"/agency/billing/clients/{orgId}":{"get":{"operationId":"AgencyRebillingController_getClientRebill","parameters":[{"name":"orgId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AgencyRebilling"],"summary":"Get Client Rebill"}},"/agency/billing/clients/{orgId}/start":{"post":{"operationId":"AgencyRebillingController_startClientBilling","parameters":[{"name":"orgId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AgencyRebilling"],"summary":"Start Client Billing"}},"/agency/billing/clients/{orgId}/stop":{"post":{"operationId":"AgencyRebillingController_stopClientBilling","parameters":[{"name":"orgId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AgencyRebilling"],"summary":"Stop Client Billing"}},"/webhooks/stripe/agency/{agencyId}":{"post":{"operationId":"AgencyStripeWebhookController_handle","parameters":[{"name":"agencyId","required":true,"in":"path","schema":{"type":"string"}},{"name":"stripe-signature","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AgencyStripeWebhook"],"summary":"Handle Agency Stripe Webhook"}},"/sms-templates":{"post":{"operationId":"SmsTemplatesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSmsTemplateDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Templates"],"summary":"Create SMS Template"},"get":{"operationId":"SmsTemplatesController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"category","required":false,"in":"query","schema":{"type":"string","enum":["MARKETING","WELCOME","REMINDER","GENERAL","PROMOTIONAL","TRANSACTIONAL","NOTIFICATION"]}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","ARCHIVED"]}},{"name":"type","required":false,"in":"query","description":"Scopes the result set to a single template type. The text-link wizard\npicker passes `?type=TEXT_LINK` so it never surfaces WELCOME-type rows\n(which would render meaninglessly when pre-filled into a contact's SMS\napp). Omit to include all types.","schema":{"type":"string","enum":["TEXT_LINK","WELCOME"]}},{"name":"tagId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"includeSystem","required":true,"in":"query","description":"Defaults to `true`: most callers (e.g. the Text-Link wizard's template\npicker) want system templates folded into the result set so the catalog\nis visible alongside the org's own templates. Pass `?includeSystem=false`\nto scope results to org templates only.","schema":{"default":true,"type":"boolean"}},{"name":"favoriteOnly","required":false,"in":"query","description":"Restricts the list to templates the calling user has starred. Defaults to\nfalse — same contract as the email templates query.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/SmsTemplateResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Templates"],"summary":"List SMS Templates"}},"/sms-templates/categories":{"get":{"operationId":"SmsTemplatesController_listCategories","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Templates"],"summary":"List Categories"}},"/sms-templates/{id}":{"get":{"operationId":"SmsTemplatesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/SmsTemplateResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Templates"],"summary":"Get SMS Template By ID"},"patch":{"operationId":"SmsTemplatesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSmsTemplateDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Templates"],"summary":"Update SMS Template"},"delete":{"operationId":"SmsTemplatesController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Templates"],"summary":"Delete SMS Template"}},"/sms-templates/{id}/clone":{"post":{"operationId":"SmsTemplatesController_clone","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloneSmsTemplateDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Templates"],"summary":"Clone SMS Template"}},"/sms-templates/{id}/favorite":{"put":{"operationId":"SmsTemplatesController_favorite","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Templates"],"summary":"Favorite SMS Template"},"delete":{"operationId":"SmsTemplatesController_unfavorite","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["SMS Templates"],"summary":"Unfavorite SMS Template"}},"/lead-forms":{"post":{"operationId":"LeadFormsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLeadFormDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Create Lead Form"},"get":{"operationId":"LeadFormsController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":255,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ARCHIVED","DRAFT","PUBLISHED"]}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","updatedAt","name","status","viewCount","submissionCount"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"List Lead Forms"}},"/lead-forms/export":{"get":{"operationId":"LeadFormsController_exportListCsv","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":255,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ARCHIVED","DRAFT","PUBLISHED"]}},{"name":"sortBy","required":false,"in":"query","schema":{"type":"string","enum":["createdAt","updatedAt","name","status","viewCount","submissionCount"]}},{"name":"sortOrder","required":false,"in":"query","schema":{"type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Lead-forms LIST as CSV, STREAMED — the forms and their funnel counters,\nnot their answers (that is the per-form submissions export below).\n\nDeclared before `:id` so 'export' is not captured as a form id.","tags":["Lead Forms"]}},"/lead-forms/templates":{"get":{"operationId":"LeadFormsController_listTemplates","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"List Templates"}},"/lead-forms/analytics/overview":{"get":{"operationId":"LeadFormsController_getOrgAnalyticsOverview","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Get Org Analytics Overview"}},"/lead-forms/themes":{"get":{"operationId":"LeadFormsController_listThemes","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"List Themes"},"post":{"operationId":"LeadFormsController_createTheme","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLeadFormThemeDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Create Theme"}},"/lead-forms/themes/{themeId}":{"delete":{"operationId":"LeadFormsController_deleteTheme","parameters":[{"name":"themeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Delete Theme"}},"/lead-forms/{id}":{"get":{"operationId":"LeadFormsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Get Lead Form By ID"},"patch":{"operationId":"LeadFormsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLeadFormDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Update Lead Form"},"delete":{"operationId":"LeadFormsController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Delete Lead Form"}},"/lead-forms/{id}/qr-design":{"put":{"operationId":"LeadFormsController_saveQrDesign","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QrDesignDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Save QR Design"}},"/lead-forms/{id}/publish":{"post":{"operationId":"LeadFormsController_publish","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Publish Lead Form"}},"/lead-forms/{id}/archive":{"post":{"operationId":"LeadFormsController_archive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Archive Lead Form"}},"/lead-forms/{id}/duplicate":{"post":{"operationId":"LeadFormsController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Duplicate Lead Form"}},"/lead-forms/{id}/submissions":{"get":{"operationId":"LeadFormsController_listSubmissions","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","description":"Narrow the list (and the CSV export, which shares this DTO's `status`) to one outcome.","schema":{"type":"string","enum":["FAILED","NEW","CONTACT_CREATED","CONTACT_UPDATED"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"List Submissions"}},"/lead-forms/{id}/submissions/export":{"get":{"operationId":"LeadFormsController_exportSubmissions","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["FAILED","NEW","CONTACT_CREATED","CONTACT_UPDATED"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Export Submissions"}},"/lead-forms/{id}/submissions/{submissionId}/file":{"get":{"operationId":"LeadFormsController_getSubmissionFileUrl","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"submissionId","required":true,"in":"path","schema":{"type":"string"}},{"name":"key","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Get Submission File URL"}},"/lead-forms/{id}/submissions/{submissionId}":{"get":{"operationId":"LeadFormsController_findSubmissionById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"submissionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Get Submission By ID"}},"/lead-forms/{id}/analytics/overview":{"get":{"operationId":"LeadFormsController_analyticsOverview","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Analytics Overview"}},"/lead-forms/{id}/analytics/timeseries":{"get":{"operationId":"LeadFormsController_analyticsTimeseries","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Analytics Timeseries"}},"/lead-forms/{id}/analytics/breakdowns":{"get":{"operationId":"LeadFormsController_analyticsBreakdowns","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Lead Forms"],"summary":"Analytics Breakdowns"}},"/forms/{slug}":{"get":{"operationId":"LeadFormsPublicController_getConfig","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Lead Forms"],"summary":"Get Config"}},"/forms/{slug}/view":{"post":{"operationId":"LeadFormsPublicController_trackView","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackLeadFormEventDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Lead Forms"],"summary":"Track View"}},"/forms/{slug}/start":{"post":{"operationId":"LeadFormsPublicController_trackStart","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackLeadFormEventDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Lead Forms"],"summary":"Track Start"}},"/forms/{slug}/file-upload-url":{"post":{"operationId":"LeadFormsPublicController_createFileUploadUrl","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestLeadFormUploadUrlDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Lead Forms"],"summary":"Create File Upload URL"}},"/forms/{slug}/submit":{"post":{"operationId":"LeadFormsPublicController_submit","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitLeadFormDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Lead Forms"],"summary":"Submit Lead Forms Public"}},"/contacts/{contactId}/forms":{"get":{"operationId":"ContactFormSubmissionsController_list","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","description":"Narrow the list (and the CSV export, which shares this DTO's `status`) to one outcome.","schema":{"type":"string","enum":["FAILED","NEW","CONTACT_CREATED","CONTACT_UPDATED"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Contacts"],"summary":"List Contact Form Submissions"}},"/dashboards":{"get":{"operationId":"DashboardsController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboards"],"summary":"List Dashboards"},"post":{"operationId":"DashboardsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDashboardDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboards"],"summary":"Create Dashboard"}},"/dashboards/{id}":{"get":{"operationId":"DashboardsController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboards"],"summary":"Get Dashboard By ID"},"patch":{"operationId":"DashboardsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDashboardDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboards"],"summary":"Update Dashboard"},"delete":{"operationId":"DashboardsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboards"],"summary":"Delete Dashboard"}},"/dashboards/{id}/duplicate":{"post":{"operationId":"DashboardsController_duplicate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboards"],"summary":"Duplicate Dashboard"}},"/dashboards/{id}/set-default":{"post":{"operationId":"DashboardsController_setDefault","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboards"],"summary":"Set Default"}},"/dashboards/{id}/set-workspace-default":{"post":{"operationId":"DashboardsController_setWorkspaceDefault","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Sharing Phase 1: flags one of the caller's own dashboards as the\norg-wide workspace default. The one privileged dashboard route —\nOwner/Admin only via `dashboard:manage`.","tags":["Dashboards"]}},"/dashboards/{id}/sharing":{"get":{"operationId":"DashboardsController_getSharing","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Sharing Phases 2+3: owner-only snapshot backing the share drawer.","tags":["Dashboards"]},"put":{"operationId":"DashboardsController_updateSharing","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDashboardSharingDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Sharing Phases 2+3: owner-only full-replace of visibility + grants.","tags":["Dashboards"]}},"/contacts/bulk-delete":{"post":{"operationId":"ContactBulkJobsController_bulkDelete","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeleteDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"object"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Bulk Delete"}},"/contacts/bulk-edit":{"post":{"operationId":"ContactBulkJobsController_bulkEdit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkEditDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"object"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Bulk Edit"}},"/contacts/bulk-preflight":{"post":{"operationId":"ContactBulkJobsController_bulkPreflight","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkPreflightDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Read-only check before Apply: count, sync/async, and workflows it would start.","tags":["Contacts"]}},"/contacts/bulk-preflight/workflows":{"post":{"operationId":"ContactBulkJobsController_triggerPreflight","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerPreflightDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Workflows that tags / a segment would start — for CSV import and campaign recipients.","tags":["Contacts"]}},"/contact-bulk-jobs":{"get":{"operationId":"ContactBulkJobsController_listBulkJobs","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"List Bulk Jobs"}},"/contact-bulk-jobs/system-check":{"get":{"operationId":"ContactBulkJobsController_getSystemCheck","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Admin: is the queue Redis safe for large bulk jobs? Declared before `:id`.","tags":["Contacts"]}},"/contact-bulk-jobs/{id}":{"get":{"operationId":"ContactBulkJobsController_getBulkJob","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Get Bulk Job"}},"/contact-bulk-jobs/{id}/cancel":{"post":{"operationId":"ContactBulkJobsController_cancelBulkJob","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Cancel Bulk Job"}},"/contact-imports/upload-url":{"post":{"operationId":"ContactImportController_getUploadUrl","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetUploadUrlDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Get Upload URL"}},"/contact-imports":{"post":{"operationId":"ContactImportController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateImportDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Create Contact Import"},"get":{"operationId":"ContactImportController_findAll","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["PENDING","FAILED","COMPLETED","PROCESSING"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"List Contact Imports"}},"/contact-imports/{id}":{"get":{"operationId":"ContactImportController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contacts"],"summary":"Get Contact Import By ID"}},"/voice/settings/enable":{"post":{"operationId":"VoiceSettingsController_enable","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Enable voice (idempotent — re-running re-syncs provider webhooks).","tags":["Voice"]}},"/voice/settings":{"get":{"operationId":"VoiceSettingsController_getState","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Get State"},"patch":{"operationId":"VoiceSettingsController_update","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVoiceSettingsDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Update Voice Setting"},"delete":{"operationId":"VoiceSettingsController_disable","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Disable voice (best-effort provider teardown; config rows kept).","tags":["Voice"]}},"/voice/numbers":{"get":{"operationId":"VoiceConfigController_listNumbers","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"List Numbers"}},"/voice/numbers/mine":{"get":{"operationId":"VoiceConfigController_listMyNumbers","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"List My Numbers"}},"/voice/numbers/{channelIdentityId}/config":{"get":{"operationId":"VoiceConfigController_getConfig","parameters":[{"name":"channelIdentityId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Get Config"},"put":{"operationId":"VoiceConfigController_upsertConfig","parameters":[{"name":"channelIdentityId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertVoiceNumberConfigDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Upsert Config"}},"/voice/greetings/upload-url":{"post":{"operationId":"VoiceGreetingsController_getUploadUrl","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetGreetingUploadUrlDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Get Upload URL"}},"/voice/greetings/playback-url":{"get":{"operationId":"VoiceGreetingsController_getPlaybackUrl","parameters":[{"name":"storageKey","required":true,"in":"query","schema":{"minLength":1,"maxLength":512,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Get Playback URL"}},"/voice/token":{"post":{"operationId":"VoiceTokenController_mintToken","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Mint a browser softphone access token — a softphone is useful for placing\ncalls or for receiving them, so either permission is enough.","tags":["Voice"]}},"/voice/calls":{"post":{"operationId":"CallsController_initiate","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiateCallDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Initiate Call"},"get":{"operationId":"CallsQueryController_list","parameters":[{"name":"handledBy","required":false,"in":"query","description":"Who handled the call — `all` (default), `team`, or `ai` (AI Phone Answering).","schema":{"type":"string","enum":["all","team","ai"]}},{"name":"employeeId","required":false,"in":"query","description":"Phase 10 (D11) — only the calls this AI employee answered; implies `handledBy=ai`.","schema":{"format":"uuid","type":"string"}},{"name":"direction","required":false,"in":"query","schema":{"type":"string","enum":["OUTBOUND","INBOUND"]}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["VOICEMAIL","NO_ANSWER","FAILED","COMPLETED","IN_PROGRESS","RINGING","CANCELED","INITIATED","ON_HOLD","TRANSFERRED","BUSY","PARKED"]}},{"name":"disposition","required":false,"in":"query","schema":{"type":"string","enum":["INTERESTED","NOT_INTERESTED","FOLLOW_UP","OTHERS"]}},{"name":"userId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"contactId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"channelIdentityId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"hasRecording","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"counterpartNumber","required":false,"in":"query","description":"Exact E.164 of the other party — the widget's per-number timeline.","schema":{"type":"string"}},{"name":"businessNumber","required":false,"in":"query","description":"Part of one of the organization's OWN numbers — the line the call was on,\nwhatever its direction: the line called (inbound), the line called from\n(outbound), the line the AI answered on (AI rows). Formatting is ignored —\nonly the digits are matched, anywhere in the stored E.164.","schema":{"pattern":"^\\d{2,15}$","type":"string"}},{"name":"includeRecordings","required":false,"in":"query","description":"Attach a lite recordings projection to each row (opt-in).","schema":{"type":"boolean"}},{"name":"dateFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","schema":{"type":"string"}},{"name":"sortDir","required":false,"in":"query","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"List Calls Queries"}},"/voice/calls/{id}/end":{"post":{"operationId":"CallsController_end","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"End Call"}},"/voice/calls/{id}/hold":{"post":{"operationId":"CallsController_hold","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Hold Call"}},"/voice/calls/{id}/resume":{"post":{"operationId":"CallsController_resume","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Resume Call"}},"/voice/calls/{id}/transfer":{"post":{"operationId":"CallsController_transfer","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferCallDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Transfer Call"}},"/voice/calls/{id}/pick":{"post":{"operationId":"CallsController_pick","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Claim a caller parked on the hold queue. Any online agent may pick it;\n the first to win the atomic transition owns the call.","tags":["Voice"]}},"/voice/calls/business-numbers":{"get":{"operationId":"CallsQueryController_businessNumbers","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"The organization's own numbers — active lines first, then removed or\ninactive ones whose calls are still listed — for the \"Business number\"\nfilter. Same permission as the list it filters, which the phone-line\nsettings' own number list (`VOICE_CONFIG_READ`) is not.","tags":["Voice"]}},"/voice/calls/analytics":{"get":{"operationId":"CallsQueryController_analytics","parameters":[{"name":"dateFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Analytics Calls Query"}},"/voice/calls/export":{"get":{"operationId":"CallsQueryController_exportCsv","parameters":[{"name":"handledBy","required":false,"in":"query","description":"Who handled the call — `all` (default), `team`, or `ai` (AI Phone Answering).","schema":{"type":"string","enum":["all","team","ai"]}},{"name":"employeeId","required":false,"in":"query","description":"Phase 10 (D11) — only the calls this AI employee answered; implies `handledBy=ai`.","schema":{"format":"uuid","type":"string"}},{"name":"direction","required":false,"in":"query","schema":{"type":"string","enum":["OUTBOUND","INBOUND"]}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["VOICEMAIL","NO_ANSWER","FAILED","COMPLETED","IN_PROGRESS","RINGING","CANCELED","INITIATED","ON_HOLD","TRANSFERRED","BUSY","PARKED"]}},{"name":"disposition","required":false,"in":"query","schema":{"type":"string","enum":["INTERESTED","NOT_INTERESTED","FOLLOW_UP","OTHERS"]}},{"name":"userId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"contactId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"channelIdentityId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"hasRecording","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"counterpartNumber","required":false,"in":"query","description":"Exact E.164 of the other party — the widget's per-number timeline.","schema":{"type":"string"}},{"name":"businessNumber","required":false,"in":"query","description":"Part of one of the organization's OWN numbers — the line the call was on,\nwhatever its direction: the line called (inbound), the line called from\n(outbound), the line the AI answered on (AI rows). Formatting is ignored —\nonly the digits are matched, anywhere in the stored E.164.","schema":{"pattern":"^\\d{2,15}$","type":"string"}},{"name":"includeRecordings","required":false,"in":"query","description":"Attach a lite recordings projection to each row (opt-in).","schema":{"type":"boolean"}},{"name":"dateFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","schema":{"type":"string"}},{"name":"sortDir","required":false,"in":"query","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"The Calls history as CSV, STREAMED — team AND AI-answered calls under the\nlist's own filters, Team / AI / All switch and sort (`page`/`limit` are\nignored — the file is every matching call). A team-only filter leaves AI\ncalls out exactly as it does on screen.\nDeclared before `:id`, whose UUID pipe would otherwise reject \"export\".","tags":["Voice"]}},"/voice/calls/ai/{id}":{"get":{"operationId":"CallsQueryController_getAiCall","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"P9-8 — an AI-answered call on the Calls page: the detail (summary,\ntranscript, what happened) under the page's own permission. A foreign\nor unknown id is the same 404. The settings page keeps its own routes.","tags":["Voice"]}},"/voice/calls/ai/{id}/recording":{"get":{"operationId":"CallsQueryController_getAiCallRecording","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"P9-8 — a short-lived playback link for the AI call's saved recording; 404\nwithout one. Fix round I-1: the softphone's listen rule applies.","tags":["Voice"]}},"/voice/calls/ai/{id}/analysis":{"post":{"operationId":"CallsQueryController_regenerateAiCallAnalysis","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"P9-10 — regenerate the AI call's summary + analysis from its saved\ntranscript. It reads what was said, so the listen rule applies; the\nfresh detail comes back trimmed to the caller's role like a GET.","tags":["Voice"]}},"/voice/calls/ai/{id}/contact":{"patch":{"operationId":"CallsQueryController_linkAiCallContact","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkCallContactDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"P9-10 — link an AI call to a contact made through the contacts flow (the softphone's own rule and permission).","tags":["Voice"]}},"/voice/calls/{id}":{"get":{"operationId":"CallsQueryController_getById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Get Calls Query By ID"}},"/voice/calls/{id}/disposition":{"patch":{"operationId":"CallsQueryController_updateDisposition","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCallDispositionDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Update Disposition"}},"/voice/calls/{id}/contact":{"patch":{"operationId":"CallsQueryController_linkContact","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkCallContactDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Link Contact"}},"/voice/blocked-numbers":{"get":{"operationId":"VoiceBlocklistController_list","parameters":[{"name":"search","required":false,"in":"query","description":"Phone substring match.","schema":{"maxLength":200,"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"List Voice Blocklists"},"post":{"operationId":"VoiceBlocklistController_block","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlockNumberDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Block Voice Blocklist"}},"/voice/blocked-numbers/{id}":{"patch":{"operationId":"VoiceBlocklistController_updateNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBlockedNumberDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Update Note"},"delete":{"operationId":"VoiceBlocklistController_unblock","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Unblock Voice Blocklist"}},"/voice/presence":{"get":{"operationId":"VoicePresenceController_getOrgPresence","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Get Org Presence"}},"/voice/presence/me":{"put":{"operationId":"VoicePresenceController_setMyStatus","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePresenceDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Set My Status"}},"/voice/recordings":{"get":{"operationId":"VoiceRecordingsController_list","parameters":[{"name":"kind","required":false,"in":"query","schema":{"type":"string","enum":["VOICEMAIL","CALL"]}},{"name":"callId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"contactId","required":false,"in":"query","schema":{"format":"uuid","type":"string"}},{"name":"heard","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"dateFrom","required":false,"in":"query","schema":{"type":"string"}},{"name":"dateTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"List Voice Recordings"}},"/voice/recordings/{id}/url":{"get":{"operationId":"VoiceRecordingsController_getPresignedUrl","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Get Presigned URL"}},"/voice/recordings/{id}/heard":{"patch":{"operationId":"VoiceRecordingsController_markHeard","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Mark Heard"}},"/voice/recordings/{id}":{"delete":{"operationId":"VoiceRecordingsController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Voice"],"summary":"Delete Voice Recording"}},"/webhooks/voice/twilio/twiml-app":{"post":{"operationId":"VoiceWebhookController_twimlApp","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Twiml App"}},"/webhooks/voice/twilio/inbound":{"post":{"operationId":"VoiceWebhookController_inbound","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Inbound Voice Webhook"}},"/webhooks/voice/twilio/ivr-gather":{"post":{"operationId":"VoiceWebhookController_ivrGather","parameters":[{"name":"orgId","required":true,"in":"query","schema":{"type":"string"}},{"name":"callId","required":true,"in":"query","schema":{"type":"string"}},{"name":"attempt","required":true,"in":"query","schema":{"type":"string"}},{"name":"slot","required":true,"in":"query","schema":{"type":"string"}},{"name":"repeat","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Ivr Gather"}},"/webhooks/voice/twilio/voicemail-complete":{"post":{"operationId":"VoiceWebhookController_voicemailComplete","parameters":[{"name":"orgId","required":true,"in":"query","schema":{"type":"string"}},{"name":"callId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Voicemail Complete"}},"/webhooks/voice/twilio/forward-action":{"post":{"operationId":"VoiceWebhookController_forwardAction","parameters":[{"name":"orgId","required":true,"in":"query","schema":{"type":"string"}},{"name":"callId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Forward Action"}},"/webhooks/voice/twilio/call-status":{"post":{"operationId":"VoiceWebhookController_callStatus","parameters":[{"name":"orgId","required":true,"in":"query","schema":{"type":"string"}},{"name":"callId","required":true,"in":"query","schema":{"type":"string"}},{"name":"role","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Call Status"}},"/webhooks/voice/twilio/conference-status":{"post":{"operationId":"VoiceWebhookController_conferenceStatus","parameters":[{"name":"orgId","required":true,"in":"query","schema":{"type":"string"}},{"name":"callId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Conference Status"}},"/webhooks/voice/twilio/recording-status":{"post":{"operationId":"VoiceWebhookController_recordingStatus","parameters":[{"name":"orgId","required":true,"in":"query","schema":{"type":"string"}},{"name":"callId","required":true,"in":"query","schema":{"type":"string"}},{"name":"kind","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Recording Status"}},"/webhooks/voice/twilio/wait":{"post":{"operationId":"VoiceWebhookController_wait","parameters":[{"name":"mode","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Wait Voice Webhook"}},"/webhooks/voice/telnyx":{"post":{"operationId":"TelnyxVoiceWebhookController_handle","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Voice"],"summary":"Handle Telnyx Voice Webhook"}},"/channels/whatsapp/connect":{"post":{"operationId":"WhatsAppChannelController_connect","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectWhatsAppDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Connect Whats App Channel","tags":["WhatsApp Channel"],"description":"Complete Meta's Embedded Signup flow for the current organization."}},"/channels/whatsapp/disconnect":{"post":{"operationId":"WhatsAppChannelController_disconnect","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Disconnect Whats App Channel","tags":["WhatsApp Channel"],"description":"Disconnect the WhatsApp channel for the current organization."}},"/channels/whatsapp/state":{"get":{"operationId":"WhatsAppChannelController_getState","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Get State","tags":["WhatsApp Channel"],"description":"Load the current WhatsApp connection state for the current organization."}},"/channels/whatsapp/messaging-limit":{"get":{"operationId":"WhatsAppChannelController_getMessagingLimit","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Get Messaging Limit","tags":["WhatsApp Channel"],"description":"The connected number's messaging limit, read live from Meta."}},"/webhooks/whatsapp/meta":{"get":{"operationId":"WhatsAppWebhookController_handleVerify","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Handle Verify","tags":["Webhooks"],"description":"Meta's one-time subscription verification handshake."},"post":{"operationId":"WhatsAppWebhookController_handleWebhook","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Handle Webhook","tags":["Webhooks"],"description":"Receives inbound messages and delivery status updates from Meta."}},"/channels/whatsapp/templates":{"get":{"operationId":"WhatsAppTemplatesController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["PENDING","REJECTED","DRAFT","DISABLED","PAUSED","APPROVED"]}},{"name":"category","required":false,"in":"query","description":"Meta's own classification. Optional — omitted means every category, so\nan existing caller that never sends it behaves exactly as before.","schema":{"type":"string","enum":["MARKETING","UTILITY","AUTHENTICATION"]}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"favoriteOnly","required":false,"in":"query","description":"Restrict to templates the CALLING user has starred. Query params arrive\nas strings, so coerce explicitly — `Boolean('false')` is `true`.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"List Whats App Templates"},"post":{"operationId":"WhatsAppTemplatesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWhatsAppTemplateDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"Create Whats App Template"}},"/channels/whatsapp/templates/{id}":{"get":{"operationId":"WhatsAppTemplatesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"Get Whats App Template By ID"},"patch":{"operationId":"WhatsAppTemplatesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWhatsAppTemplateDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"Update Whats App Template"},"delete":{"operationId":"WhatsAppTemplatesController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"Delete Whats App Template"}},"/channels/whatsapp/templates/{id}/send-settings":{"patch":{"operationId":"WhatsAppTemplatesController_updateSendSettings","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWhatsAppTemplateSendSettingsDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The values Meta re-asks for on every send — a location header's four\nfields, a limited-time offer's countdown, a dynamic url button's suffix.\nSeparate from `@Patch(':id')` because none of them is part of the shape\nMeta approved, so unlike a real edit this is allowed on an APPROVED row\nand needs no re-submission. See `updateSendSettings`.","tags":["WhatsApp Templates"]}},"/channels/whatsapp/templates/{id}/favorite":{"put":{"operationId":"WhatsAppTemplatesController_favorite","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"Favorite Whats App Template"},"delete":{"operationId":"WhatsAppTemplatesController_unfavorite","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"Unfavorite Whats App Template"}},"/channels/whatsapp/templates/{id}/clone":{"post":{"operationId":"WhatsAppTemplatesController_clone","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"Clone Whats App Template"}},"/channels/whatsapp/templates/{id}/submit":{"post":{"operationId":"WhatsAppTemplatesController_submit","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"Submit Whats App Template"}},"/channels/whatsapp/templates/sync":{"post":{"operationId":"WhatsAppTemplatesController_sync","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["WhatsApp Templates"],"summary":"Sync Whats App Template"}},"/contacts/{contactId}/whatsapp-consent":{"get":{"operationId":"ContactWhatsAppConsentController_get","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contact WhatsApp Consent"],"summary":"Get Contact Whats App Consent"},"patch":{"operationId":"ContactWhatsAppConsentController_update","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWhatsAppConsentDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Contact WhatsApp Consent"],"summary":"Update Contact Whats App Consent"}},"/dev/mock-channels/whatsapp/templates/{id}/delete-in-meta":{"post":{"operationId":"WhatsAppMockTemplatesController_deleteInMeta","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Mock Channels (dev)"],"summary":"Delete In Meta"}},"/dev/mock-channels/sms/inbound":{"post":{"operationId":"MockInboundController_simulateInbound","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MockInboundSmsDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"object"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"Resolves the target channel identity (by id or destination number),\nresolves the owning channel's actual provider (TWILIO/TELNYX — falls\nback to TWILIO only if unresolvable), then drives the SAME\nclassification pipeline the real Twilio/Telnyx webhook uses\n(`InboundSmsProcessor.processInbound`) — synchronously, so the\nresponse can report what was persisted.","tags":["Mock Channels (dev)"]}},"/join-links":{"post":{"operationId":"JoinLinksController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJoinLinkDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Create Join Link"},"get":{"operationId":"JoinLinksController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"search","required":false,"in":"query","schema":{"maxLength":200,"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","INACTIVE","ARCHIVED"]}},{"name":"type","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/JoinLinkAdminResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"List Join Links"}},"/join-links/stats":{"get":{"operationId":"JoinLinksController_stats","parameters":[{"name":"type","required":false,"in":"query","description":"Optional — scopes the stats to a single join-link type. Omit for all types.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/JoinLinkStatsDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Get Join Link Stats"}},"/join-links/slug/check":{"get":{"operationId":"JoinLinksController_checkSlug","parameters":[{"name":"value","required":true,"in":"query","schema":{"minLength":3,"maxLength":50,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Check Slug"}},"/join-links/slug/suggest":{"post":{"operationId":"JoinLinksController_suggestSlug","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestSlugDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Suggest Slug"}},"/join-links/{id}":{"get":{"operationId":"JoinLinksController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/JoinLinkAdminResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Get Join Link By ID"},"patch":{"operationId":"JoinLinksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateJoinLinkDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Update Join Link"},"delete":{"operationId":"JoinLinksController_softDelete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Delete Join Link"}},"/join-links/bulk-delete":{"post":{"operationId":"JoinLinksController_bulkDelete","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeleteJoinLinksDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Bulk Delete"}},"/join-links/{id}/qr":{"post":{"operationId":"JoinLinksController_generateQr","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Generate QR"}},"/join-links/{id}/qr-url":{"get":{"operationId":"JoinLinksController_getQrUrl","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Get QR URL"}},"/join-links/{id}/qr-design":{"put":{"operationId":"JoinLinksController_saveQrDesign","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QrDesignDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Save QR Design"}},"/join-links/{id}/qr-download":{"get":{"operationId":"JoinLinksController_downloadQr","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Download QR"}},"/join-links/{id}/qr-stats":{"get":{"operationId":"JoinLinksController_getQrStats","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Get QR Stats"}},"/join-links/{id}/submissions/export":{"get":{"operationId":"JoinLinksController_exportSubmissionsCsv","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"A signup form's submissions as CSV, STREAMED.\n\nDeclared before the paginated `:id/submissions` so the literal `/export`\nsuffix is matched first.\n\nThe file carries the CONSENT block (text, timestamp, user agent) as well\nas the contact, because that is what makes it usable as evidence. The\nhashed consent IP is deliberately left out — see the columns file.","tags":["Join Links"]}},"/join-links/{id}/submissions":{"get":{"operationId":"JoinLinksController_listSubmissions","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"List Submissions"}},"/join-links/{id}/analytics":{"get":{"operationId":"JoinLinksController_analytics","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"range","required":true,"in":"query","schema":{"default":"7d","type":"string","enum":["all","7d","30d","2mo"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Get Join Link Analytics"}},"/join/{slug}":{"get":{"operationId":"JoinLinksPublicController_getConfig","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/PublicJoinLinkConfigDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Join Links"],"summary":"Get Public Form Config"}},"/join/{slug}/view":{"post":{"operationId":"JoinLinksPublicController_trackView","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackViewDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Join Links"],"summary":"Track View"}},"/join/{slug}/otp/send":{"post":{"operationId":"JoinLinksPublicController_sendOtp","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendJoinLinkOtpDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Join Links"],"summary":"Send OTP"}},"/join/{slug}/submit":{"post":{"operationId":"JoinLinksPublicController_submit","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitJoinLinkDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/JoinLinkSubmitResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Join Links"],"summary":"Submit Join Form"}},"/welcome-templates":{"get":{"operationId":"WelcomeTemplatesController_list","parameters":[{"name":"category","required":false,"in":"query","schema":{"type":"string","enum":["MARKETING","SALES","GENERAL","PROMOTIONAL","TRANSACTIONAL","EVENT","ONBOARDING","SUPPORT"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/WelcomeTemplateResponseDto"}},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"List Welcome Templates"}},"/welcome-templates/{id}":{"get":{"operationId":"WelcomeTemplatesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/WelcomeTemplateResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"tags":["Join Links"],"summary":"Get Welcome Template By ID"}},"/analytics/overview/kpis":{"get":{"operationId":"AnalyticsController_getKpis","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Analytics"],"summary":"Get Kpis"}},"/analytics/overview/funnel":{"get":{"operationId":"AnalyticsController_getFunnel","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Analytics"],"summary":"Get Funnel"}},"/analytics/overview/channels":{"get":{"operationId":"AnalyticsController_getChannels","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Analytics"],"summary":"Get Channels"}},"/analytics/overview/campaigns":{"get":{"operationId":"AnalyticsController_getCampaigns","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"sortBy","required":true,"in":"query","schema":{"default":"createdAt","type":"string","enum":["createdAt","name","sent","delivered","replies","clicks"]}},{"name":"sortOrder","required":true,"in":"query","schema":{"default":"desc","type":"string","enum":["asc","desc"]}},{"name":"channel","required":false,"in":"query","description":"Additive filter (Task 3) — absent means \"all channels\".","schema":{"type":"string","enum":["SMS","EMAIL"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Analytics"],"summary":"Get Campaigns"}},"/analytics/overview/campaigns/export":{"get":{"operationId":"AnalyticsController_exportCampaignsCsv","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}},{"name":"channel","required":false,"in":"query","schema":{"type":"string","enum":["SMS","EMAIL"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Analytics"],"summary":"Export Campaigns Csv"}},"/analytics/marketing/kpis":{"get":{"operationId":"AnalyticsMarketingController_getKpis","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsMarketing"],"summary":"Get Kpis"}},"/analytics/marketing/series":{"get":{"operationId":"AnalyticsMarketingController_getSeries","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsMarketing"],"summary":"Get Series"}},"/analytics/marketing/sources":{"get":{"operationId":"AnalyticsMarketingController_getSources","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsMarketing"],"summary":"Get Sources"}},"/analytics/conversations/kpis":{"get":{"operationId":"AnalyticsConversationsController_getKpis","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsConversations"],"summary":"Get Kpis"}},"/analytics/conversations/series":{"get":{"operationId":"AnalyticsConversationsController_getSeries","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsConversations"],"summary":"Get Series"}},"/analytics/conversations/split":{"get":{"operationId":"AnalyticsConversationsController_getSplit","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsConversations"],"summary":"Get Split"}},"/analytics/conversations/hours":{"get":{"operationId":"AnalyticsConversationsController_getHours","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsConversations"],"summary":"Get Hours"}},"/analytics/insights/health":{"get":{"operationId":"AnalyticsInsightsController_getHealth","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsInsights"],"summary":"Get Health"}},"/analytics/insights/coach":{"get":{"operationId":"AnalyticsInsightsController_getCoach","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsInsights"],"summary":"Get Coach"}},"/analytics/revenue/kpis":{"get":{"operationId":"AnalyticsRevenueController_getKpis","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsRevenue"],"summary":"Get Kpis"}},"/analytics/revenue/campaigns":{"get":{"operationId":"AnalyticsRevenueController_getCampaigns","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"pageSize","required":true,"in":"query","schema":{"minimum":1,"maximum":50,"default":10,"type":"number"}},{"name":"sortBy","required":true,"in":"query","schema":{"default":"revenue","type":"string","enum":["revenue","roi","conversions","estimatedCost","sends"]}},{"name":"sortDir","required":true,"in":"query","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsRevenue"],"summary":"Get Campaigns"}},"/analytics/revenue/sources":{"get":{"operationId":"AnalyticsRevenueController_getSources","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsRevenue"],"summary":"Get Sources"}},"/analytics/appointments/kpis":{"get":{"operationId":"AnalyticsAppointmentsController_getKpis","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsAppointments"],"summary":"Get Kpis"}},"/analytics/appointments/series":{"get":{"operationId":"AnalyticsAppointmentsController_getSeries","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsAppointments"],"summary":"Get Series"}},"/analytics/appointments/meeting-types":{"get":{"operationId":"AnalyticsAppointmentsController_getMeetingTypes","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsAppointments"],"summary":"Get Meeting Types"}},"/analytics/appointments/sources":{"get":{"operationId":"AnalyticsAppointmentsController_getSources","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsAppointments"],"summary":"Get Sources"}},"/analytics/deliverability/kpis":{"get":{"operationId":"AnalyticsDeliverabilityController_getKpis","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsDeliverability"],"summary":"Get Kpis"}},"/analytics/deliverability/sms-failures":{"get":{"operationId":"AnalyticsDeliverabilityController_getSmsFailures","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsDeliverability"],"summary":"Get SMS Failures"}},"/analytics/deliverability/email-funnel":{"get":{"operationId":"AnalyticsDeliverabilityController_getEmailFunnel","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsDeliverability"],"summary":"Get Email Funnel"}},"/analytics/deliverability/opt-outs":{"get":{"operationId":"AnalyticsDeliverabilityController_getOptOuts","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsDeliverability"],"summary":"Get Opt Outs"}},"/analytics/deliverability/compliance-status":{"get":{"operationId":"AnalyticsDeliverabilityController_getComplianceStatus","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["AnalyticsDeliverability"],"summary":"Get Compliance Status"}},"/onboarding/status":{"get":{"operationId":"OnboardingController_getStatus","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Get Status"}},"/onboarding/wizard":{"get":{"operationId":"OnboardingController_getWizard","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Get Wizard"}},"/onboarding/wizard/lead-profile":{"post":{"operationId":"OnboardingController_saveLeadProfile","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizardLeadProfileDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Save Lead Profile"}},"/onboarding/wizard/lead-source":{"post":{"operationId":"OnboardingController_saveLeadSource","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizardLeadSourceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Save Lead Source"}},"/onboarding/wizard/playbook":{"post":{"operationId":"OnboardingController_installPlaybook","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Install Playbook"}},"/onboarding/wizard/ai-policy":{"post":{"operationId":"OnboardingController_saveAiPolicy","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizardAiPolicyDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Save Ai Policy"}},"/onboarding/test-lead":{"post":{"operationId":"OnboardingController_runTestLead","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Run Test Lead"}},"/onboarding/test-lead/{contactId}":{"get":{"operationId":"OnboardingController_getTestLeadTrace","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Get Test Lead Trace"}},"/onboarding/wizard/go-live":{"post":{"operationId":"OnboardingController_goLive","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Go Live"}},"/onboarding/wizard/advance":{"post":{"operationId":"OnboardingController_advanceWizard","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizardAdvanceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Advance Wizard"}},"/onboarding/wizard/complete":{"post":{"operationId":"OnboardingController_completeWizard","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Complete Wizard"}},"/onboarding/wizard/business":{"post":{"operationId":"OnboardingController_saveWizardBusiness","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizardBusinessDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"The retired campaign-first wizard's business step. Legacy route retained\nfor API compatibility; unused by the app — no frontend screen calls it.\n`POST wizard/goal` is gone.","tags":["Onboarding"]}},"/onboarding/welcome-seen":{"post":{"operationId":"OnboardingController_welcomeSeen","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Welcome Seen"}},"/onboarding/skip":{"post":{"operationId":"OnboardingController_skip","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Skip Onboarding"}},"/onboarding/dismiss-rail":{"post":{"operationId":"OnboardingController_dismissRail","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Dismiss Rail"}},"/onboarding/celebrate":{"post":{"operationId":"OnboardingController_celebrate","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Onboarding"],"summary":"Celebrate Onboarding"}},"/analytics/insights/coach/regenerate":{"post":{"operationId":"CoachController_regenerate","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Coach"],"summary":"Regenerate Coach"}},"/outcomes/funnel":{"get":{"operationId":"OutcomesController_getFunnel","parameters":[{"name":"from","required":false,"in":"query","description":"First day of the window, inclusive, as a calendar date in the\nORGANIZATION's timezone. Omit both to get the last 30 days.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Last day of the window, inclusive.","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"The window as a span, counted back from the BUSINESS's today.","schema":{"type":"number","enum":[7,30,90]}},{"name":"source","required":false,"in":"query","description":"Where the lead came from.","schema":{"type":"string","enum":["TEXT_LINK","JOIN_KEYWORD","CSV_IMPORT","MANUAL","WEB_FORM","INBOUND_SMS","INBOUND_CALL","GOOGLE_ADS","META_ADS","INBOUND_EMAIL","INBOUND_WHATSAPP","LEAD_FORM","WEB_CHAT"]}},{"name":"owner","required":false,"in":"query","description":"Whose leads — `me`, resolved to the caller here rather than in the\nbrowser, or a member's user id. Never org-checked by a lookup: every\nstatement it reaches is org-bound, so another business's user id matches\nno rows.","schema":{"type":"string"}},{"name":"responder","required":false,"in":"query","description":"Who answered the lead first.","schema":{"type":"string","enum":["ai","human","unanswered"]}},{"name":"playbook","required":false,"in":"query","description":"An installed playbook's key — leads that playbook actually worked.","schema":{"minLength":1,"maxLength":80,"type":"string"}},{"name":"area","required":false,"in":"query","description":"Lead area: a postal-code prefix, or a state/region name. Bounded because\nit reaches a `LIKE` — a filter is not a place to paste a document.","schema":{"minLength":1,"maxLength":60,"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"What happened to the leads that came in over a window of days","tags":["Outcomes"]}},"/outcomes/leads":{"get":{"operationId":"OutcomesController_getStepLeads","parameters":[{"name":"from","required":false,"in":"query","description":"First day of the window, inclusive, as a calendar date in the\nORGANIZATION's timezone. Omit both to get the last 30 days.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Last day of the window, inclusive.","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"The window as a span, counted back from the BUSINESS's today.","schema":{"type":"number","enum":[7,30,90]}},{"name":"source","required":false,"in":"query","description":"Where the lead came from.","schema":{"type":"string","enum":["TEXT_LINK","JOIN_KEYWORD","CSV_IMPORT","MANUAL","WEB_FORM","INBOUND_SMS","INBOUND_CALL","GOOGLE_ADS","META_ADS","INBOUND_EMAIL","INBOUND_WHATSAPP","LEAD_FORM","WEB_CHAT"]}},{"name":"owner","required":false,"in":"query","description":"Whose leads — `me`, resolved to the caller here rather than in the\nbrowser, or a member's user id. Never org-checked by a lookup: every\nstatement it reaches is org-bound, so another business's user id matches\nno rows.","schema":{"type":"string"}},{"name":"responder","required":false,"in":"query","description":"Who answered the lead first.","schema":{"type":"string","enum":["ai","human","unanswered"]}},{"name":"playbook","required":false,"in":"query","description":"An installed playbook's key — leads that playbook actually worked.","schema":{"minLength":1,"maxLength":80,"type":"string"}},{"name":"area","required":false,"in":"query","description":"Lead area: a postal-code prefix, or a state/region name. Bounded because\nit reaches a `LIKE` — a filter is not a place to paste a document.","schema":{"minLength":1,"maxLength":60,"type":"string"}},{"name":"step","required":true,"in":"query","schema":{"type":"string","enum":["new_leads","answered_within_target","qualified","booking_link_sent","booked","attended","won","no_show","cancelled","lost","no_target","answered_late"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":50,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The leads behind one step of the funnel","tags":["Outcomes"]}},"/today/summary":{"get":{"operationId":"TodayController_getSummary","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","this_week","last_week","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The filtered window's outcome metrics and the live queue counts","tags":["Today"]}},"/today/employees":{"get":{"operationId":"TodayController_getEmployees","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","this_week","last_week","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Each active AI employee with what it did in the filtered window","tags":["Today"]}},"/today/series":{"get":{"operationId":"TodayController_getSeries","parameters":[{"name":"preset","required":false,"in":"query","schema":{"type":"string","enum":["today","yesterday","this_week","last_week","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"New leads and bookings per org-local day, this window and the previous","tags":["Today"]}},"/today/leads":{"get":{"operationId":"TodayController_getLeads","parameters":[{"name":"group","required":true,"in":"query","schema":{"type":"string","enum":["hot","new","sla","replied_not_booked","handoff","booking_pending","new_inquiries","responded_within_sla","responded_late","booked","open_follow_ups","won"]}},{"name":"period","required":false,"in":"query","description":"Legacy window name from before the date filter; `preset` wins when both\nare sent. Ignored for the five queue groups — those are always \"right now\".","schema":{"type":"string","enum":["today","last_7d","prior_7d"]}},{"name":"preset","required":false,"in":"query","description":"The date filter the drill was opened under (ticket [13]); same set as the summary's.","schema":{"type":"string","enum":["today","yesterday","this_week","last_week","7d","30d","this_month","custom"]}},{"name":"from","required":false,"in":"query","description":"Org-local calendar date (YYYY-MM-DD). Required when preset=custom.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}},{"name":"assignedTo","required":false,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":50,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"One queue group, or the leads behind one metric","tags":["Today"]}},"/today/leads/{contactId}":{"get":{"operationId":"TodayController_getLead","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"One lead: its queue card plus its outcome history","tags":["Today"]}},"/today/digest":{"get":{"operationId":"TodayController_getDigest","parameters":[{"name":"date","required":false,"in":"query","description":"A calendar date in the ORGANIZATION's timezone — the day boundary is\nthe org's, so `2026-09-16` means the same range for every user of the\nsame business. Defaults to the org's today.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"A day's new leads with the AI's stored account of each arrival","tags":["Today"]}},"/today/digest/days":{"get":{"operationId":"TodayController_getDigestDays","parameters":[{"name":"from","required":true,"in":"query","description":"Org-local inclusive calendar dates; at most 31 days — this feeds a week strip, not a report.","schema":{"type":"string"}},{"name":"to","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Per-day lead counts for the digest's week strip","tags":["Today"]}},"/today/bookings":{"get":{"operationId":"TodayController_getBookings","parameters":[{"name":"date","required":false,"in":"query","description":"A calendar date in the ORGANIZATION's timezone, not the caller's — the\nday boundary is the org's, so `2026-09-16` means the same range for\nevery user of the same business. Defaults to the org's today.","schema":{"pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"A day's bookings in the organization's timezone","tags":["Today"]}},"/dashboard/kpis":{"get":{"operationId":"DashboardController_getKpis","parameters":[{"name":"period","required":false,"in":"query","schema":{"type":"string","enum":["7d","30d","this_month","last_month","custom"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Kpis"}},"/dashboard/campaign-performance":{"get":{"operationId":"DashboardController_getCampaignPerformance","parameters":[{"name":"period","required":false,"in":"query","schema":{"type":"string","enum":["7d","30d","this_month","last_month","custom"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Campaign Performance"}},"/dashboard/opt-out-trends":{"get":{"operationId":"DashboardController_getOptOutTrends","parameters":[{"name":"period","required":false,"in":"query","schema":{"type":"string","enum":["7d","30d","this_month","last_month","custom"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Opt Out Trends"}},"/dashboard/channel-engagement":{"get":{"operationId":"DashboardController_getChannelEngagement","parameters":[{"name":"period","required":false,"in":"query","schema":{"type":"string","enum":["7d","30d","this_month","last_month","custom"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Channel Engagement"}},"/dashboard/poll-insights":{"get":{"operationId":"DashboardController_getPollInsights","parameters":[{"name":"period","required":false,"in":"query","schema":{"type":"string","enum":["7d","30d","this_month","last_month","custom"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Poll Insights"}},"/dashboard/link-engagement":{"get":{"operationId":"DashboardController_getLinkEngagement","parameters":[{"name":"period","required":false,"in":"query","schema":{"type":"string","enum":["7d","30d","this_month","last_month","custom"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Link Engagement"}},"/dashboard/today-snapshot":{"get":{"operationId":"DashboardController_getTodaySnapshot","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Today Snapshot"}},"/dashboard/business-kpis":{"get":{"operationId":"DashboardController_getBusinessKpis","parameters":[{"name":"period","required":false,"in":"query","schema":{"type":"string","enum":["7d","30d","this_month","last_month","custom"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Business Kpis"}},"/dashboard/revenue-series":{"get":{"operationId":"DashboardController_getRevenueSeries","parameters":[{"name":"period","required":false,"in":"query","schema":{"type":"string","enum":["7d","30d","this_month","last_month","custom"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Revenue Series"}},"/dashboard/activity":{"get":{"operationId":"DashboardController_getActivity","parameters":[{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":50,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Activity"}},"/dashboard/ai-summary":{"get":{"operationId":"DashboardController_getAiSummary","parameters":[{"name":"period","required":false,"in":"query","schema":{"type":"string","enum":["7d","30d","this_month","last_month","custom"]}},{"name":"from","required":false,"in":"query","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Dashboard"],"summary":"Get Ai Summary"}},"/ai-lead-responder/metrics":{"get":{"operationId":"AiLeadResponderController_getMetrics","parameters":[{"name":"from","required":false,"in":"query","description":"First day of the window, inclusive, as a calendar date in the\nORGANIZATION's timezone — the same convention as `/today/bookings`, so\neveryone in one business reads the same range. Omit both to get the\nlast 30 days.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Last day of the window, inclusive.","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"The window as a span instead: one of the three the picker offers, counted\nback from today in the ORGANIZATION's timezone.\n\nIt exists so the page never computes dates in the browser. \"Last 7 days\"\ncounted in the reader's calendar is a different seven days from a\ncolleague's a timezone away, over the same URL — and the response says\nwhich days it measured, so the page can print them.\n\nMutually exclusive with `from`/`to`; the shared constraint reports that.","schema":{"type":"number","enum":[7,30,90]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"How the AI Lead Responder did over a window of days","tags":["AI Lead Responder"]}},"/ai-lead-responder/handoffs/conversations":{"get":{"operationId":"AiLeadResponderController_listHandoffConversations","parameters":[{"name":"from","required":false,"in":"query","description":"First day of the window, inclusive, as a calendar date in the\nORGANIZATION's timezone — the same convention as `/today/bookings`, so\neveryone in one business reads the same range. Omit both to get the\nlast 30 days.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Last day of the window, inclusive.","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"The window as a span instead: one of the three the picker offers, counted\nback from today in the ORGANIZATION's timezone.\n\nIt exists so the page never computes dates in the browser. \"Last 7 days\"\ncounted in the reader's calendar is a different seven days from a\ncolleague's a timezone away, over the same URL — and the response says\nwhich days it measured, so the page can print them.\n\nMutually exclusive with `from`/`to`; the shared constraint reports that.","schema":{"type":"number","enum":[7,30,90]}},{"name":"trigger","required":false,"in":"query","schema":{"type":"string","enum":["MANUAL","CONTACT_OPTED_OUT","PHRASE_EXACT","PHRASE_CONTAINS","SEMANTIC","MODEL_TOOL","ERROR_BUDGET"]}},{"name":"presetKey","required":false,"in":"query","description":"A preset catalog key, e.g. `CUSTOMER_ASKS_HUMAN`.","schema":{"pattern":"^[A-Z0-9_]{1,64}$","type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The conversations handed to a person, for one reason or all","tags":["AI Lead Responder"]}},"/ai-lead-responder/feedback/incorrect":{"get":{"operationId":"AiLeadResponderController_listIncorrectReplies","parameters":[{"name":"from","required":false,"in":"query","description":"First day of the window, inclusive, as a calendar date in the\nORGANIZATION's timezone — the same convention as `/today/bookings`, so\neveryone in one business reads the same range. Omit both to get the\nlast 30 days.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Last day of the window, inclusive.","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"The window as a span instead: one of the three the picker offers, counted\nback from today in the ORGANIZATION's timezone.\n\nIt exists so the page never computes dates in the browser. \"Last 7 days\"\ncounted in the reader's calendar is a different seven days from a\ncolleague's a timezone away, over the same URL — and the response says\nwhich days it measured, so the page can print them.\n\nMutually exclusive with `from`/`to`; the shared constraint reports that.","schema":{"type":"number","enum":[7,30,90]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The AI replies a teammate marked wrong, with why","tags":["AI Lead Responder"]}},"/ai-lead-responder/drafts":{"get":{"operationId":"AiLeadResponderController_listDraftActivity","parameters":[{"name":"from","required":false,"in":"query","description":"First day of the window, inclusive, as a calendar date in the\nORGANIZATION's timezone — the same convention as `/today/bookings`, so\neveryone in one business reads the same range. Omit both to get the\nlast 30 days.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Last day of the window, inclusive.","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"The window as a span instead: one of the three the picker offers, counted\nback from today in the ORGANIZATION's timezone.\n\nIt exists so the page never computes dates in the browser. \"Last 7 days\"\ncounted in the reader's calendar is a different seven days from a\ncolleague's a timezone away, over the same URL — and the response says\nwhich days it measured, so the page can print them.\n\nMutually exclusive with `from`/`to`; the shared constraint reports that.","schema":{"type":"number","enum":[7,30,90]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"outcome","required":false,"in":"query","schema":{"type":"string","enum":["APPROVED","EDITED","REJECTED","SUPERSEDED","PENDING","UNDECIDED"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The drafts the responder wrote for approval, and what became of each","tags":["AI Lead Responder"]}},"/ai-lead-responder/bookings/ai-first":{"get":{"operationId":"AiLeadResponderController_listAiFirstBookings","parameters":[{"name":"from","required":false,"in":"query","description":"First day of the window, inclusive, as a calendar date in the\nORGANIZATION's timezone — the same convention as `/today/bookings`, so\neveryone in one business reads the same range. Omit both to get the\nlast 30 days.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Last day of the window, inclusive.","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"The window as a span instead: one of the three the picker offers, counted\nback from today in the ORGANIZATION's timezone.\n\nIt exists so the page never computes dates in the browser. \"Last 7 days\"\ncounted in the reader's calendar is a different seven days from a\ncolleague's a timezone away, over the same URL — and the response says\nwhich days it measured, so the page can print them.\n\nMutually exclusive with `from`/`to`; the shared constraint reports that.","schema":{"type":"number","enum":[7,30,90]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The leads the AI answered first that went on to book","tags":["AI Lead Responder"]}},"/ai-lead-responder/won":{"get":{"operationId":"AiLeadResponderController_listWonWork","parameters":[{"name":"from","required":false,"in":"query","description":"First day of the window, inclusive, as a calendar date in the\nORGANIZATION's timezone — the same convention as `/today/bookings`, so\neveryone in one business reads the same range. Omit both to get the\nlast 30 days.","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Last day of the window, inclusive.","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"The window as a span instead: one of the three the picker offers, counted\nback from today in the ORGANIZATION's timezone.\n\nIt exists so the page never computes dates in the browser. \"Last 7 days\"\ncounted in the reader's calendar is a different seven days from a\ncolleague's a timezone away, over the same URL — and the response says\nwhich days it measured, so the page can print them.\n\nMutually exclusive with `from`/`to`; the shared constraint reports that.","schema":{"type":"number","enum":[7,30,90]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"bucket","required":false,"in":"query","schema":{"type":"string","enum":["VERIFIED","INFERRED","MANUAL"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"The work won in the window, by how far it is confirmed","tags":["AI Lead Responder"]}},"/webhook-endpoints":{"post":{"operationId":"WebhooksController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookEndpointDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Create Webhook"},"get":{"operationId":"WebhooksController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"List Webhooks"}},"/webhook-endpoints/{id}":{"get":{"operationId":"WebhooksController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Get Webhook By ID"},"patch":{"operationId":"WebhooksController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookEndpointDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Update Webhook"},"delete":{"operationId":"WebhooksController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Delete Webhook"}},"/webhook-endpoints/{id}/rotate-secret":{"post":{"operationId":"WebhooksController_rotateSecret","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Rotate Secret"}},"/webhook-endpoints/{id}/send-test":{"post":{"operationId":"WebhooksController_sendTest","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Webhooks"],"summary":"Send Test"}},"/webhook-deliveries":{"get":{"operationId":"WebhookDeliveriesController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WebhookDeliveries"],"summary":"List Webhook Deliveries"}},"/webhook-deliveries/metrics":{"get":{"operationId":"WebhookDeliveriesController_metrics","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WebhookDeliveries"],"summary":"Metrics Webhook Delivery"}},"/webhook-deliveries/{id}":{"get":{"operationId":"WebhookDeliveriesController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WebhookDeliveries"],"summary":"Get Webhook Delivery By ID"}},"/webhook-deliveries/{id}/retry":{"post":{"operationId":"WebhookDeliveriesController_retry","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["WebhookDeliveries"],"summary":"Retry Webhook Delivery"}},"/inbox/ai-draft":{"post":{"operationId":"AiDraftingController_draft","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiDraftRequestDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/AiDraftResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Generate or rewrite an inbox composer draft","tags":["Inbox"]}},"/field-service/providers":{"get":{"operationId":"FieldServiceController_listProviders","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Providers","tags":["Field Service"]}},"/field-service/connections":{"get":{"operationId":"FieldServiceController_listConnections","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Connections","tags":["Field Service"]}},"/field-service/jobber/authorize":{"get":{"operationId":"FieldServiceController_getJobberAuthorizeUrl","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Jobber Authorize URL","tags":["Field Service"]}},"/field-service/jobnimbus/connect":{"post":{"operationId":"FieldServiceController_connectJobNimbus","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectJobNimbusDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Connect Job Nimbus","tags":["Field Service"],"description":"The response carries the last four characters of the key and nothing more."}},"/field-service/connections/{id}/status-map":{"get":{"operationId":"FieldServiceController_getStatusMap","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Status Map","tags":["Field Service"],"description":"JobNimbus statuses mean. A read, so `:read`: the mapping is not a secret and the screen that shows a job's raw status is the same screen that shows how it is being read."},"put":{"operationId":"FieldServiceController_putStatusMap","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStatusMapDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Put Status Map","tags":["Field Service"],"description":"`:manage`, because this decides what counts as a completed job and therefore what the reports call revenue. Saving it also re-decides the records already stored, so a newly mapped \"Completed\" produces the conversions it should always have — and removing one voids them."}},"/field-service/connections/{id}/status-map/observed":{"get":{"operationId":"FieldServiceController_getObservedStatuses","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Observed Statuses","tags":["Field Service"],"description":"words this connection's own records have arrived with. What makes the mapping screen usable: JobNimbus publishes no endpoint listing a tenant's workflows or statuses, so the choices have to come from the records themselves."}},"/field-service/connections/{id}/webhook-url":{"get":{"operationId":"FieldServiceController_getWebhookUrl","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Get Webhook URL","tags":["Field Service"],"description":"JobNimbus Automation. `:manage`, and its own endpoint rather than a field on the connection list, because the URL contains the connection's webhook secret. Keeping it off the list projection is what stops that credential reaching a read-only screen, a log line or an error report; this is asked for once, by somebody setting the automation up."}},"/field-service/connections/{id}/sync-now":{"post":{"operationId":"FieldServiceController_syncNow","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Sync Now","tags":["Field Service"],"description":"`:manage` rather than `:read`, because pressing it spends the customer's own provider API budget. Throttled per IP by the decorator and per CONNECTION in Redis by the service: the budget belongs to the Jobber account, so five people in one office would otherwise spend it five times over."}},"/field-service/links":{"get":{"operationId":"FieldServiceController_listContactLinks","parameters":[{"name":"contactId","required":true,"in":"query","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Contact Links","tags":["Field Service"],"description":"lead. `:read`, and bound to the organisation by the query itself. Across every connection rather than per connection: the panel this feeds asks \"what is happening with this person\", and a business has one Jobber account."}},"/field-service/links/needs-a-person":{"get":{"operationId":"FieldServiceController_listNeedsAPerson","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":50,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"List Needs A Person","tags":["Field Service"],"description":"Declared BEFORE `links/:id/...` would matter if it shared a method; it does not, but the order is kept deliberate anyway so a later GET on `links/:id` cannot swallow this path. Paged with a total, because this is a work list somebody clears rather than a report: a list that silently stops at a limit tells them the job is done when it is not."}},"/field-service/links/{id}/match":{"post":{"operationId":"FieldServiceController_matchLink","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchLinkDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Match Link","tags":["Field Service"],"description":"`:manage`, because what follows from it is money: a completed job matched here writes the conversion it never got, and the reports change. Tenant-checked on BOTH sides — the record and the lead."}},"/field-service/leads/{contactId}/send":{"post":{"operationId":"FieldServiceController_sendLead","parameters":[{"name":"contactId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendLeadDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Send Lead","tags":["Field Service"],"description":"The ONE thing this integration writes (design D7), so it carries the most checks of any route here: `:manage`, a per-IP throttle by the decorator AND a per-user cap in Redis, both the lead and the connection bound to the caller's organisation, a test lead refused in production, and the person looked up in the provider before anything is created."}},"/field-service/connections/{id}":{"delete":{"operationId":"FieldServiceController_disconnect","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Disconnect Field Service","tags":["Field Service"]}},"/field-service/jobber/callback":{"get":{"operationId":"JobberOAuthCallbackController_handleCallback","parameters":[{"name":"error","required":false,"in":"query","schema":{}},{"name":"state","required":false,"in":"query","schema":{}},{"name":"code","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Field Service"],"summary":"Handle Callback"}},"/voice-agent/config":{"get":{"operationId":"VoiceAgentController_getConfig","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Get Config"},"put":{"operationId":"VoiceAgentController_saveConfig","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVoiceAgentConfigDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Save Config"}},"/voice-agent/enable":{"post":{"operationId":"VoiceAgentController_enable","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Enable Voice Agent"}},"/voice-agent/disable":{"post":{"operationId":"VoiceAgentController_disable","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Disable Voice Agent"}},"/voice-agent/voices":{"get":{"operationId":"VoiceAgentController_listVoices","parameters":[{"name":"employeeId","required":false,"in":"query","description":"The employee whose phone setup's voice leads the list; without it, the organisation's.","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"List Voices"}},"/voice-agent/voices/library":{"get":{"operationId":"VoiceAgentController_listVoiceLibrary","parameters":[{"name":"search","required":false,"in":"query","schema":{"maxLength":80,"type":"string"}},{"name":"gender","required":false,"in":"query","schema":{"maxItems":10,"maxLength":40,"type":"array","items":{"type":"string"}}},{"name":"accent","required":false,"in":"query","schema":{"maxItems":10,"maxLength":40,"type":"array","items":{"type":"string"}}},{"name":"language","required":false,"in":"query","schema":{"maxItems":10,"maxLength":40,"type":"array","items":{"type":"string"}}},{"name":"style","required":false,"in":"query","schema":{"maxItems":10,"maxLength":40,"type":"array","items":{"type":"string"}}},{"name":"recommended","required":false,"in":"query","schema":{"type":"string","enum":["1"]}},{"name":"sort","required":false,"in":"query","schema":{"type":"string","enum":["recommended","name","newest"]}},{"name":"fresh","required":false,"in":"query","description":"`1` when the person pressed Retry — bypasses the 60 s \"unavailable\" marker (L-b).","schema":{"type":"string","enum":["1"]}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":24,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"P9-9 — the provider's whole library, searched, filtered, sorted and paged\nhere; `unavailable` when it cannot be read. P9-11: facets with counts,\nthe recommended voices and the sorts on offer ride along.","tags":["AI Phone Answering"]}},"/voice-agent/voices/adopt":{"post":{"operationId":"VoiceAgentController_adoptVoice","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdoptVoiceDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"P9-9 — a library voice becomes a catalogue row, so a save with it passes the catalogue rule.","tags":["AI Phone Answering"]}},"/voice-agent/webhook-secret/rotate":{"post":{"operationId":"VoiceAgentController_rotateWebhookSecret","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Rotate Webhook Secret"}},"/voice-agent/calls":{"get":{"operationId":"VoiceAgentController_listCalls","parameters":[{"name":"employeeId","required":false,"in":"query","description":"Phase 10 (D11) — only the calls the given AI employee's setup answered (`voice_agent_calls.ai_agent_id`).","schema":{"format":"uuid","type":"string"}},{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"List Calls"}},"/voice-agent/calls/{id}":{"get":{"operationId":"VoiceAgentController_getCall","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Get Call"}},"/voice-agent/calls/{id}/analysis":{"post":{"operationId":"VoiceAgentController_regenerateCallAnalysis","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"P9-10 — regenerate the summary + analysis from the saved transcript; the fresh detail comes back.","tags":["AI Phone Answering"]}},"/voice-agent/calls/{id}/recording":{"get":{"operationId":"VoiceAgentController_getCallRecording","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Item 8 — a short-lived playback link for the recording copied under our key; 404 without one.","tags":["AI Phone Answering"]}},"/voice-agent/number":{"post":{"operationId":"VoiceAgentController_attachNumber","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachVoiceAgentNumberDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Attach Number"},"delete":{"operationId":"VoiceAgentController_releaseNumber","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"No entitlement gate: a lapsed plan must still be able to give the number back (M3).","tags":["AI Phone Answering"]}},"/voice-agent/test-call":{"post":{"operationId":"VoiceAgentController_placeTestCall","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestCallDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"The operator hears the agent on their own phone (R6.5). The per-IP throttle\nis the coarse guard; the product rule — three an hour per organisation —\nis a Redis counter in the service.","tags":["AI Phone Answering"]}},"/voice-agent/phones":{"get":{"operationId":"VoiceAgentEmployeePhoneController_listPhones","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"One line per employee setup for the cards, the unassigned legacy row apart (D2).","tags":["AI Phone Answering"]}},"/ai-employees/{employeeId}/phone":{"get":{"operationId":"VoiceAgentEmployeePhoneController_getPhone","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"The setup's view with the employee's status, or `{ exists: false, employeeStatus }`.","tags":["AI Phone Answering"]},"post":{"operationId":"VoiceAgentEmployeePhoneController_createPhone","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmployeePhoneDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Create the employee's setup, or let it adopt the unassigned legacy row (D2, D7); 409 87020 / 87021.","tags":["AI Phone Answering"]},"put":{"operationId":"VoiceAgentEmployeePhoneController_savePhone","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmployeePhoneDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Save Phone"},"delete":{"operationId":"VoiceAgentEmployeePhoneController_deletePhone","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Only when off and without a number (409 87022 otherwise). No entitlement gate: a lapsed plan may clean up.","tags":["AI Phone Answering"]}},"/ai-employees/{employeeId}/phone/enable":{"post":{"operationId":"VoiceAgentEmployeePhoneController_enable","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Switch on: the employee must be ACTIVE (D7) and a number attached.","tags":["AI Phone Answering"]}},"/ai-employees/{employeeId}/phone/disable":{"post":{"operationId":"VoiceAgentEmployeePhoneController_disable","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Disable Voice Agent Employee Phone"}},"/ai-employees/{employeeId}/phone/number":{"post":{"operationId":"VoiceAgentEmployeePhoneController_attachNumber","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachVoiceAgentNumberDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Attach a number: import one of the organisation's own, buy one, or one already in the voice account.","tags":["AI Phone Answering"]},"put":{"operationId":"VoiceAgentEmployeePhoneController_replaceNumber","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceVoiceAgentNumberDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Swap the employee's number for another in one step; the old one is put back if the new one fails.","tags":["AI Phone Answering"]},"delete":{"operationId":"VoiceAgentEmployeePhoneController_releaseNumber","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"No entitlement gate: a lapsed plan must still be able to give the number back (M3).","tags":["AI Phone Answering"]}},"/ai-employees/{employeeId}/phone/number-candidates":{"get":{"operationId":"VoiceAgentEmployeePhoneController_numberCandidates","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Every number the employee could answer, with who holds it and why one is blocked.","tags":["AI Phone Answering"]}},"/ai-employees/{employeeId}/phone/webhook-secret/rotate":{"post":{"operationId":"VoiceAgentEmployeePhoneController_rotateWebhookSecret","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Rotate Webhook Secret"}},"/ai-employees/{employeeId}/phone/test-call":{"post":{"operationId":"VoiceAgentEmployeePhoneController_placeTestCall","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestCallDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Call my phone (R6.5): the per-IP throttle is the coarse guard; the\nproduct rule — three an hour per organisation — is the service's counter.","tags":["AI Phone Answering"]}},"/voice-agent/settings":{"get":{"operationId":"VoiceAgentOrgSettingsController_getSettings","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Get Settings"},"put":{"operationId":"VoiceAgentOrgSettingsController_updateSettings","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVoiceAgentOrgSettingsDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Phone Answering"],"summary":"Update Settings"}},"/lead-response/profile":{"get":{"operationId":"LeadResponseController_getProfile","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Get the organization's lead-response profile","tags":["Lead Response"]},"put":{"operationId":"LeadResponseController_updateProfile","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLeadProfileDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Update the organization's lead-response profile","tags":["Lead Response"]}},"/lead-profile/trade-pack/preview":{"get":{"operationId":"TradePackController_preview","parameters":[{"name":"trade","required":false,"in":"query","description":"Preview a trade picked but not saved yet (what switching to it would do). Omitted: the saved trade.","schema":{"type":"string","enum":["HVAC","PLUMBING","ELECTRICAL","ROOFING","OTHER"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Preview what applying the trade pack would add (writes nothing)","tags":["Lead Response"]}},"/lead-profile/trade-pack/apply":{"post":{"operationId":"TradePackController_apply","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyTradePackDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"apiKey":[]},{"jwt":[]}],"summary":"Apply the trade pack: adds what is missing, never overwrites edits","tags":["Lead Response"]}},"/bug-reports/attachments/upload-url":{"post":{"operationId":"BugReportsController_getUploadUrl","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBugReportUploadUrlDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Presign an upload for proof attached BEFORE the report is submitted.\nRegistered ahead of ':id' so the literal path is never swallowed by the\nUUID param route.","tags":["Bug Reports"]}},"/bug-reports":{"post":{"operationId":"BugReportsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBugReportDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bug Reports"],"summary":"Create Bug Report"},"get":{"operationId":"BugReportsController_findAll","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bug Reports"],"summary":"List Bug Reports"}},"/bug-reports/{id}":{"get":{"operationId":"BugReportsController_findById","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bug Reports"],"summary":"Get Bug Report By ID"}},"/bug-reports/{id}/comments":{"post":{"operationId":"BugReportsController_addComment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBugReportCommentDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"$ref":"#/components/schemas/IdResponseDto"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Bug Reports"],"summary":"Add Comment"}},"/chat-widget/config":{"get":{"operationId":"ChatWidgetAdminController_getConfig","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Chat Widget"],"summary":"Get Config"},"put":{"operationId":"ChatWidgetAdminController_upsertConfig","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWidgetConfigDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Chat Widget"],"summary":"Upsert Config"}},"/widget-api/{publicKey}/config":{"get":{"operationId":"ChatWidgetPublicController_getConfig","parameters":[{"name":"publicKey","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"`Access-Control-Allow-Origin: *` is forced on this route ONLY (design\nspec Decision 9) via `WidgetConfigCorsMiddleware`, bound in\n`ChatWidgetModule.configure()` — not here. Module middleware (not a\ncontroller interceptor) is deliberate: it runs before the guard\nchain, so the header survives even a guard-rejected response (e.g.\nthe global `ThrottlerGuard`'s 429).","tags":["Public — Chat Widget"]}},"/widget-api/{publicKey}/sessions":{"post":{"operationId":"ChatWidgetPublicController_createSession","parameters":[{"name":"publicKey","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWidgetSessionDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Chat Widget"],"summary":"Create Session"}},"/widget-api/session/resume":{"post":{"operationId":"ChatWidgetPublicController_resumeSession","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResumeWidgetSessionDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Chat Widget"],"summary":"Resume Session"}},"/widget-api/session/messages":{"post":{"operationId":"ChatWidgetPublicController_postMessage","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostWidgetMessageDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Chat Widget"],"summary":"Post Message"},"get":{"operationId":"ChatWidgetPublicController_getMessages","parameters":[{"name":"cursor","required":false,"in":"query","schema":{"maxLength":255,"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":50,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Chat Widget"],"summary":"Get Messages"}},"/widget-api/session/offline-message":{"post":{"operationId":"ChatWidgetPublicController_postOfflineMessage","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostOfflineMessageDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Public — Chat Widget"],"summary":"Post Offline Message"}},"/search":{"get":{"operationId":"SearchController_search","parameters":[{"name":"q","required":true,"in":"query","schema":{"minLength":2,"maxLength":200,"type":"string"}},{"name":"types","required":false,"in":"query","description":"Optional CSV filter, e.g. ?types=contact,campaign","schema":{"type":"array","items":{"type":"string","enum":["contact","campaign","segment","tag","smsTemplate","emailTemplate","whatsappTemplate","joinKeyword","joinLink","shortLink","leadForm","poll","workflow","aiEmployee","meetingType","dashboard","ticket","member"]}}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":10,"default":5,"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Search"],"summary":"Search Search"}},"/marketplace/templates":{"get":{"operationId":"MarketplaceController_list","parameters":[{"name":"page","required":true,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"type","required":false,"in":"query","schema":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","AUTOMATION","LEAD_FORM","SEQUENCE","CAMPAIGN","AI_EMPLOYEE","PLAYBOOK"]}},{"name":"category","required":false,"in":"query","schema":{"maxLength":60,"type":"string"}},{"name":"industry","required":false,"in":"query","schema":{"maxLength":60,"type":"string"}},{"name":"goal","required":false,"in":"query","schema":{"maxLength":60,"type":"string"}},{"name":"channel","required":false,"in":"query","schema":{"type":"string","enum":["SMS","EMAIL"]}},{"name":"difficulty","required":false,"in":"query","schema":{"type":"string","enum":["BEGINNER","INTERMEDIATE","ADVANCED"]}},{"name":"search","required":false,"in":"query","schema":{"maxLength":255,"type":"string"}},{"name":"favoritesOnly","required":false,"in":"query","schema":{"type":"boolean"}},{"name":"sort","required":false,"in":"query","schema":{"type":"string","enum":["popular","newest","name"]}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Marketplace"],"summary":"List Marketplaces"}},"/marketplace/templates/{slug}":{"get":{"operationId":"MarketplaceController_getBySlug","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Marketplace"],"summary":"Get By Slug"}},"/marketplace/templates/{slug}/install":{"post":{"operationId":"MarketplaceController_install","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Marketplace"],"summary":"Install Marketplace"}},"/marketplace/templates/{slug}/favorite":{"put":{"operationId":"MarketplaceController_favorite","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Marketplace"],"summary":"Favorite Marketplace"},"delete":{"operationId":"MarketplaceController_unfavorite","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["Marketplace"],"summary":"Unfavorite Marketplace"}},"/marketplace/playbooks/installations":{"get":{"operationId":"PlaybookInstallationsController_list","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"tags":["PlaybookInstallations"],"summary":"List Playbook Installations"}},"/marketplace/playbooks/readiness":{"get":{"operationId":"PlaybookInstallationsController_readiness","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"summary":"\"Which prerequisites is this organization still missing?\" — the union\nof every shipped playbook's `requires`, run through the SAME resolver\nan install uses, so a card's readiness chip can never promise something\nthe install would put on the checklist. Org-level on purpose: the four\nchecks are facts about the organization, not about any one playbook,\nand each card narrows the answer to its own `requires`.","tags":["PlaybookInstallations"]}},"/ai-employees/{employeeId}/journeys":{"get":{"operationId":"EmployeeJourneysController_list","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Employee Journeys"],"summary":"List Employee Journeys"},"post":{"operationId":"EmployeeJourneysController_create","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJourneyDto"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Employee Journeys"],"summary":"Create Employee Journey"}},"/ai-employees/{employeeId}/journeys/follow-ups/automation":{"get":{"operationId":"EmployeeJourneysController_followUpsAutomation","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"The automation behind the employee's Follow-ups, so the screen can link to\nits runs. Follow-ups are a managed journey, which `list` leaves out.","tags":["AI Employee Journeys"]}},"/ai-employees/{employeeId}/journeys/catalog":{"get":{"operationId":"EmployeeJourneysController_catalog","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"The pre-built journeys for this employee's role and where each stands\nfor it. Declared before `:journeyId` so \"catalog\" is never read as an id.","tags":["AI Employee Journeys"]}},"/ai-employees/{employeeId}/journeys/catalog/install":{"post":{"operationId":"EmployeeJourneysController_installCatalog","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Add whatever this employee's role recommends and it does not have yet —\nthe way back when a journey failed to install, or the employee was hired\nbefore journeys existed. Idempotent: what is already there is left alone.","tags":["AI Employee Journeys"]}},"/ai-employees/{employeeId}/journeys/situations/catalog":{"get":{"operationId":"EmployeeJourneysController_situationCatalog","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"The customer situations this employee can have, grouped, with what it has\nnow and what is still missing. Declared before `:journeyId` so\n\"situations\" is never read as an id.","tags":["AI Employee Journeys"]}},"/ai-employees/{employeeId}/journeys/situations":{"put":{"operationId":"EmployeeJourneysController_saveSituations","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutSituationsDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Replace the employee's customer situations with exactly this set. What is\nnot in it is taken away again, and nothing the owner set by hand is\noverwritten. 400 73005 on a set that breaks a rule.","tags":["AI Employee Journeys"]}},"/ai-employees/{employeeId}/journeys/generate":{"post":{"operationId":"EmployeeJourneysController_generate","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateJourneyDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Turn the owner's words into a journey to look at. Saves nothing and turns\nnothing on: the client sends the spec back through `POST /` and then\n`activate`, each on an explicit click. 422 73008 says in plain words why\nnothing could be written.","tags":["AI Employee Journeys"]}},"/ai-employees/{employeeId}/journeys/{journeyId}":{"get":{"operationId":"EmployeeJourneysController_get","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"journeyId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Employee Journeys"],"summary":"Get Employee Journey"},"put":{"operationId":"EmployeeJourneysController_update","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"journeyId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateJourneyDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"409 73001 when it was changed in the advanced editor — revert first.","tags":["AI Employee Journeys"]},"delete":{"operationId":"EmployeeJourneysController_remove","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"journeyId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"No entitlement gate, like pause: removing must work on a lapsed plan.","tags":["AI Employee Journeys"]}},"/ai-employees/{employeeId}/journeys/{journeyId}/activate":{"post":{"operationId":"EmployeeJourneysController_activate","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"journeyId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"409 73004 with the pending items when the organization is missing something.","tags":["AI Employee Journeys"]}},"/ai-employees/{employeeId}/journeys/{journeyId}/pause":{"post":{"operationId":"EmployeeJourneysController_pause","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"journeyId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"No entitlement gate: a lapsed plan must still be able to switch a journey off.","tags":["AI Employee Journeys"]}},"/ai-employees/{employeeId}/journeys/{journeyId}/revert":{"post":{"operationId":"EmployeeJourneysController_revert","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"journeyId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["AI Employee Journeys"],"summary":"Revert Employee Journey"}},"/meeting-types/{meetingTypeId}/follow-ups":{"get":{"operationId":"MeetingTypeFollowUpsController_list","parameters":[{"name":"meetingTypeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"tags":["Meeting Types"],"summary":"List Meeting Type Follow Ups"}},"/meeting-types/{meetingTypeId}/follow-ups/{kind}":{"patch":{"operationId":"MeetingTypeFollowUpsController_set","parameters":[{"name":"meetingTypeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"kind","required":true,"in":"path","schema":{"enum":["REVIEW_REQUEST","NO_SHOW_RECOVERY","ESTIMATE_FOLLOW_UP"],"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetFollowUpDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Switching one on builds and publishes an automation, so it takes the automation grants too.","tags":["Meeting Types"]}},"/ai-employees/{employeeId}/channels":{"get":{"operationId":"EmployeeChannelsController_list","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Where this AI employee answers, and what else the workspace has","tags":["AI Employee Channels"]}},"/ai-employees/{employeeId}/channels/skipped-picks":{"delete":{"operationId":"EmployeeChannelsController_dismissSkippedPicks","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Dismiss the notice about picked channels this AI employee did not get","tags":["AI Employee Channels"]}},"/ai-employees/{employeeId}/channels/{identityId}":{"put":{"operationId":"EmployeeChannelsController_assign","parameters":[{"name":"employeeId","required":true,"in":"path","schema":{"type":"string"}},{"name":"identityId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetEmployeeChannelDto"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Have this AI employee answer on a number, inbox or widget - or stop","tags":["AI Employee Channels"]}},"/channels/overview":{"get":{"operationId":"ChannelsOverviewController_get","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccessResponse"}}}},"default":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}},"security":[{"jwt":[]}],"summary":"Every channel in the workspace, with its status and who answers it","tags":["Channels"]}}},"info":{"title":"Text Campaign API","description":"Multi-tenant SMS campaign platform. Authenticate with a JWT (`Authorization: Bearer <jwt>`) for first-party calls, or an organization API key (`Authorization: Bearer et_live_…`) for server-to-server access.","version":"1.0.0","contact":{}},"tags":[],"servers":[{"url":"/"}],"components":{"securitySchemes":{"jwt":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"JWT access token from POST /auth/login"},"apiKey":{"scheme":"bearer","bearerFormat":"API Key","type":"http","description":"Organization API key (et_live_…) from POST /api-keys"}},"schemas":{"OrganizationSettingsDto":{"type":"object","properties":{"logoUrl":{"type":"string","nullable":true},"streetAddress":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"country":{"type":"string"},"countryCode":{"type":"string"},"zipCode":{"type":"string"},"currency":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"googlePlaceId":{"type":"string"}}},"OrganizationResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"plan":{"enum":["FREE","STARTER","PRO","ENTERPRISE"],"type":"string"},"settings":{"$ref":"#/components/schemas/OrganizationSettingsDto"},"timezone":{"type":"string"},"quietHoursStart":{"type":"string","nullable":true},"quietHoursEnd":{"type":"string","nullable":true},"defaultCountryCode":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"optOutReplyMessage":{"type":"string","nullable":true},"optInReplyMessage":{"type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","name","slug","plan","settings","timezone","quietHoursStart","quietHoursEnd","defaultCountryCode","email","phone","website","optOutReplyMessage","optInReplyMessage","createdAt","updatedAt"]},"CreateOrganizationDto":{"type":"object","properties":{"name":{"type":"string"},"timezone":{"type":"string"},"email":{"type":"string","maxLength":255,"format":"email"},"defaultCountryCode":{"type":"string","description":"ISO-3166-1 alpha-2 dialling country — see `common/phone`."},"phone":{"type":"string","maxLength":32},"website":{"type":"string","maxLength":500,"format":"uri"}},"required":["name"]},"CreateOrganizationResponseDto":{"type":"object","properties":{"organization":{"$ref":"#/components/schemas/OrganizationResponseDto"},"accessToken":{"type":"string"}},"required":["organization","accessToken"]},"SwitchOrganizationDto":{"type":"object","properties":{"organizationId":{"type":"string","format":"uuid"}},"required":["organizationId"]},"ContactCardResponseDto":{"type":"object","properties":{"businessName":{"type":"string"},"phoneE164":{"type":"string"},"email":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"logoStorageKey":{"type":"string","nullable":true},"vcardUrl":{"type":"string","nullable":true},"vcardSizeBytes":{"type":"number","nullable":true},"logoUrl":{"type":"string","nullable":true,"description":"Public URL of the logo embedded in the card, for previews in the UI."},"updatedAt":{"format":"date-time","type":"string","nullable":true}},"required":["businessName","phoneE164","email","website","logoStorageKey","vcardUrl","vcardSizeBytes","logoUrl","updatedAt"]},"UpdateContactCardDto":{"type":"object","properties":{"businessName":{"type":"string","minLength":1,"maxLength":150},"phoneE164":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$"},"email":{"type":"string","nullable":true,"maxLength":255},"website":{"type":"string","nullable":true,"maxLength":500,"format":"uri"},"logoStorageKey":{"type":"string","nullable":true,"maxLength":512}},"required":["businessName","phoneE164"]},"BusinessHoursStatusDto":{"type":"object","properties":{"open":{"type":"boolean"},"reason":{"type":"string","enum":["open","always-open","invalid-timezone","date-override","holiday","closed-day","outside-hours"]},"nextOpenAt":{"type":"string","nullable":true,"description":"UTC instant of the next opening. Format it in `timezone`, not the viewer's."}},"required":["open","reason","nextOpenAt"]},"OrganizationBusinessHoursResponseDto":{"type":"object","properties":{"timezone":{"type":"string","description":"Echoed from `Organization.timezone` — read-only on this endpoint."},"weekly":{"type":"object"},"overrides":{"type":"array","items":{"type":"object"}},"isUnset":{"type":"boolean","description":"True when nothing is configured yet, i.e. the org is always open."},"status":{"$ref":"#/components/schemas/BusinessHoursStatusDto"}},"required":["timezone","weekly","overrides","isUnset","status"]},"BusinessHoursIntervalDto":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"}},"required":["start","end"]},"BusinessHoursWeeklyDto":{"type":"object","properties":{"mon":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursIntervalDto"}},"tue":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursIntervalDto"}},"wed":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursIntervalDto"}},"thu":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursIntervalDto"}},"fri":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursIntervalDto"}},"sat":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursIntervalDto"}},"sun":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursIntervalDto"}}}},"BusinessHoursOverrideDto":{"type":"object","properties":{"date":{"type":"string"},"intervals":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursIntervalDto"}},"reason":{"type":"string","maxLength":120}},"required":["date","intervals"]},"UpdateOrganizationBusinessHoursDto":{"type":"object","properties":{"weekly":{"$ref":"#/components/schemas/BusinessHoursWeeklyDto"},"overrides":{"description":"Date-specific hours; an entry with no intervals closes that date.","type":"array","items":{"$ref":"#/components/schemas/BusinessHoursOverrideDto"}}},"required":["weekly"]},"CreateRoleDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":500},"permissionIds":{"description":"Direct permission ID list. Kept for backwards-compat with seeders and\ntests. Either this or `matrix` must be provided.","type":"array","items":{"type":"string","format":"uuid"}},"matrix":{"type":"object","additionalProperties":true,"description":"Per-module CRUD selection matrix from the UI. The service expands this\ninto the full real permission set before persisting."}},"required":["name"]},"TransferOwnershipDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"}},"required":["userId"]},"AssignRoleDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"roleId":{"type":"string","format":"uuid"}},"required":["userId","roleId"]},"UpdateRoleDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"description":{"type":"string","maxLength":500},"permissionIds":{"type":"array","items":{"type":"string","format":"uuid"}},"matrix":{"type":"object","additionalProperties":true}}},"RemoveMemberDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"}},"required":["userId"]},"SubscriptionCheckoutDto":{"type":"object","properties":{"kind":{"type":"string","enum":["SUBSCRIPTION","PLAN_CHANGE"]},"targetRef":{"type":"string","description":"planVersionId (or plan slug) from GET /billing/plans."},"billingInterval":{"type":"string","enum":["month","year"]},"successUrl":{"type":"string","format":"uri"},"cancelUrl":{"type":"string","format":"uri"}},"required":["kind","targetRef","successUrl","cancelUrl"]},"AddOnCheckoutDto":{"type":"object","properties":{"billingInterval":{"type":"string","enum":["month","year"]},"successUrl":{"type":"string","format":"uri"},"cancelUrl":{"type":"string","format":"uri"}},"required":["successUrl","cancelUrl"]},"BillingPortalDto":{"type":"object","properties":{"returnUrl":{"type":"string","description":"Where Stripe returns the user after the portal (the billing page).","format":"uri"}},"required":["returnUrl"]},"AddOnPurchaseDto":{"type":"object","properties":{"billingInterval":{"enum":["month","year"],"type":"string"},"successUrl":{"type":"string","format":"uri"},"cancelUrl":{"type":"string","format":"uri"},"autoRefill":{"type":"boolean","description":"Enable threshold auto-refill on the resulting grant."},"refillThreshold":{"type":"number","description":"Remaining-units trigger — required when autoRefill is true.","minimum":1}},"required":["successUrl","cancelUrl"]},"AutoRefillUpdateDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Turn the policy on/off (also resumes a system-paused policy)."},"threshold":{"type":"number","description":"Remaining-units trigger.","minimum":1}}},"CreditPackCheckoutDto":{"type":"object","properties":{"billingInterval":{"enum":["month","year"],"type":"string"},"successUrl":{"type":"string","format":"uri"},"cancelUrl":{"type":"string","format":"uri"},"targetRef":{"type":"string","description":"Credit-pack add-on key from GET /billing/add-ons."}},"required":["successUrl","cancelUrl","targetRef"]},"UserResponseDto":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE","SUSPENDED"],"type":"string"},"avatarUrl":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true},"timezone":{"type":"string","nullable":true},"locale":{"type":"string","nullable":true},"lastLoginAt":{"format":"date-time","type":"string","nullable":true},"lastActiveOrgId":{"type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"hasPassword":{"type":"boolean","description":"`false` for accounts created through Google / Microsoft sign-in that\nhave not set a password yet — the profile's security card then offers\n\"Set a password\" (no current-password prompt) instead of \"Change\"."}},"required":["id","email","firstName","lastName","status","avatarUrl","phone","timezone","locale","lastLoginAt","lastActiveOrgId","createdAt","updatedAt","hasPassword"]},"UpdateUserDto":{"type":"object","properties":{"firstName":{"type":"string","maxLength":100},"lastName":{"type":"string","description":"`''` is allowed: it is how the profile form clears a surname.","maxLength":100},"phone":{"type":"string","nullable":true,"description":"`null` clears a stored number; omitting the key leaves it untouched.\n`@IsOptional()` skips both null and undefined, so the decorators below\nonly ever see a real string. `''` is not a way to clear — it fails the\nsix-character floor in `PHONE_INPUT_REGEX`.","maxLength":32},"timezone":{"type":"string","maxLength":50},"locale":{"type":"string","maxLength":10}}},"ChangePasswordDto":{"type":"object","properties":{"currentPassword":{"type":"string","description":"Required whenever the account has a password; may be omitted only by an\nOAuth-created account that is setting its first one. The service, not\nthe DTO, decides — it knows whether a hash exists."},"newPassword":{"type":"string","minLength":8}},"required":["newPassword"]},"NotificationViewDto":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["MESSAGE","ALERT"]},"category":{"type":"string","enum":["CAMPAIGN_REPLY","CONVERSATION_ASSIGNED","CAMPAIGN_PAUSED","CAMPAIGN_RESUMED","CAMPAIGN_COMPLETED","POLL_CLOSED","POLL_EXPIRED","VOICEMAIL_RECEIVED","MEETING_BOOKED","MEETING_RESCHEDULED","MEETING_CANCELLED","CALENDAR_CONNECTION_BROKEN","AD_CONNECTION_BROKEN","INBOUND_MESSAGE","CONVERSATION_NOTE_MENTION","CONVERSATION_SNOOZE_ENDED","CAMPAIGN_SCHEDULED","CAMPAIGN_STARTED","CAMPAIGN_FAILED","CAMPAIGN_EXPERIMENT_APPROVAL_NEEDED","CAMPAIGN_EXPERIMENT_DECIDED","CAMPAIGN_EXPERIMENT_WINNER_SENT","CSV_IMPORT_COMPLETED","CSV_IMPORT_FAILED","SEGMENT_CREATED","SEGMENT_UPDATED","BULK_OPERATION_COMPLETED","POLL_ACTIVATED","USER_INVITED","USER_JOINED","USER_ROLE_CHANGED","CHANNEL_CONNECTED","CHANNEL_DISCONNECTED","CHANNEL_ERROR","PROVIDER_ERROR","KB_SOURCE_INGESTED","AI_HANDOVER_REQUESTED","AI_SUSPENDED","MISSED_CALL","OUT_OF_AREA_REQUEST","CALENDAR_EVENT_DESYNCED","WORKFLOW_ALERT","TICKET_ASSIGNED","OPPORTUNITY_ASSIGNED","OPPORTUNITY_COMMENT_MENTION","OPPORTUNITY_TASK_ASSIGNED","OPPORTUNITY_WON","LEAD_FORM_SUBMISSION","BUG_REPORT_UPDATED","BILLING_LOW_CREDITS"]},"title":{"type":"string"},"body":{"type":"string"},"referenceType":{"type":"string"},"referenceId":{"type":"string","nullable":true},"actionUrl":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":true,"nullable":true},"actorUserId":{"type":"string","nullable":true},"isRead":{"type":"boolean"},"createdAt":{"type":"string","description":"ISO-8601 timestamp."}},"required":["id","type","category","title","body","referenceType","referenceId","actionUrl","metadata","actorUserId","isRead","createdAt"]},"NotificationListResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/NotificationViewDto"}},"nextCursor":{"type":"string","nullable":true}},"required":["items","nextCursor"]},"UnreadCountsResponseDto":{"type":"object","properties":{"messageUnread":{"type":"number"},"alertUnread":{"type":"number"}},"required":["messageUnread","alertUnread"]},"NotificationSyncResponseDto":{"type":"object","properties":{"notifications":{"type":"array","items":{"$ref":"#/components/schemas/NotificationViewDto"}},"counts":{"$ref":"#/components/schemas/UnreadCountsResponseDto"}},"required":["notifications","counts"]},"IdResponseDto":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"MarkReadDto":{"type":"object","properties":{"type":{"type":"string","enum":["MESSAGE","ALERT"]}}},"MarkAllReadResponseDto":{"type":"object","properties":{"type":{"type":"string","nullable":true,"enum":["MESSAGE","ALERT"]}},"required":["type"]},"StaffNotifyChannelsDto":{"type":"object","properties":{"inApp":{"type":"boolean"},"email":{"type":"boolean"},"sms":{"type":"boolean"}},"required":["inApp","email","sms"]},"StaffNotifyRecipientsDto":{"type":"object","properties":{"owner":{"type":"boolean"},"admins":{"type":"boolean"},"assignee":{"type":"boolean"}},"required":["owner","admins","assignee"]},"StaffNotifyRuleDto":{"type":"object","properties":{"channels":{"$ref":"#/components/schemas/StaffNotifyChannelsDto"},"recipients":{"$ref":"#/components/schemas/StaffNotifyRecipientsDto"}},"required":["channels","recipients"]},"MissedCallRuleDto":{"type":"object","properties":{"channels":{"$ref":"#/components/schemas/StaffNotifyChannelsDto"},"recipients":{"$ref":"#/components/schemas/StaffNotifyRecipientsDto"},"afterMinutes":{"type":"number","minimum":1,"maximum":1440}},"required":["channels","recipients","afterMinutes"]},"HandoverUnclaimedRuleDto":{"type":"object","properties":{"channels":{"$ref":"#/components/schemas/StaffNotifyChannelsDto"},"recipients":{"$ref":"#/components/schemas/StaffNotifyRecipientsDto"},"afterMinutes":{"type":"number","minimum":1,"maximum":240}},"required":["channels","recipients","afterMinutes"]},"UpdateStaffNotificationsDto":{"type":"object","properties":{"handover":{"$ref":"#/components/schemas/StaffNotifyRuleDto"},"hotLead":{"$ref":"#/components/schemas/StaffNotifyRuleDto"},"emergency":{"$ref":"#/components/schemas/StaffNotifyRuleDto"},"missedCallUnanswered":{"$ref":"#/components/schemas/MissedCallRuleDto"},"handoverUnclaimed":{"description":"Optional so a screen from before this moment existed can still save: when\nit is left out, what is stored for it stays (see the settings service).","allOf":[{"$ref":"#/components/schemas/HandoverUnclaimedRuleDto"}]}},"required":["handover","hotLead","emergency","missedCallUnanswered"]},"CreateOptOutKeywordDto":{"type":"object","properties":{"keyword":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^\\s]+(?:\\s+[^\\s]+)*$"}},"required":["keyword"]},"UpdateOptOutKeywordDto":{"type":"object","properties":{"keyword":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^\\s]+(?:\\s+[^\\s]+)*$"}},"required":["keyword"]},"UpdateReplyMessageDto":{"type":"object","properties":{"replyMessage":{"type":"string","nullable":true,"maxLength":1600}},"required":["replyMessage"]},"CreateContactDto":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","maxLength":100},"phone":{"type":"string","nullable":true,"minLength":1,"maxLength":32},"email":{"type":"string","format":"email"},"status":{"type":"string","enum":["ACTIVE","INVALID","ARCHIVED"]},"tagIds":{"type":"array","items":{"type":"string","format":"uuid"}},"streetAddress":{"type":"string","maxLength":255},"addressLine2":{"type":"string","maxLength":255},"city":{"type":"string","maxLength":100},"state":{"type":"string","maxLength":100},"postalCode":{"type":"string","maxLength":20},"country":{"type":"string","maxLength":100},"avatarBgColor":{"type":"string","maxLength":7},"companyName":{"type":"string","maxLength":200},"jobTitle":{"type":"string","maxLength":120},"isOptedOut":{"type":"boolean","description":"Portal-driven initial opt-out. When `true` at create time, the contact\nis born already opted-out (no messages will be sent until an agent\nre-opts them in). Audited via `OPTED_OUT` activity log; not emitted as\na transition event since there's no prior state to transition from."},"source":{"type":"string","description":"How this contact reached the business. Omitted means `MANUAL` (a record\nsomebody typed in). A lead source — `WEB_FORM`, `LEAD_FORM`, `GOOGLE_ADS`, … —\nmarks it as an inbound lead: the response clock starts and the Lead Response\nplaybook answers it.","enum":["MANUAL","WEB_FORM","LEAD_FORM","JOIN_KEYWORD","WEB_CHAT","INBOUND_SMS","INBOUND_EMAIL","INBOUND_CALL","INBOUND_WHATSAPP","TEXT_LINK","GOOGLE_ADS","META_ADS"]},"sourceDetail":{"type":"string","description":"The system or campaign behind the lead, e.g. `angi` or `website-zapier`.","minLength":1,"maxLength":64},"message":{"type":"string","description":"What the lead wrote when they asked — kept on the contact's timeline.","minLength":1,"maxLength":2000}},"required":["firstName"]},"Object":{"type":"object","properties":{}},"ContactTagSummaryDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"string","nullable":true}},"required":["id","name"]},"ContactTagLinkDto":{"type":"object","properties":{"tag":{"$ref":"#/components/schemas/ContactTagSummaryDto"}},"required":["tag"]},"ContactEmailSubscriptionDto":{"type":"object","properties":{"isSubscribed":{"type":"boolean"},"reason":{"type":"string","description":"Why the address is suppressed. Absent while subscribed.","enum":["MANUAL","UNSUBSCRIBED","HARD_BOUNCE","SPAM_REPORT"]},"since":{"format":"date-time","type":"string","description":"When the suppression was recorded. Absent while subscribed."},"canResubscribe":{"type":"boolean","description":"Whether a team member may re-subscribe this address. `false` when the\nperson unsubscribed themselves or reported spam. Absent while subscribed."}},"required":["isSubscribed"]},"ContactAdvertisingDto":{"type":"object","properties":{"platform":{"type":"string","enum":["GOOGLE_ADS","META_ADS"]},"campaignName":{"type":"string"},"leadFormName":{"type":"string"},"firstContactAt":{"format":"date-time","type":"string"},"latestCampaignName":{"type":"string"}},"required":["platform","firstContactAt"]},"ContactResponseDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","nullable":true},"status":{"enum":["ACTIVE","INVALID","ARCHIVED"],"type":"string"},"source":{"enum":["TEXT_LINK","JOIN_KEYWORD","CSV_IMPORT","MANUAL","WEB_FORM","INBOUND_SMS","INBOUND_CALL","GOOGLE_ADS","META_ADS","INBOUND_EMAIL","INBOUND_WHATSAPP","LEAD_FORM","WEB_CHAT"],"type":"string"},"stage":{"enum":["ARCHIVED","NEW_LEAD","ENGAGED","QUALIFIED","APPOINTMENT_BOOKED","CUSTOMER","LOST","BOOKING_PENDING","ESTIMATE_GIVEN","DECIDING","NOT_QUALIFIED"],"type":"string"},"stageChangedAt":{"format":"date-time","type":"string","nullable":true},"leadScore":{"nullable":true,"description":"Lead temperature — written by the system, read-only here.","enum":["HOT","WARM","COLD"],"type":"string"},"leadScoreReasons":{"nullable":true,"description":"Short reason codes behind `leadScore`.","type":"array","items":{"type":"string"}},"nextFollowUpAt":{"format":"date-time","type":"string","nullable":true,"description":"When the next automated follow-up may happen."},"decisionReason":{"type":"string","nullable":true,"description":"Why the customer has not decided (one of `DECISION_REASONS`)."},"decisionSource":{"type":"string","nullable":true,"description":"Who recorded the decision: `ai` (undoable for 7 days), `sync` or `user`."},"decidedAt":{"format":"date-time","type":"string","nullable":true},"estimates":{"description":"Estimates given to this lead, newest first (detail response only).","type":"array","items":{"type":"object"}},"isOptedOut":{"type":"boolean","description":"The ONE opt-out for every channel (SMS, WhatsApp, email, calls). Set by a\nSTOP on SMS or WhatsApp, an email unsubscribe, blocking a caller, or the\nstaff switch."},"optedOutAt":{"format":"date-time","type":"string","nullable":true},"optedInAt":{"format":"date-time","type":"string","nullable":true},"optOutSource":{"nullable":true,"description":"Who opted the contact out: CONTACT (the person — STOP, an unsubscribe\nlink; only they can opt back in, save an email-only contact's email\nopt-out) or STAFF (a team member may undo it). Null while opted in.","enum":["CONTACT","STAFF"],"type":"string"},"optOutChannel":{"nullable":true,"description":"The channel the opt-out came in on; null for the staff switch.","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"],"type":"string"},"whatsappOptIn":{"type":"boolean","nullable":true,"description":"WhatsApp consent, separate from SMS: `false` after a WhatsApp STOP,\n`true` once the contact messaged in (or re-subscribed with START),\n`null` when never established."},"whatsappOptInSource":{"type":"string","nullable":true},"whatsappOptInAt":{"format":"date-time","type":"string","nullable":true},"whatsappOptedOutAt":{"format":"date-time","type":"string","nullable":true},"streetAddress":{"type":"string","nullable":true},"addressLine2":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"state":{"type":"string","nullable":true},"postalCode":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"avatarBgColor":{"type":"string","nullable":true},"companyName":{"type":"string","nullable":true},"jobTitle":{"type":"string","nullable":true},"isSample":{"type":"boolean","description":"True for a record from the removable sample dataset."},"customFields":{"type":"object","additionalProperties":true},"lastContactedAt":{"format":"date-time","type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/ContactTagLinkDto"}},"emailSubscription":{"description":"Omitted when the contact has no email address.","allOf":[{"$ref":"#/components/schemas/ContactEmailSubscriptionDto"}]},"advertising":{"description":"Detail endpoint only — omitted when the contact has no ad attribution.","allOf":[{"$ref":"#/components/schemas/ContactAdvertisingDto"}]}},"required":["id","organizationId","firstName","lastName","phone","email","status","source","stage","stageChangedAt","leadScore","leadScoreReasons","nextFollowUpAt","decisionReason","decisionSource","decidedAt","isOptedOut","optedOutAt","optedInAt","optOutSource","optOutChannel","whatsappOptIn","whatsappOptInSource","whatsappOptInAt","whatsappOptedOutAt","streetAddress","addressLine2","city","state","postalCode","country","avatarBgColor","companyName","jobTitle","isSample","customFields","lastContactedAt","createdAt","updatedAt","tags"]},"UpdateContactDto":{"type":"object","properties":{"nextFollowUpAt":{"format":"date-time","type":"string","nullable":true,"description":"When the next automated follow-up may happen (\"call me in March\")."},"decisionReason":{"type":"string","nullable":true,"description":"Why the customer has not decided — one of `DECISION_REASONS`.","enum":["price","timing","other_quotes","insurance","financing","no_response","other"]}}},"SetPreferredCallerIdDto":{"type":"object","properties":{"channelIdentityId":{"type":"string","nullable":true,"format":"uuid"}},"required":["channelIdentityId"]},"UpdateContactStageDto":{"type":"object","properties":{"stage":{"type":"string","enum":["ARCHIVED","NEW_LEAD","ENGAGED","QUALIFIED","APPOINTMENT_BOOKED","CUSTOMER","LOST","BOOKING_PENDING","ESTIMATE_GIVEN","DECIDING","NOT_QUALIFIED"]},"reason":{"type":"string","maxLength":500}},"required":["stage"]},"MarkWonDto":{"type":"object","properties":{"value":{"type":"number","minimum":0,"maximum":9999999999}}},"ManageTagsDto":{"type":"object","properties":{"tagIds":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["tagIds"]},"CreateContactNoteDto":{"type":"object","properties":{"body":{"type":"string","minLength":1},"bodyFormat":{"type":"string","description":"Omitted by existing clients, which keeps them on the historical\nplain-text behaviour — the column default is `PLAIN` too.","enum":["PLAIN","HTML"]}},"required":["body"]},"CreateEstimateDto":{"type":"object","properties":{"amount":{"type":"number","minimum":0,"maximum":9999999999,"description":"The quoted total."},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"Three-letter currency code. Defaults to USD."},"sentAt":{"format":"date-time","type":"string","description":"When it was sent. Defaults to now."},"validUntil":{"format":"date-time","type":"string"},"note":{"type":"string","maxLength":1000}},"required":["amount"]},"UpdateEstimateDto":{"type":"object","properties":{"status":{"enum":["SENT","ACCEPTED","DECLINED","EXPIRED"],"type":"string"},"amount":{"type":"number","minimum":0,"maximum":9999999999},"validUntil":{"format":"date-time","type":"string"},"note":{"type":"string","maxLength":1000},"declinedReason":{"enum":["price","timing","other_quotes","insurance","financing","no_response","other"],"type":"string","description":"Why it was declined."}}},"TagColorDto":{"type":"object","properties":{"fg":{"type":"string","pattern":"^#[0-9a-fA-F]{3,8}$"},"bg":{"type":"string","pattern":"^#[0-9a-fA-F]{3,8}$"}},"required":["fg","bg"]},"CreateTagDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50},"color":{"$ref":"#/components/schemas/TagColorDto"}},"required":["name"]},"UpdateTagDto":{"type":"object","properties":{}},"CreateModuleDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"displayName":{"type":"string","maxLength":255},"singularName":{"type":"string","maxLength":255},"pluralName":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":2000},"icon":{"type":"string","maxLength":64},"color":{"type":"string","maxLength":64}},"required":["name"]},"ReorderDto":{"type":"object","properties":{"orderedIds":{"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["orderedIds"]},"ModuleSettingsDto":{"type":"object","properties":{"showInNav":{"type":"boolean","description":"Show the module in the dynamic \"Modules\" nav (default true)."},"recordsPerPage":{"type":"number","description":"Default page size for the records list.","minimum":10,"maximum":100}}},"UpdateModuleDto":{"type":"object","properties":{"displayName":{"type":"string","maxLength":255},"singularName":{"type":"string","maxLength":255},"pluralName":{"type":"string","maxLength":255},"description":{"type":"string","maxLength":2000},"icon":{"type":"string","maxLength":64},"color":{"type":"string","maxLength":64},"isActive":{"type":"boolean"},"settings":{"$ref":"#/components/schemas/ModuleSettingsDto"}}},"CreateSectionDto":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"columns":{"type":"number","minimum":1,"maximum":4},"isCollapsible":{"type":"boolean"},"isDefaultCollapsed":{"type":"boolean"}},"required":["displayName"]},"UpdateSectionDto":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"columns":{"type":"number","minimum":1,"maximum":4},"isCollapsible":{"type":"boolean"},"isDefaultCollapsed":{"type":"boolean"},"isActive":{"type":"boolean"}}},"FieldOptionDto":{"type":"object","properties":{"label":{"type":"string","maxLength":255},"value":{"type":"string","maxLength":255},"color":{"type":"string","maxLength":32}},"required":["label","value"]},"ValidationRulesDto":{"type":"object","properties":{"min":{"type":"object"},"max":{"type":"object"},"minLength":{"type":"number","minimum":0},"maxLength":{"type":"number","minimum":1,"maximum":65535},"pattern":{"type":"string","description":"Applies to TEXT/TEXTAREA/URL/EMAIL/PHONE only; must compile as a RegExp.","maxLength":300}}},"FieldSettingsDto":{"type":"object","properties":{"symbol":{"type":"string","maxLength":32},"scale":{"type":"number","minimum":1,"maximum":10},"color":{"type":"string","maxLength":32},"prefix":{"type":"string","maxLength":20},"digits":{"type":"number","minimum":1,"maximum":10},"startingNumber":{"type":"number","minimum":0},"decimalPlaces":{"type":"number","minimum":0,"maximum":6},"currencySymbol":{"type":"string","maxLength":8},"minValue":{"type":"string","maxLength":32},"maxValue":{"type":"string","maxLength":32},"associationType":{"type":"string","enum":["single","multiple"]},"targetModule":{"type":"string","maxLength":255},"pipelineIds":{"maxItems":50,"type":"array","items":{"type":"string","format":"uuid"}}}},"DependencyConditionDto":{"type":"object","properties":{"fieldId":{"type":"string","description":"The controlling field (SELECT / MULTI_SELECT / BOOLEAN).","format":"uuid"},"operator":{"type":"string","enum":["equals","not_equals","in","not_in","is_set","is_not_set"]},"value":{"type":"object","description":"Option value(s) / boolean — semantics validated per controlling field type."}},"required":["fieldId","operator"]},"DependencyRuleDto":{"type":"object","properties":{"logic":{"type":"string","enum":["AND","OR"]},"conditions":{"minItems":1,"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/DependencyConditionDto"}}},"required":["logic","conditions"]},"FieldDependencyRulesDto":{"type":"object","properties":{"visibleWhen":{"$ref":"#/components/schemas/DependencyRuleDto"},"requiredWhen":{"$ref":"#/components/schemas/DependencyRuleDto"}}},"CreateFieldDto":{"type":"object","properties":{"sectionId":{"type":"string","format":"uuid"},"fieldType":{"type":"string","enum":["EMAIL","TEXT","URL","PHONE","NUMBER","SELECT","BOOLEAN","TEXTAREA","CURRENCY","PERCENTAGE","DATE","DATETIME","MULTI_SELECT","LOOKUP","USER","RATING","AUTO_INCREMENT","TIMEZONE"]},"displayName":{"type":"string","minLength":1,"maxLength":255},"name":{"type":"string","description":"Immutable internal key; derived from displayName when omitted.","maxLength":255},"isRequired":{"type":"boolean"},"isUnique":{"type":"boolean"},"isFilterable":{"type":"boolean"},"isSearchable":{"type":"boolean"},"isReadOnly":{"type":"boolean"},"columnSpan":{"type":"number","minimum":1,"maximum":4},"defaultValue":{"type":"string","maxLength":2000},"placeholder":{"type":"string","maxLength":255},"helpText":{"type":"string","maxLength":500},"options":{"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/FieldOptionDto"}},"validationRules":{"$ref":"#/components/schemas/ValidationRulesDto"},"settings":{"$ref":"#/components/schemas/FieldSettingsDto"},"dependencyRules":{"$ref":"#/components/schemas/FieldDependencyRulesDto"},"relatedModuleName":{"type":"string","description":"LOOKUP/relation configuration.","maxLength":255},"relatedSystemTable":{"type":"string","maxLength":255}},"required":["sectionId","fieldType","displayName"]},"ReorderFieldsDto":{"type":"object","properties":{"sectionId":{"type":"string","format":"uuid"},"orderedIds":{"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["sectionId","orderedIds"]},"UpdateFieldDto":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":255},"isRequired":{"type":"boolean"},"isUnique":{"type":"boolean"},"isFilterable":{"type":"boolean"},"isSearchable":{"type":"boolean"},"isReadOnly":{"type":"boolean"},"isActive":{"type":"boolean"},"columnSpan":{"type":"number","minimum":1,"maximum":4},"defaultValue":{"type":"string","maxLength":2000},"placeholder":{"type":"string","maxLength":255},"helpText":{"type":"string","maxLength":500},"options":{"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/FieldOptionDto"}},"validationRules":{"$ref":"#/components/schemas/ValidationRulesDto"},"settings":{"$ref":"#/components/schemas/FieldSettingsDto"},"dependencyRules":{"$ref":"#/components/schemas/FieldDependencyRulesDto"}}},"MoveFieldDto":{"type":"object","properties":{"sectionId":{"type":"string","format":"uuid"},"position":{"type":"number","minimum":0}},"required":["sectionId","position"]},"RecordValueItemDto":{"type":"object","properties":{"fieldId":{"type":"string","format":"uuid"},"value":{"type":"object"}},"required":["fieldId"]},"CreateRecordDto":{"type":"object","properties":{"values":{"maxItems":500,"type":"array","items":{"$ref":"#/components/schemas/RecordValueItemDto"}},"ownerId":{"type":"string","format":"uuid"}},"required":["values"]},"UpdateRecordDto":{"type":"object","properties":{"values":{"maxItems":500,"type":"array","items":{"$ref":"#/components/schemas/RecordValueItemDto"}},"ownerId":{"type":"string","format":"uuid"}},"required":["values"]},"LayoutTabDto":{"type":"object","properties":{"id":{"type":"string","description":"Stable client-generated id (kept across renames).","minLength":1,"maxLength":64},"label":{"type":"string","minLength":1,"maxLength":255},"sectionIds":{"maxItems":50,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["id","label","sectionIds"]},"LayoutKanbanDto":{"type":"object","properties":{"groupFieldId":{"type":"string","description":"SELECT field whose options become the board columns.","format":"uuid"},"cardFieldIds":{"maxItems":10,"type":"array","items":{"type":"string","format":"uuid"}}}},"ModuleLayoutConfigDto":{"type":"object","properties":{"regions":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Section placement per template region (`{ main: [...], sidebar: [...] }`).\nRegion keys are validated against the template semantically."},"tabs":{"description":"Tabbed template only.","maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/LayoutTabDto"}},"headerFieldIds":{"maxItems":10,"type":"array","items":{"type":"string","format":"uuid"}},"quickViewFieldIds":{"maxItems":20,"type":"array","items":{"type":"string","format":"uuid"}},"listColumns":{"maxItems":20,"type":"array","items":{"type":"string","format":"uuid"}},"enabledViews":{"type":"array","description":"Which record views are available. Absent = legacy semantics (kanban is\navailable when a group field is configured). `list` can never be\ndisabled — enforced by ModuleLayoutValidator.","maxItems":4,"items":{"type":"string","enum":["list","kanban"]}},"defaultView":{"type":"string","enum":["list","kanban"]},"kanban":{"$ref":"#/components/schemas/LayoutKanbanDto"}}},"UpdateModuleLayoutDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"template":{"type":"string","enum":["full","two_column","three_column","tabbed"]},"config":{"description":"Replaces the whole config object (no deep merge).","allOf":[{"$ref":"#/components/schemas/ModuleLayoutConfigDto"}]}}},"SetSystemEntityValuesDto":{"type":"object","properties":{"values":{"maxItems":500,"type":"array","items":{"$ref":"#/components/schemas/RecordValueItemDto"}}},"required":["values"]},"QuickCreateOpportunityFieldDto":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":255},"fieldType":{"type":"string","enum":["EMAIL","TEXT","URL","PHONE","NUMBER","SELECT","BOOLEAN","TEXTAREA","CURRENCY","PERCENTAGE","DATE","DATETIME","MULTI_SELECT","LOOKUP","USER","RATING","AUTO_INCREMENT","TIMEZONE"]},"options":{"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/FieldOptionDto"}},"pipelineIds":{"description":"Empty/absent ⇒ available in every pipeline.","maxItems":50,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["displayName","fieldType"]},"ReorderOpportunityFieldsDto":{"type":"object","properties":{"fieldIds":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["fieldIds"]},"UpdateOpportunityFieldDto":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":255},"options":{"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/FieldOptionDto"}},"pipelineIds":{"maxItems":50,"type":"array","items":{"type":"string","format":"uuid"}}}},"CreateAuthorizationUrlDto":{"type":"object","properties":{"returnTo":{"type":"string","maxLength":300}}},"AdAccountSelectionItemDto":{"type":"object","properties":{"externalId":{"type":"string","minLength":1,"maxLength":255},"isEnabled":{"type":"boolean"}},"required":["externalId","isEnabled"]},"UpdateAdAccountSelectionDto":{"type":"object","properties":{"accounts":{"minItems":1,"maxItems":200,"type":"array","items":{"$ref":"#/components/schemas/AdAccountSelectionItemDto"}}},"required":["accounts"]},"SimulateLeadDto":{"type":"object","properties":{"connectionId":{"type":"string","format":"uuid"},"count":{"type":"number","minimum":1,"maximum":25},"formExternalId":{"type":"string","maxLength":255},"campaignExternalId":{"type":"string","description":"Accepted for shape symmetry with the ingest job payload, but currently\ninert: Meta's real webhook body has no campaign field (campaign is\nonly ever resolved via `fetchLeadDetails`, and `MockAdsProvider`'s mock\ndata hardcodes `mock-camp-1`) — see `AdsDevSimulationController` for\nthe full note.","maxLength":255}},"required":["connectionId"]},"CreateLostReasonDto":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":120}},"required":["label"]},"UpdateLostReasonDto":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":120},"position":{"type":"number","minimum":0}}},"CreatePipelineDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","description":"\"What is this pipeline for?\"","maxLength":500},"currency":{"type":"string","description":"ISO-4217, e.g. `USD`. Defaults to USD.","minLength":3,"maxLength":3,"pattern":"^[A-Z]{3}$"},"stages":{"description":"Optional OPEN stage names in order (Won/Lost are always appended).\nOmitted → the default skeleton (New Lead · Contacted · Qualified · Proposal).","maxItems":20,"type":"array","items":{"type":"string","maxLength":80,"minLength":1}}},"required":["name"]},"UpdatePipelineDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","nullable":true,"maxLength":500},"currency":{"type":"string","minLength":3,"maxLength":3,"pattern":"^[A-Z]{3}$"},"valueLabel":{"type":"string","nullable":true,"description":"Label shown for the money field (\"Deal value\"). `null` restores \"Value\".","minLength":1,"maxLength":40},"isDefault":{"type":"boolean","description":"`true` makes this the org default; `false` is ignored (there is always one default)."},"position":{"type":"number","minimum":0}}},"CreateStageDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"color":{"type":"string","nullable":true},"probability":{"type":"number","nullable":true,"description":"Default win probability (0–100) for opportunities in this stage.","minimum":0,"maximum":100}},"required":["name"]},"ReorderStagesDto":{"type":"object","properties":{"stageIds":{"description":"Every OPEN stage of the pipeline exactly once, in the new order.","uniqueItems":true,"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["stageIds"]},"UpdateStageDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"color":{"type":"string","nullable":true},"probability":{"type":"number","nullable":true,"minimum":0,"maximum":100},"isEntry":{"type":"boolean","description":"\"Set as default\" — new opportunities land here. Rejected on Won/Lost."}}},"CreateOpportunityDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"pipelineId":{"type":"string","description":"Defaults to the org's default pipeline.","format":"uuid"},"stageId":{"type":"string","description":"Must belong to the pipeline; defaults to its entry stage.","format":"uuid"},"contactId":{"type":"string","format":"uuid"},"companyName":{"type":"string","maxLength":255},"value":{"type":"number","minimum":0,"maximum":9999999999999},"currency":{"type":"string","description":"ISO-4217; defaults to the pipeline currency.","minLength":3,"maxLength":3,"pattern":"^[A-Z]{3}$"},"probability":{"type":"number","description":"Explicit win probability override (0–100).","minimum":0,"maximum":100},"expectedCloseAt":{"type":"string"},"ownerId":{"type":"string","format":"uuid"},"source":{"type":"string","maxLength":100},"priority":{"type":"string","enum":["LOW","HIGH","MEDIUM"]},"description":{"type":"string","maxLength":10000},"lostReasonId":{"type":"string","description":"Required when `stageId` is the Lost stage.","format":"uuid"},"lostReasonNote":{"type":"string","maxLength":1000},"tagIds":{"type":"array","items":{"type":"string","format":"uuid"}},"customFields":{"type":"object","additionalProperties":true,"description":"Name-keyed custom-field values written right after the row is created."}},"required":["name"]},"BulkOpportunityActionDto":{"type":"object","properties":{"ids":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}},"action":{"type":"string","enum":["assign_owner","change_stage","change_priority","add_tags"]},"ownerId":{"type":"string","nullable":true,"description":"`assign_owner`. `null` unassigns the owner.","format":"uuid"},"stageId":{"type":"string","description":"`change_stage`.","format":"uuid"},"priority":{"type":"string","description":"`change_priority`.","enum":["LOW","HIGH","MEDIUM"]},"tagIds":{"description":"`add_tags`.","minItems":1,"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}},"lostReasonId":{"type":"string","description":"`change_stage`, only meaningful when `stageId` is a Lost stage.","format":"uuid"},"lostReasonNote":{"type":"string","maxLength":1000}},"required":["ids","action"]},"BulkDeleteOpportunitiesDto":{"type":"object","properties":{"ids":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["ids"]},"UpdateOpportunityDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"pipelineId":{"type":"string","description":"Cross-pipeline move. Requires `stageId` (an OPEN stage of the target\npipeline); the opportunity re-enters as OPEN.","format":"uuid"},"stageId":{"type":"string","format":"uuid"},"contactId":{"type":"string","nullable":true,"description":"`null` unlinks the contact.","format":"uuid"},"companyName":{"type":"string","nullable":true,"maxLength":255},"value":{"type":"number","nullable":true,"description":"`null` clears the value.","minimum":0,"maximum":9999999999999},"currency":{"type":"string","minLength":3,"maxLength":3,"pattern":"^[A-Z]{3}$"},"probability":{"type":"number","nullable":true,"description":"`null` falls back to the stage probability.","minimum":0,"maximum":100},"expectedCloseAt":{"type":"string","nullable":true,"description":"`null` clears the close date."},"ownerId":{"type":"string","nullable":true,"description":"`null` unassigns the owner.","format":"uuid"},"source":{"type":"string","nullable":true,"maxLength":100},"priority":{"type":"string","enum":["LOW","HIGH","MEDIUM"]},"description":{"type":"string","nullable":true,"maxLength":10000}}},"ChangeOpportunityStageDto":{"type":"object","properties":{"stageId":{"type":"string","format":"uuid"},"expectedStageId":{"type":"string","description":"The stage the client believes the opportunity is in. When it no longer\nmatches (someone else moved the card) the move is refused with a 409\ninstead of silently double-applying.","format":"uuid"},"lostReasonId":{"type":"string","description":"Required (id or note) when `stageId` is the Lost stage.","format":"uuid"},"lostReasonNote":{"type":"string","maxLength":1000}},"required":["stageId"]},"ManageOpportunityTagsDto":{"type":"object","properties":{"tagIds":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["tagIds"]},"CreateOpportunityCommentDto":{"type":"object","properties":{"body":{"type":"string"},"bodyFormat":{"type":"string","description":"Omitted by existing clients, which keeps them on the historical\nplain-text behaviour — the column default is `PLAIN` too.","enum":["PLAIN","HTML"]}},"required":["body"]},"UpdateOpportunityCommentDto":{"type":"object","properties":{"body":{"type":"string"},"bodyFormat":{"type":"string","enum":["PLAIN","HTML"]}},"required":["body"]},"GetOpportunityAttachmentUploadUrlDto":{"type":"object","properties":{"fileName":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","minLength":1,"maxLength":255},"sizeBytes":{"type":"number","minimum":1,"maximum":26214400}},"required":["fileName","contentType","sizeBytes"]},"ConfirmOpportunityAttachmentDto":{"type":"object","properties":{"storageKey":{"type":"string","minLength":1,"maxLength":1024},"fileName":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","minLength":1,"maxLength":255},"sizeBytes":{"type":"number","minimum":1,"maximum":26214400}},"required":["storageKey","fileName","contentType","sizeBytes"]},"CreateOpportunityTaskDto":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":255},"dueAt":{"type":"string"},"assigneeId":{"type":"string","format":"uuid"}},"required":["title"]},"UpdateOpportunityTaskDto":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":255},"dueAt":{"type":"string","nullable":true,"description":"`null` clears the due date."},"assigneeId":{"type":"string","nullable":true,"description":"`null` unassigns.","format":"uuid"}}},"CreateOptInKeywordDto":{"type":"object","properties":{"keyword":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^\\s]+(?:\\s+[^\\s]+)*$"}},"required":["keyword"]},"UpdateOptInKeywordDto":{"type":"object","properties":{"keyword":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^\\s]+(?:\\s+[^\\s]+)*$"}},"required":["keyword"]},"CreateQuickMessageDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50},"slug":{"type":"string","minLength":1,"maxLength":50},"body":{"type":"string","minLength":1,"maxLength":1600},"mediaUrls":{"type":"array","items":{"type":"string"}}},"required":["name","slug","body"]},"UpdateQuickMessageDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50},"slug":{"type":"string","minLength":1,"maxLength":50},"body":{"type":"string","minLength":1,"maxLength":1600},"mediaUrls":{"type":"array","items":{"type":"string"}}}},"PresignMediaAssetDto":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","minLength":1,"maxLength":150},"sizeBytes":{"type":"number","minimum":1},"profile":{"type":"string","description":"Which rule set to validate against — the email builder's image library\n(5 MB, four image types) or MMS (600 KB, thirteen types). Omitted means\n`IMAGE_LIBRARY`, so callers written before MMS existed are unaffected.\n\nThis is the ONLY place a profile is chosen: `confirm` reads it back out\nof the storage key the presign returns, so the two can never disagree.","enum":["IMAGE_LIBRARY","MMS","WHATSAPP_HEADER","WHATSAPP_MESSAGE"]}},"required":["filename","contentType","sizeBytes"]},"PresignMediaAssetResponseDto":{"type":"object","properties":{"uploadUrl":{"type":"string"},"storageKey":{"type":"string"}},"required":["uploadUrl","storageKey"]},"ConfirmMediaAssetDto":{"type":"object","properties":{"storageKey":{"type":"string","minLength":1,"maxLength":512},"filename":{"type":"string","minLength":1,"maxLength":255},"width":{"type":"number","minimum":1},"height":{"type":"number","minimum":1}},"required":["storageKey","filename"]},"MediaAssetResponseDto":{"type":"object","properties":{"id":{"type":"string"},"kind":{"description":"What the bytes are — drives the client's thumbnail-vs-chip rendering.","enum":["IMAGE","VIDEO","DOCUMENT","VCARD","AUDIO"],"type":"string"},"publicUrl":{"type":"string","description":"Durable. Safe to persist. Not necessarily fetchable by a browser."},"displayUrl":{"type":"string","description":"Ephemeral presigned GET for `<img src>`. NEVER persist this."},"embedUrl":{"type":"string","description":"Durable AND fetchable. Use for anything frozen into sent content."},"filename":{"type":"string"},"width":{"type":"number","nullable":true},"height":{"type":"number","nullable":true},"sizeBytes":{"type":"number"},"contentType":{"type":"string"},"createdAt":{"format":"date-time","type":"string"}},"required":["id","kind","publicUrl","displayUrl","embedUrl","filename","width","height","sizeBytes","contentType","createdAt"]},"ValidateCredentialsDto":{"type":"object","properties":{"provider":{"type":"string","enum":["WEBCHAT","TWILIO","TELNYX","SENDGRID","META","RESEND","AWS_SES","GOOGLE_RCS"]},"credentials":{"type":"object"}},"required":["provider","credentials"]},"AddIdentityMemberDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"expiresAt":{"type":"string","description":"Optional expiry (ISO 8601). Omit for a grant that does not expire."}},"required":["userId"]},"SelectResourcesDto":{"type":"object","properties":{"selectedServiceSids":{"minItems":1,"type":"array","items":{"type":"string"}}},"required":["selectedServiceSids"]},"AssignNumberLiveDto":{"type":"object","properties":{"serviceSid":{"type":"string"},"currentServiceSid":{"type":"string","description":"The number's current messaging service SID, if any. When provided,\nthe provider can detach from the old service before attaching to\nthe new one — Twilio rejects re-attach without an explicit detach\n(error 21712). Omit for unassigned numbers."}},"required":["serviceSid"]},"RegisterBrandDto":{"type":"object","properties":{"businessName":{"type":"string","minLength":2,"maxLength":200},"businessType":{"type":"string","enum":["PRIVATE_COMPANY","PUBLIC_COMPANY","NON_PROFIT","GOVERNMENT","SOLE_PROPRIETOR"]},"businessIndustry":{"type":"string","maxLength":50},"companyType":{"type":"string","enum":["PRIVATE","PUBLIC","NON_PROFIT","GOVERNMENT"]},"brandType":{"type":"string","default":"STANDARD","maxLength":50},"ein":{"type":"string","minLength":2,"maxLength":50},"socialMediaUrls":{"type":"string","maxLength":500},"stockExchange":{"type":"string","maxLength":50},"stockTicker":{"type":"string","maxLength":50},"street":{"type":"string","maxLength":255},"city":{"type":"string","maxLength":100},"state":{"type":"string","maxLength":100},"postalCode":{"type":"string","maxLength":20},"country":{"type":"string"},"email":{"type":"string","format":"email"},"website":{"type":"string","format":"uri"},"phoneNumber":{"type":"string"},"repFirstName":{"type":"string","maxLength":100},"repLastName":{"type":"string","maxLength":100},"repEmail":{"type":"string","format":"email"},"repPhone":{"type":"string"},"repJobTitle":{"type":"string","maxLength":100},"repJobPosition":{"type":"string","maxLength":100},"friendlyName":{"type":"string","maxLength":100}},"required":["businessName","businessType","businessIndustry","companyType","ein","street","city","state","postalCode","country","email","website","phoneNumber","repFirstName","repLastName","repEmail","repPhone","repJobTitle","repJobPosition"]},"CreateCampaignDto":{"type":"object","properties":{"asDraft":{"type":"boolean","description":"Save without sending — the campaign lands in DRAFT.\n\nEvery `@ValidateIf` below that enforces COMPLETENESS is additionally gated\non this being false, because a draft is half-built by definition: no body\nyet, no sender picked, no send time chosen. Checks that judge a value the\ncaller DID supply (length caps, UUID shape, enum membership) stay on for\ndrafts — saving early should not mean saving garbage.\n\nNothing here is relaxed for a real send: when `asDraft` is absent or false\nevery validator behaves exactly as it did before drafts existed, and the\nsend gate in `CampaignsService.validateCreateInputs` re-checks all of it\nserver-side anyway when the draft is later sent."},"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"type":{"type":"string","enum":["SCHEDULED","IMMEDIATE","RECURRING"]},"channel":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"messageTemplate":{"type":"string","minLength":1},"subject":{"type":"string","minLength":1,"maxLength":500},"previewText":{"type":"string","maxLength":255},"designJson":{"type":"object"},"emailTemplateId":{"type":"string","format":"uuid"},"whatsappTemplateId":{"type":"string","format":"uuid"},"whatsappVariantBody":{"type":"string","minLength":1},"whatsappVariableMap":{"type":"array","items":{"type":"string","enum":["","first_name","last_name","full_name","phone","email","street_address","address_line_2","city","state","postal_code","country","full_address","organization_name","organization_phone","organization_email","organization_website"]}},"mediaUrls":{"type":"array","items":{"type":"string"}},"segmentIds":{"type":"array","items":{"type":"string","format":"uuid"}},"contactIds":{"description":"Hand-picked recipients — the alternative to `segmentIds`, never both.","type":"array","items":{"type":"string","format":"uuid"}},"channelIdentityIds":{"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}},"scheduledAt":{"type":"string"},"scheduledTimezone":{"type":"string","minLength":1,"maxLength":64},"quietHoursMode":{"type":"string","enum":["OFF","CUSTOM","INHERIT"]},"quietHoursStart":{"type":"string"},"quietHoursEnd":{"type":"string"},"quietHoursTimezone":{"type":"string","minLength":1,"maxLength":64},"recurrenceRule":{"type":"string","minLength":1,"maxLength":500},"recurrenceTimezone":{"type":"string","minLength":1,"maxLength":64},"recurrenceStartsAt":{"type":"string"},"recurrenceEndsAt":{"type":"string"},"maxRuns":{"type":"number","minimum":1,"maximum":10000},"catchUpPolicy":{"type":"string","enum":["LATEST_ONLY","FIRE_ALL","SKIP_ALL"]},"overlapPolicy":{"type":"string","enum":["SKIP","ALLOW"]},"allowOpenEnded":{"type":"boolean"},"trackedLinks":{"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/TrackedLinkDto"}},"contactActions":{"type":"array","items":{"$ref":"#/components/schemas/CampaignContactActionDto"}},"experiment":{"$ref":"#/components/schemas/CreateCampaignExperimentDto"}},"required":["name","type","channel","segmentIds","channelIdentityIds"]},"CreateMessagingServiceDto":{"type":"object","properties":{"serviceName":{"type":"string","minLength":1,"maxLength":255}},"required":["serviceName"]},"UpdateMessagingServiceAssignmentDto":{"type":"object","properties":{"phoneNumber":{"type":"string"},"phoneNumberSid":{"type":"string"},"serviceSid":{"type":"string"}},"required":["phoneNumber","phoneNumberSid","serviceSid"]},"PurchasePhoneNumberDto":{"type":"object","properties":{"phoneNumber":{"type":"string"},"friendlyName":{"type":"string","maxLength":100}},"required":["phoneNumber"]},"CreateJoinKeywordDto":{"type":"object","properties":{"keyword":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9]+$"},"channelIdentityId":{"type":"string","format":"uuid"},"segmentId":{"type":"string","format":"uuid"},"welcomeMessage":{"type":"string","minLength":1,"maxLength":1600},"sequenceId":{"type":"string","format":"uuid"}},"required":["keyword","channelIdentityId"]},"UpdateJoinKeywordDto":{"type":"object","properties":{"segmentId":{"type":"string","nullable":true,"format":"uuid"},"welcomeMessage":{"type":"string","nullable":true,"minLength":1,"maxLength":1600},"sequenceId":{"type":"string","nullable":true,"format":"uuid"}}},"QrCenterLogoDto":{"type":"object","properties":{"url":{"type":"string","maxLength":2000},"size":{"type":"number","minimum":20,"maximum":60}},"required":["url","size"]},"QrCodeStyleDto":{"type":"object","properties":{"fgColor":{"type":"string"},"bgColor":{"type":"string"},"dotShape":{"type":"string","enum":["square","rounded","dots","smooth","classy","classyRounded"]},"cornerStyle":{"type":"string","enum":["square","rounded","extraRounded"]},"centerLogo":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/QrCenterLogoDto"}]}},"required":["fgColor","bgColor","dotShape","cornerStyle","centerLogo"]},"QrPlainDto":{"type":"object","properties":{"bottomText":{"type":"string","maxLength":160}},"required":["bottomText"]},"QrCardLogoDto":{"type":"object","properties":{"url":{"type":"string","maxLength":2000},"size":{"type":"number","minimum":20,"maximum":200}},"required":["url","size"]},"QrCardFaceDto":{"type":"object","properties":{"logo":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/QrCardLogoDto"}]},"title":{"type":"string","maxLength":80},"description":{"type":"string","maxLength":160},"bottomText":{"type":"string","maxLength":160}},"required":["logo","title","description","bottomText"]},"QrTentDto":{"type":"object","properties":{"front":{"$ref":"#/components/schemas/QrCardFaceDto"},"back":{"$ref":"#/components/schemas/QrCardFaceDto"}},"required":["front","back"]},"QrPosterDto":{"type":"object","properties":{"logo":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/QrCardLogoDto"}]},"title":{"type":"string","maxLength":80},"tagline":{"type":"string","maxLength":160},"bottomText":{"type":"string","maxLength":160}},"required":["logo","title","tagline","bottomText"]},"QrDesignDto":{"type":"object","properties":{"version":{"enum":[1],"type":"number"},"type":{"enum":["plain","standalone","tent","poster"],"type":"string"},"style":{"$ref":"#/components/schemas/QrCodeStyleDto"},"plain":{"$ref":"#/components/schemas/QrPlainDto"},"standalone":{"$ref":"#/components/schemas/QrCardFaceDto"},"tent":{"$ref":"#/components/schemas/QrTentDto"},"poster":{"$ref":"#/components/schemas/QrPosterDto"}},"required":["version","type","style","plain","standalone","tent","poster"]},"DuplicateJoinKeywordDto":{"type":"object","properties":{"keyword":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9]+$"}},"required":["keyword"]},"PreviewRulesDto":{"type":"object","properties":{"rules":{"type":"object","additionalProperties":true},"page":{"type":"number","default":1,"minimum":1},"limit":{"type":"number","default":10,"minimum":1,"maximum":100},"countOnly":{"type":"boolean","default":false}},"required":["rules"]},"SegmentContactTagSummaryDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"object"}},"required":["id","name"]},"SegmentContactTagLinkDto":{"type":"object","properties":{"tag":{"$ref":"#/components/schemas/SegmentContactTagSummaryDto"}},"required":["tag"]},"SegmentContactTagCountDto":{"type":"object","properties":{"tags":{"type":"number"}},"required":["tags"]},"SegmentContactResponseDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","nullable":true},"status":{"enum":["ACTIVE","INVALID","ARCHIVED"],"type":"string"},"source":{"enum":["TEXT_LINK","JOIN_KEYWORD","CSV_IMPORT","MANUAL","WEB_FORM","INBOUND_SMS","INBOUND_CALL","GOOGLE_ADS","META_ADS","INBOUND_EMAIL","INBOUND_WHATSAPP","LEAD_FORM","WEB_CHAT"],"type":"string"},"isOptedOut":{"type":"boolean"},"optedOutAt":{"format":"date-time","type":"string","nullable":true},"optedInAt":{"format":"date-time","type":"string","nullable":true},"importId":{"type":"string","nullable":true},"streetAddress":{"type":"string","nullable":true},"addressLine2":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"state":{"type":"string","nullable":true},"postalCode":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"avatarBgColor":{"type":"string","nullable":true},"customFields":{"type":"object","additionalProperties":true},"lastContactedAt":{"format":"date-time","type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/SegmentContactTagLinkDto"}},"_count":{"$ref":"#/components/schemas/SegmentContactTagCountDto"},"emailSubscription":{"type":"object","properties":{"isSubscribed":{"type":"boolean"},"reason":{"type":"string"},"since":{"format":"date-time","type":"string"}},"required":["isSubscribed"]}},"required":["id","organizationId","firstName","lastName","phone","email","status","source","isOptedOut","optedOutAt","optedInAt","importId","streetAddress","addressLine2","city","state","postalCode","country","avatarBgColor","customFields","lastContactedAt","createdAt","updatedAt"]},"SegmentRulesPreviewResponseDto":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/SegmentContactResponseDto"}}},"required":["total","data"]},"SegmentResponseDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"type":{"enum":["STATIC","DYNAMIC"],"type":"string"},"rules":{"type":"object","additionalProperties":true,"nullable":true},"computeStatus":{"enum":["QUEUED","FAILED","IDLE","COMPUTING"],"type":"string"},"contactCount":{"type":"number"},"lastComputedAt":{"format":"date-time","type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","organizationId","name","description","type","rules","computeStatus","contactCount","lastComputedAt","createdAt","updatedAt"]},"SegmentReplyRateDto":{"type":"object","properties":{"rate":{"type":"number","nullable":true,"description":"Percentage 0–100, 2dp. Null when `recipients` is 0 (no send to divide by)."},"repliedContacts":{"type":"number","description":"Contacts that replied after their first campaign message."},"recipients":{"type":"number","description":"Distinct contacts that received at least one campaign message."},"totalSent":{"type":"number","description":"Messages sent — context only; deliberately NOT the rate's denominator."},"campaignsSampled":{"type":"number","description":"Campaigns sampled, capped by SEGMENT_REPLY_SAMPLE_CAMPAIGNS."}},"required":["rate","repliedContacts","recipients","totalSent","campaignsSampled"]},"SegmentGrowthDto":{"type":"object","properties":{"net":{"type":"number","description":"Adds minus removes. Negative when the segment shrank."},"added":{"type":"number"},"removed":{"type":"number"},"pct":{"type":"number","nullable":true,"description":"Percent change against the window's opening count. Null when that was 0."},"windowDays":{"type":"number"}},"required":["net","added","removed","pct","windowDays"]},"SegmentGrowthPointDto":{"type":"object","properties":{"day":{"type":"string","description":"`YYYY-MM-DD`, UTC."},"count":{"type":"number","description":"Reconstructed membership at the end of this day."},"added":{"type":"number"},"removed":{"type":"number"},"estimated":{"type":"boolean","description":"True when this point predates the complete-ledger epoch (flattened floor)."}},"required":["day","count","added","removed","estimated"]},"SegmentGrowthSeriesDto":{"type":"object","properties":{"points":{"type":"array","items":{"$ref":"#/components/schemas/SegmentGrowthPointDto"}},"reliableFrom":{"type":"string","nullable":true,"description":"ISO instant from which the series is trustworthy; null = whole window is."},"windowDays":{"type":"number"}},"required":["points","reliableFrom","windowDays"]},"SegmentStatsResponseDto":{"type":"object","properties":{"segmentId":{"type":"string"},"contactCount":{"type":"number","description":"Echo of the anchor the series was reconstructed from."},"campaignsUsed":{"type":"number","description":"Live campaigns targeting this segment. Zero, never null."},"replyRate":{"$ref":"#/components/schemas/SegmentReplyRateDto"},"growth7d":{"$ref":"#/components/schemas/SegmentGrowthDto"},"growthSeries":{"$ref":"#/components/schemas/SegmentGrowthSeriesDto"},"generatedAt":{"type":"string","description":"ISO instant the payload was computed — lets the UI show cache age."}},"required":["segmentId","contactCount","campaignsUsed","replyRate","growth7d","growthSeries","generatedAt"]},"UpdateSegmentDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"rules":{"type":"object","additionalProperties":true}}},"CloneSegmentDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255}}},"EstimateAudienceDto":{"type":"object","properties":{"segmentIds":{"maxItems":20,"type":"array","items":{"type":"string"}},"tagIds":{"maxItems":20,"type":"array","items":{"type":"string"}},"stages":{"maxItems":10,"type":"array","items":{"type":"string"}},"sources":{"maxItems":10,"type":"array","items":{"type":"string"}}}},"ContactQueryDto":{"type":"object","properties":{"search":{"type":"string","maxLength":200},"name":{"type":"string","maxLength":200},"phone":{"type":"string","maxLength":50},"email":{"type":"string","maxLength":200},"status":{"type":"array","items":{"type":"string","enum":["ACTIVE","INVALID","ARCHIVED"]}},"source":{"type":"array","items":{"type":"string","enum":["TEXT_LINK","JOIN_KEYWORD","CSV_IMPORT","MANUAL","WEB_FORM","INBOUND_SMS","INBOUND_CALL","GOOGLE_ADS","META_ADS","INBOUND_EMAIL","INBOUND_WHATSAPP","LEAD_FORM","WEB_CHAT"]}},"stage":{"type":"array","items":{"type":"string","enum":["ARCHIVED","NEW_LEAD","ENGAGED","QUALIFIED","APPOINTMENT_BOOKED","CUSTOMER","LOST","BOOKING_PENDING","ESTIMATE_GIVEN","DECIDING","NOT_QUALIFIED"]}},"leadScore":{"type":"array","description":"Hot / Warm / Cold — e.g. `?leadScore=HOT` for the \"Hot leads\" filter.","items":{"type":"string","enum":["HOT","WARM","COLD"]}},"isOptedOut":{"type":"boolean"},"emailSubscribed":{"type":"boolean","description":"EMAIL subscription state — deliberately SEPARATE from `isOptedOut`, which\nis the SMS opt-out flag. A contact can be reachable by SMS and\nunsubscribed from email, or the reverse; collapsing them would silently\nfilter out contacts the user still wants.\n\n`true` = still emailable, `false` = on the org's suppression list."},"optedOutChannel":{"description":"Opted out: `ALL_CHANNELS` (= `isOptedOut`, the global opt-out), `WHATSAPP`\n(`whatsappOptIn === false`, set by a WhatsApp STOP) or `ANY`.","enum":["ANY","ALL_CHANNELS","WHATSAPP"],"type":"string"},"tagIds":{"type":"array","items":{"type":"string","format":"uuid"}},"sample":{"type":"boolean","description":"`sample=1` (or `true`) → only sample-data contacts."},"createdFrom":{"type":"string"},"createdTo":{"type":"string"},"excludeSegmentId":{"type":"string","description":"Hide contacts that are already members of this segment. Used by the\nsegment \"Add Contacts\" picker so an existing member can't be selected\nand re-added (the insert is idempotent, but offering it reads as a bug).","format":"uuid"},"sortBy":{"type":"string","enum":["createdAt","firstName","lastName","phone","email","status","leadScore"]},"sortOrder":{"enum":["asc","desc"],"type":"string"},"customFieldFilters":{"description":"Custom-field filters (module-builder bridge), passed as a JSON-encoded\narray keyed by field name, e.g.\n`?customFieldFilters=[{\"field\":\"company\",\"operator\":\"contains\",\"value\":\"acme\"}]`.\nUnknown fields/operators are ignored by the resolver.","type":"array","items":{"type":"object"}},"page":{"type":"number","default":1,"minimum":1},"limit":{"type":"number","default":20,"minimum":1,"maximum":100}},"required":["page","limit"]},"BulkEnrollmentDto":{"type":"object","properties":{"sequenceIds":{"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}},"ids":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"$ref":"#/components/schemas/ContactQueryDto"},"confirmTriggers":{"type":"boolean","description":"Above the sync limit, a bulk action that would start published workflows (tag\nadded/removed) is refused until the user confirms it. Ignored on the sync path."}},"required":["sequenceIds"]},"CreateSequenceDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":500},"templateId":{"type":"string","description":"System gallery key or org template id.","maxLength":80},"ensureUniqueName":{"type":"boolean","description":"`name` is only a suggestion — the template's own name, not one the owner typed. A\ntaken name then becomes the first free \"name (2)\", \"name (3)\"… instead of failing,\nso the same template can be used again and again. A typed name is never renamed."},"channels":{"type":"array","description":"Channels for a blank sequence (ignored when templateId is set).","maxItems":2,"items":{"type":"string","enum":["EMAIL","SMS"]}}},"required":["name"]},"UpdateSequenceDto":{"type":"object","properties":{"expectedVersion":{"type":"number","description":"Optimistic-concurrency guard (autosave).","minimum":0},"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":500},"definition":{"type":"object","additionalProperties":true,"description":"Linear sequence document — deep-validated by the zod domain schema."}},"required":["expectedVersion"]},"PublishSequenceDto":{"type":"object","properties":{"enrollExisting":{"type":"boolean","description":"Enroll contacts who already match the audience today (default true)."}}},"SequenceTestSendDto":{"type":"object","properties":{"toPhone":{"type":"string","description":"SMS steps only — the phone number the test goes to.","maxLength":20}}},"CreateEmailDomainDto":{"type":"object","properties":{"domain":{"type":"string","maxLength":255,"pattern":"^(?!-)[a-z0-9-]{1,63}(?<!-)(\\.(?!-)[a-z0-9-]{1,63}(?<!-))+$"}},"required":["domain"]},"EnableInboundDto":{"type":"object","properties":{"hostname":{"type":"string","description":"Hostname whose MX will point at the provider. Defaults to the domain\nitself. Use a subdomain when the root already receives mail elsewhere —\nMX can only name one provider, so a domain on Google Workspace must not\nrepoint its root. The service additionally rejects any hostname outside\nthe domain's own tree.","maxLength":255,"pattern":"^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))+$","example":"reply.acme.com"}}},"CreateEmailSenderDto":{"type":"object","properties":{"emailDomainId":{"type":"string","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":150},"email":{"type":"string","maxLength":255,"format":"email"},"replyTo":{"type":"string","maxLength":255,"format":"email"},"isDefault":{"type":"boolean"}},"required":["emailDomainId","name","email"]},"UpdateEmailSenderDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":150},"replyTo":{"type":"string","maxLength":255,"format":"email"},"isDefault":{"type":"boolean"}}},"TestSendDto":{"type":"object","properties":{"senderId":{"type":"string","format":"uuid"},"subject":{"type":"string","minLength":1,"maxLength":500},"html":{"type":"string","minLength":1,"maxLength":500000},"previewText":{"type":"string","maxLength":255},"toEmails":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","format":"email"}}},"required":["senderId","subject","html","toEmails"]},"EmailSuppressionWriteDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"contactId":{"type":"string","description":"Optional — supplied when the change was made from a contact's screen.","format":"uuid"}},"required":["email"]},"UpdateEmailSubscriptionDto":{"type":"object","properties":{"subscribed":{"type":"boolean","description":"`true` subscribes the contact's email address, `false` unsubscribes it."}},"required":["subscribed"]},"CreateWorkflowDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":500}},"required":["name"]},"PresignEmailAttachmentDto":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","minLength":1,"maxLength":150},"sizeBytes":{"type":"number","minimum":1}},"required":["filename","contentType","sizeBytes"]},"UpdateWorkflowDraftDto":{"type":"object","properties":{"expectedVersion":{"type":"number","description":"Optimistic-concurrency token — the workflow row's current `version`.","minimum":0},"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":500},"draftDefinition":{"type":"object","additionalProperties":true,"description":"Full graph JSON — structurally validated by the zod schema in the service."},"reEntryMode":{"type":"string","enum":["ONCE_EVER","ONCE_ACTIVE","ALWAYS"]},"reEntryCooldownDays":{"type":"number","description":"ALWAYS mode only: minimum days between re-enrollments (1–365).","minimum":1,"maximum":365},"timezone":{"type":"string","maxLength":64}},"required":["expectedVersion"]},"ExecuteWorkflowDto":{"type":"object","properties":{"contactIds":{"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["contactIds"]},"UseTemplateDto":{"type":"object","properties":{}},"SaveTemplateDto":{"type":"object","properties":{}},"StartTestRunDto":{"type":"object","properties":{}},"SimulateEventDto":{"type":"object","properties":{}},"CreatePollOptionInputDto":{"type":"object","properties":{"position":{"type":"number","minimum":1,"maximum":10},"value":{"type":"string","minLength":1,"maxLength":60},"description":{"type":"string","maxLength":255},"matchPhrases":{"description":"Alternate wordings a reply may use for this option (\"count me in\").\nMatch-only — the outbound SMS always shows `value`. The value itself is\nstored as an implicit phrase, so omitting this changes nothing.","type":"array","items":{"type":"string","maxLength":120,"minLength":1}},"autoTagRules":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["position","value"]},"CreatePollDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"questionTemplate":{"type":"string","minLength":1,"maxLength":1024},"mediaUrls":{"type":"array","items":{"type":"string"}},"allowMultipleOptions":{"type":"boolean"},"segmentId":{"type":"string","format":"uuid"},"channelIdentityIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","format":"uuid"}},"options":{"minItems":2,"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/CreatePollOptionInputDto"}},"dispatchType":{"type":"string","enum":["SCHEDULED","IMMEDIATE"]},"scheduledAt":{"type":"string"},"scheduleTimezone":{"type":"string","minLength":1,"maxLength":64},"expiresAt":{"type":"string"}},"required":["name","questionTemplate","segmentId","channelIdentityIds","options","dispatchType"]},"PollCreateResponseDto":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["ACTIVE","CLOSED","SCHEDULED","CANCELLED","BROADCASTING","EXPIRED"]}},"required":["id","status"]},"PollSegmentSummaryDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"PollCountersDto":{"type":"object","properties":{"totalRecipients":{"type":"number"},"queuedCount":{"type":"number"},"sentCount":{"type":"number"},"deliveredCount":{"type":"number"},"failedCount":{"type":"number"},"cancelledCount":{"type":"number"},"totalVotes":{"type":"number"},"uniqueVoters":{"type":"number"}},"required":["totalRecipients","queuedCount","sentCount","deliveredCount","failedCount","cancelledCount","totalVotes","uniqueVoters"]},"PollListItemDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"status":{"type":"string","enum":["ACTIVE","CLOSED","SCHEDULED","CANCELLED","BROADCASTING","EXPIRED"]},"dispatchType":{"type":"string","enum":["SCHEDULED","IMMEDIATE"]},"allowMultipleOptions":{"type":"boolean"},"segmentId":{"type":"string"},"segment":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/PollSegmentSummaryDto"}]},"scheduledAt":{"type":"string","nullable":true},"expiresAt":{"type":"string","nullable":true},"startedAt":{"type":"string","nullable":true},"activatedAt":{"type":"string","nullable":true},"closedAt":{"type":"string","nullable":true},"cancelledAt":{"type":"string","nullable":true},"counters":{"$ref":"#/components/schemas/PollCountersDto"},"createdBy":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","status","dispatchType","allowMultipleOptions","segmentId","segment","scheduledAt","expiresAt","startedAt","activatedAt","closedAt","cancelledAt","counters","createdBy","createdAt","updatedAt"]},"PollOptionDetailDto":{"type":"object","properties":{"id":{"type":"string"},"position":{"type":"number"},"value":{"type":"string"},"description":{"type":"string","nullable":true},"voteCount":{"type":"number"},"autoTagRules":{"type":"array","items":{"type":"string"}}},"required":["id","position","value","description","voteCount","autoTagRules"]},"PollDetailDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"questionTemplate":{"type":"string"},"mediaUrls":{"type":"array","items":{"type":"string"}},"mediaAttachments":{"description":"What each `mediaUrls` entry is, for the attachments we host.","type":"array","items":{"type":"object"}},"status":{"type":"string","enum":["ACTIVE","CLOSED","SCHEDULED","CANCELLED","BROADCASTING","EXPIRED"]},"dispatchType":{"type":"string","enum":["SCHEDULED","IMMEDIATE"]},"allowMultipleOptions":{"type":"boolean"},"segmentId":{"type":"string"},"segment":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/PollSegmentSummaryDto"}]},"scheduledAt":{"type":"string","nullable":true},"scheduleTimezone":{"type":"string","nullable":true},"expiresAt":{"type":"string","nullable":true},"startedAt":{"type":"string","nullable":true},"activatedAt":{"type":"string","nullable":true},"closedAt":{"type":"string","nullable":true},"cancelledAt":{"type":"string","nullable":true},"autoPausedAt":{"type":"string","nullable":true},"autoPauseReason":{"type":"string","nullable":true},"failureReason":{"type":"string","nullable":true},"counters":{"$ref":"#/components/schemas/PollCountersDto"},"options":{"type":"array","items":{"$ref":"#/components/schemas/PollOptionDetailDto"}},"channelIdentityIds":{"type":"array","items":{"type":"string"}},"createdBy":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","questionTemplate","mediaUrls","mediaAttachments","status","dispatchType","allowMultipleOptions","segmentId","segment","scheduledAt","scheduleTimezone","expiresAt","startedAt","activatedAt","closedAt","cancelledAt","autoPausedAt","autoPauseReason","failureReason","counters","options","channelIdentityIds","createdBy","createdAt","updatedAt"]},"PollMessageContactDto":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","firstName","lastName"]},"PollMessageDto":{"type":"object","properties":{"id":{"type":"string"},"pollId":{"type":"string"},"contactId":{"type":"string"},"fromIdentityId":{"type":"string"},"fromNumber":{"type":"string"},"toNumber":{"type":"string"},"body":{"type":"string"},"status":{"type":"string","enum":["QUEUED","SENT","DELIVERED","UNDELIVERED","FAILED","REJECTED","CANCELLED","PROCESSING"]},"providerMessageId":{"type":"string","nullable":true},"providerName":{"type":"string","nullable":true},"retryCount":{"type":"number"},"errorCode":{"type":"string","nullable":true},"errorMessage":{"type":"string","nullable":true},"sentAt":{"format":"date-time","type":"string","nullable":true},"deliveredAt":{"format":"date-time","type":"string","nullable":true},"failedAt":{"format":"date-time","type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"contact":{"$ref":"#/components/schemas/PollMessageContactDto"}},"required":["id","pollId","contactId","fromIdentityId","fromNumber","toNumber","body","status","providerMessageId","providerName","retryCount","errorCode","errorMessage","sentAt","deliveredAt","failedAt","createdAt","contact"]},"PollPerOptionAnalyticsDto":{"type":"object","properties":{"id":{"type":"string"},"position":{"type":"number"},"value":{"type":"string"},"voteCount":{"type":"number"},"sharePct":{"type":"number"}},"required":["id","position","value","voteCount","sharePct"]},"PollResponseRatePointDto":{"type":"object","properties":{"bucket":{"type":"string"},"cumulativeVoters":{"type":"number"},"cumulativeDelivered":{"type":"number"}},"required":["bucket","cumulativeVoters","cumulativeDelivered"]},"PollAnalyticsDto":{"type":"object","properties":{"pollId":{"type":"string"},"status":{"type":"string","enum":["ACTIVE","CLOSED","SCHEDULED","CANCELLED","BROADCASTING","EXPIRED"]},"counters":{"$ref":"#/components/schemas/PollCountersDto"},"options":{"type":"array","items":{"$ref":"#/components/schemas/PollPerOptionAnalyticsDto"}},"responseRate":{"type":"number"},"responseRateSeries":{"type":"array","items":{"$ref":"#/components/schemas/PollResponseRatePointDto"}}},"required":["pollId","status","counters","options","responseRate","responseRateSeries"]},"CreateSegmentFromPollDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"selector":{"type":"string","enum":["voted_options","voted_any","did_not_vote"]},"optionIds":{"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["name","selector"]},"PollSegmentResultDto":{"type":"object","properties":{"segmentId":{"type":"string"},"contactCount":{"type":"number"}},"required":["segmentId","contactCount"]},"PollVoteContactDto":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"phone":{"type":"string"},"isOptedOut":{"type":"boolean"},"whatsappOptIn":{"type":"boolean","nullable":true}},"required":["id","firstName","lastName","phone","isOptedOut","whatsappOptIn"]},"PollVoteOptionDto":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"string"},"position":{"type":"number"}},"required":["id","value","position"]},"PollVoteDto":{"type":"object","properties":{"id":{"type":"string"},"pollId":{"type":"string"},"optionId":{"type":"string"},"contactId":{"type":"string"},"providerMessageId":{"type":"string","nullable":true},"receivedAt":{"format":"date-time","type":"string"},"contact":{"$ref":"#/components/schemas/PollVoteContactDto"},"option":{"$ref":"#/components/schemas/PollVoteOptionDto"}},"required":["id","pollId","optionId","contactId","providerMessageId","receivedAt","contact","option"]},"PollVoteRecordDto":{"type":"object","properties":{"contactId":{"type":"string","format":"uuid"},"optionIds":{"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["contactId","optionIds"]},"TrackedLinkDto":{"type":"object","properties":{"url":{"type":"string","maxLength":2048},"enabled":{"type":"boolean"}},"required":["url","enabled"]},"CampaignContactActionDto":{"type":"object","properties":{"type":{"type":"string","enum":["ADD_TAGS","REMOVE_TAGS","ADD_TO_SEGMENT","ASSIGN_TO_TEAMMATE"]},"tagIds":{"uniqueItems":true,"type":"array","items":{"type":"string","format":"uuid"}},"segmentId":{"type":"string","nullable":true,"format":"uuid"},"userId":{"type":"string","nullable":true,"format":"uuid"}},"required":["type"]},"CreateCampaignExperimentDto":{"type":"object","properties":{"testDimension":{"type":"string","enum":["SUBJECT_LINE","MESSAGE_CONTENT"]},"percentA":{"type":"number","minimum":1,"maximum":98},"percentB":{"type":"number","minimum":1,"maximum":98},"holdoutPercent":{"type":"number","minimum":0,"maximum":98},"winnerCriterion":{"type":"string","enum":["MANUAL","OPEN_RATE","CLICK_RATE"]},"decisionDelayMinutes":{"type":"number","enum":[30,60,180,360,1440]},"requireApproval":{"type":"boolean"},"variantSubject":{"type":"string","maxLength":500},"variantPreviewText":{"type":"string","maxLength":255},"variantMessageTemplate":{"type":"string","maxLength":500000}},"required":["testDimension","percentA","percentB","holdoutPercent","winnerCriterion","decisionDelayMinutes","requireApproval"]},"CampaignCreateResponseDto":{"type":"object","properties":{"id":{"type":"string"},"executionIds":{"type":"array","items":{"type":"string"}}},"required":["id","executionIds"]},"CampaignSegmentRefDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","description":"Lets the UI gate STATIC-only actions (remove-from-segment) without a second round-trip.","enum":["STATIC","DYNAMIC"]}},"required":["id","name","type"]},"CampaignCountersDto":{"type":"object","properties":{"totalRecipients":{"type":"number"},"sentCount":{"type":"number"},"deliveredCount":{"type":"number"},"failedCount":{"type":"number"},"cancelledCount":{"type":"number"},"suppressedCount":{"type":"number","description":"EMAIL only, and a SUBSET of `failedCount`: rows never sent because the\n address is unsubscribed. Lets the summary say how much of \"Failed\" is\n really \"the contact asked not to be emailed\"."},"queuedCount":{"type":"number","description":"Rows still awaiting dispatch. Counted from `outbound_messages`, NOT derived —\n `sentCount` and `failedCount` overlap, so subtracting them understates it."},"totalCost":{"type":"number"},"repliedCount":{"type":"number","description":"Distinct recipients who replied. Channel-agnostic — SMS and EMAIL both\ncount here, unlike the email-only engagement counters below."},"rejectedCount":{"type":"number","description":"Recipients skipped on purpose at dispatch — consent withdrawn, contact\ngone, or a closed WhatsApp window on a skip-configured step. Not a\ndelivery failure (spec §2), so it is excluded from `failedCount`."},"openedCount":{"type":"number","description":"EMAIL only."},"clickedCount":{"type":"number"},"uniqueOpenedCount":{"type":"number"},"uniqueClickedCount":{"type":"number"},"bouncedCount":{"type":"number"},"unsubscribedCount":{"type":"number"},"spamReportCount":{"type":"number"}},"required":["totalRecipients","sentCount","deliveredCount","failedCount","cancelledCount","suppressedCount","queuedCount","totalCost","repliedCount","rejectedCount","openedCount","clickedCount","uniqueOpenedCount","uniqueClickedCount","bouncedCount","unsubscribedCount","spamReportCount"]},"CampaignListItemDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"type":{"type":"string","enum":["SCHEDULED","IMMEDIATE","RECURRING"]},"status":{"type":"string","enum":["ACTIVE","FAILED","SCHEDULED","CANCELLED","COMPLETED","DRAFT","PAUSED"]},"channel":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"scheduledAt":{"format":"date-time","type":"string","nullable":true},"startedAt":{"format":"date-time","type":"string","nullable":true},"completedAt":{"format":"date-time","type":"string","nullable":true},"pausedAt":{"format":"date-time","type":"string","nullable":true},"nextRunAt":{"format":"date-time","type":"string","nullable":true},"endRequestedAt":{"format":"date-time","type":"string","nullable":true},"runsCompleted":{"type":"number"},"maxRuns":{"type":"number","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"directContactCount":{"type":"number","description":"Every targeted segment, in pick order."},"segments":{"type":"array","items":{"$ref":"#/components/schemas/CampaignSegmentRefDto"}},"counters":{"$ref":"#/components/schemas/CampaignCountersDto"}},"required":["id","organizationId","name","description","type","status","channel","scheduledAt","startedAt","completedAt","pausedAt","nextRunAt","endRequestedAt","runsCompleted","maxRuns","createdAt","updatedAt","directContactCount","segments","counters"]},"CampaignAnalyticsSummaryDto":{"type":"object","properties":{"totalCampaigns":{"type":"number"},"messagesSentLast30d":{"type":"number"},"avgDeliveryRate":{"type":"number","nullable":true},"statusCounts":{"type":"object","additionalProperties":{"type":"number"}}},"required":["totalCampaigns","messagesSentLast30d","avgDeliveryRate","statusCounts"]},"CampaignDetailDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"type":{"type":"string","enum":["SCHEDULED","IMMEDIATE","RECURRING"]},"status":{"type":"string","enum":["ACTIVE","FAILED","SCHEDULED","CANCELLED","COMPLETED","DRAFT","PAUSED"]},"channel":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"messageTemplate":{"type":"string"},"subject":{"type":"string","nullable":true},"previewText":{"type":"string","nullable":true},"designJson":{"type":"object","description":"EMAIL designed-mode only — NULL when the campaign is plain-mode or SMS."},"emailTemplateId":{"type":"string","nullable":true,"description":"EMAIL only — provenance link to the seeding template, if any."},"whatsappTemplateId":{"type":"string","nullable":true,"description":"WHATSAPP only — the APPROVED template this campaign sends. NULL for every\nother channel. `messageTemplate` is blank for WhatsApp (the body lives on\nthe template record), so the detail page hydrates the body by this id."},"whatsappVariantBody":{"type":"string","nullable":true,"description":"WHATSAPP only — the optional free-form open-conversation reply. NULL otherwise."},"whatsappVariableMap":{"description":"WHATSAPP only — per-campaign tag per template variable ('' = the template's own).","type":"array","items":{"type":"string"}},"mediaUrls":{"type":"array","items":{"type":"string"}},"mediaAttachments":{"description":"What each `mediaUrls` entry is, for the attachments we host.","type":"array","items":{"type":"object"}},"segments":{"description":"Every targeted segment, in pick order.","type":"array","items":{"$ref":"#/components/schemas/CampaignSegmentRefDto"}},"scheduledAt":{"format":"date-time","type":"string","nullable":true},"scheduleTimezone":{"type":"string","nullable":true},"quietHoursMode":{"type":"string","description":"Three-state quiet-hours override: INHERIT the org window, OFF, or CUSTOM (fields below).","enum":["OFF","CUSTOM","INHERIT"]},"quietHoursStart":{"type":"string","nullable":true,"description":"CUSTOM mode only — HH:MM wall clock in `quietHoursTimezone` (else schedule/org tz)."},"quietHoursEnd":{"type":"string","nullable":true},"quietHoursTimezone":{"type":"string","nullable":true},"recurrenceRule":{"type":"string","nullable":true},"recurrenceTimezone":{"type":"string","nullable":true},"recurrenceStartsAt":{"format":"date-time","type":"string","nullable":true},"recurrenceEndsAt":{"format":"date-time","type":"string","nullable":true},"maxRuns":{"type":"number","nullable":true},"runsCompleted":{"type":"number"},"catchUpPolicy":{"type":"string","enum":["LATEST_ONLY","FIRE_ALL","SKIP_ALL"]},"overlapPolicy":{"type":"string","enum":["SKIP","ALLOW"]},"nextRunAt":{"format":"date-time","type":"string","nullable":true},"endRequestedAt":{"format":"date-time","type":"string","nullable":true},"startedAt":{"format":"date-time","type":"string","nullable":true},"completedAt":{"format":"date-time","type":"string","nullable":true},"pausedAt":{"format":"date-time","type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"counters":{"$ref":"#/components/schemas/CampaignCountersDto"},"channelIdentityIds":{"type":"array","items":{"type":"string"}},"hasExperiment":{"type":"boolean","description":"Whether this campaign is an A/B experiment. An experiment can only be attached at\ncreation, so `GET /campaigns/:id/experiment` 404s whenever this is false — the\nclient gates that call on this flag rather than probing for a 404."},"nextOccurrencePreview":{"type":"array","items":{"type":"string"}}},"required":["id","organizationId","name","description","type","status","channel","messageTemplate","subject","previewText","designJson","emailTemplateId","whatsappTemplateId","whatsappVariantBody","whatsappVariableMap","mediaUrls","mediaAttachments","segments","scheduledAt","scheduleTimezone","quietHoursMode","quietHoursStart","quietHoursEnd","quietHoursTimezone","recurrenceRule","recurrenceTimezone","recurrenceStartsAt","recurrenceEndsAt","maxRuns","runsCompleted","catchUpPolicy","overlapPolicy","nextRunAt","endRequestedAt","startedAt","completedAt","pausedAt","createdAt","updatedAt","counters","channelIdentityIds","hasExperiment"]},"UpdateCampaignDto":{"type":"object","properties":{"expectedVersion":{"type":"number","minimum":0,"maximum":1000000},"type":{"type":"string","enum":["SCHEDULED","IMMEDIATE","RECURRING"]},"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"messageTemplate":{"type":"string","maxLength":500000},"subject":{"type":"string","minLength":1,"maxLength":500},"previewText":{"type":"string","maxLength":255},"designJson":{"type":"object"},"emailTemplateId":{"type":"string","format":"uuid"},"whatsappTemplateId":{"type":"string","format":"uuid"},"whatsappVariantBody":{"type":"string","minLength":1,"maxLength":4096},"whatsappVariableMap":{"type":"array","items":{"type":"string","enum":["","first_name","last_name","full_name","phone","email","street_address","address_line_2","city","state","postal_code","country","full_address","organization_name","organization_phone","organization_email","organization_website"]}},"contactActions":{"type":"array","items":{"$ref":"#/components/schemas/CampaignContactActionDto"}},"mediaUrls":{"type":"array","items":{"type":"string"}},"segmentIds":{"description":"Replaces the whole target audience when present; omit to leave it untouched.\n\nNo `@ArrayMinSize(1)`, matching `CreateCampaignDto`: a campaign targets EITHER\nsegments or hand-picked contacts, so `segmentIds: []` alongside a non-empty\n`contactIds` is the normal shape of a contacts-targeted edit — the minimum\nrejected every one of them before the service saw the XOR. A draft with no\naudience at all sends `[]` for the same reason. The service enforces both the\nXOR and (for anything that is not a draft) the \"at least one recipient\" rule.","type":"array","items":{"type":"string","format":"uuid"}},"contactIds":{"description":"Hand-picked recipients. Mutually exclusive with `segmentIds`.","type":"array","items":{"type":"string","format":"uuid"}},"channelIdentityIds":{"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}},"scheduledAt":{"type":"string"},"scheduledTimezone":{"type":"string","minLength":1,"maxLength":64},"quietHoursMode":{"type":"string","enum":["OFF","CUSTOM","INHERIT"]},"quietHoursStart":{"type":"string"},"quietHoursEnd":{"type":"string"},"quietHoursTimezone":{"type":"string","minLength":1,"maxLength":64},"recurrenceRule":{"type":"string","minLength":1,"maxLength":500},"recurrenceTimezone":{"type":"string","minLength":1,"maxLength":64},"recurrenceStartsAt":{"type":"string"},"recurrenceEndsAt":{"type":"string"},"maxRuns":{"type":"number","minimum":1,"maximum":10000},"catchUpPolicy":{"type":"string","enum":["LATEST_ONLY","FIRE_ALL","SKIP_ALL"]},"overlapPolicy":{"type":"string","enum":["SKIP","ALLOW"]}},"required":["expectedVersion"]},"PauseCampaignDto":{"type":"object","properties":{"pauseInFlight":{"type":"boolean"}}},"DuplicateCampaignDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255}}},"CampaignCostEstimateDto":{"type":"object","properties":{"recipientCount":{"type":"number"},"messageType":{"description":"`MMS` when the campaign carries media. MMS is billed per message, so the\nsegment fields collapse to 1 / `recipientCount` and the rate that drives\nthe total is `costPerMessage`, not `costPerSegment`. `WHATSAPP` (SP3) is\nlikewise billed per message.","enum":["SMS","WHATSAPP","MMS"],"type":"string"},"segmentsPerMessage":{"type":"number"},"totalSegments":{"type":"number"},"costPerSegment":{"type":"number"},"costPerMessage":{"type":"number","nullable":true,"description":"Flat per-message rate. Null for SMS, which is priced per segment."},"totalCost":{"type":"number"},"audienceSize":{"type":"number","description":"Why `recipientCount` is smaller than the segment: the buckets sum to `audienceSize`."},"optedOutCount":{"type":"number"},"unreachableCount":{"type":"number"},"suppressedCount":{"type":"number","nullable":true,"description":"EMAIL only. `0` for SMS; `null` when the audience was too large to scan."},"whatsappOptedOutCount":{"type":"number","description":"WHATSAPP only — replied STOP on WhatsApp; a fourth bucket of `audienceSize`."},"whatsappUnconfirmedCount":{"type":"number","description":"WHATSAPP only — of `recipientCount`, never messaged the org on WhatsApp."}},"required":["recipientCount","messageType","segmentsPerMessage","totalSegments","costPerSegment","costPerMessage","totalCost","audienceSize","optedOutCount","unreachableCount","suppressedCount"]},"EstimateCampaignDto":{"type":"object","properties":{"segmentIds":{"type":"array","items":{"type":"string","format":"uuid"}},"contactIds":{"description":"Hand-picked recipients. When non-empty this is the audience, not `segmentIds`.","type":"array","items":{"type":"string","format":"uuid"}},"template":{"type":"string","minLength":1},"channel":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"mediaUrls":{"type":"array","items":{"type":"string"}},"trackedLinks":{"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/TrackedLinkDto"}}},"required":["segmentIds","template","channel"]},"CampaignValidationReportDto":{"type":"object","properties":{"ok":{"type":"boolean"},"blockers":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}}},"required":["ok","blockers","warnings"]},"RecurrencePreviewDto":{"type":"object","properties":{"recurrenceRule":{"type":"string","minLength":1,"maxLength":500},"timezone":{"type":"string","minLength":1,"maxLength":64},"from":{"type":"string"},"count":{"type":"number","minimum":1,"maximum":20}},"required":["recurrenceRule","timezone"]},"CampaignRecurrencePreviewDto":{"type":"object","properties":{"next":{"type":"array","items":{"type":"string"}}},"required":["next"]},"CampaignAnalyticsExecutionDto":{"type":"object","properties":{"executionId":{"type":"string"},"occurrenceIndex":{"type":"number"},"status":{"type":"string","enum":["FAILED","SCHEDULED","CANCELLED","COMPLETED","PAUSED","EXPANDING","RUNNING"]},"totalRecipients":{"type":"number"},"sentCount":{"type":"number"},"deliveredCount":{"type":"number"},"failedCount":{"type":"number"},"cancelledCount":{"type":"number"},"rejectedCount":{"type":"number","description":"Recipients skipped on purpose at dispatch for this run — its own column,\nnever folded into `failedCount` (spec §2). Declared here AND mapped in\n`CampaignsService.getAnalytics`: a Swagger-only declaration would promise\na counter the response never carried."},"totalCost":{"type":"number"},"scheduledAt":{"format":"date-time","type":"string","nullable":true},"completedAt":{"format":"date-time","type":"string","nullable":true}},"required":["executionId","occurrenceIndex","status","totalRecipients","sentCount","deliveredCount","failedCount","cancelledCount","rejectedCount","totalCost","scheduledAt","completedAt"]},"CampaignAnalyticsDto":{"type":"object","properties":{"counters":{"$ref":"#/components/schemas/CampaignCountersDto"},"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"},"perExecution":{"type":"array","items":{"$ref":"#/components/schemas/CampaignAnalyticsExecutionDto"}}},"required":["counters","page","limit","total","totalPages","perExecution"]},"CampaignMessageContactDto":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","firstName","lastName"]},"CampaignMessageDto":{"type":"object","properties":{"id":{"type":"string"},"purposeKind":{"enum":["WORKFLOW","CAMPAIGN","POLL"],"type":"string"},"purposeId":{"type":"string"},"contactId":{"type":"string"},"fromIdentityId":{"type":"string"},"fromNumber":{"type":"string"},"toNumber":{"type":"string"},"toEmail":{"type":"string","nullable":true,"description":"Authoritative addresses for EMAIL rows, `null` for SMS/WhatsApp."},"fromEmail":{"type":"string","nullable":true},"body":{"type":"string"},"status":{"enum":["QUEUED","SENT","DELIVERED","UNDELIVERED","FAILED","REJECTED","CANCELLED","PROCESSING"],"type":"string"},"providerMessageId":{"type":"string","nullable":true},"providerName":{"type":"string","nullable":true},"retryCount":{"type":"number"},"errorCode":{"type":"string","nullable":true},"errorMessage":{"type":"string","nullable":true},"sentAt":{"format":"date-time","type":"string","nullable":true},"deliveredAt":{"format":"date-time","type":"string","nullable":true},"failedAt":{"format":"date-time","type":"string","nullable":true},"firstOpenedAt":{"format":"date-time","type":"string","nullable":true,"description":"First open/click timestamps from the provider webhook — EMAIL only, `null` otherwise."},"firstClickedAt":{"format":"date-time","type":"string","nullable":true},"firstRepliedAt":{"format":"date-time","type":"string","nullable":true,"description":"First attributed campaign reply — SMS *and* EMAIL, unlike the two above.\nThe row's `status` is deliberately left at its delivery value."},"createdAt":{"format":"date-time","type":"string"},"contact":{"$ref":"#/components/schemas/CampaignMessageContactDto"}},"required":["id","purposeKind","purposeId","contactId","fromIdentityId","fromNumber","toNumber","toEmail","fromEmail","body","status","providerMessageId","providerName","retryCount","errorCode","errorMessage","sentAt","deliveredAt","failedAt","firstOpenedAt","firstClickedAt","firstRepliedAt","createdAt","contact"]},"GenerateVariantsDto":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"testDimension":{"type":"string","enum":["SUBJECT_LINE","MESSAGE_CONTENT"]},"originalContent":{"type":"string","minLength":1,"maxLength":5000},"tone":{"type":"string","enum":["professional","friendly","short","urgent","sales"]}},"required":["channel","testDimension","originalContent"]},"ExperimentVariantDto":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"isControl":{"type":"boolean"},"subject":{"type":"string","nullable":true},"messageTemplate":{"type":"string","nullable":true},"executionStatus":{"type":"string","nullable":true,"enum":["FAILED","SCHEDULED","CANCELLED","COMPLETED","PAUSED","EXPANDING","RUNNING"]},"totalRecipients":{"type":"number"},"deliveredCount":{"type":"number"},"uniqueOpenedCount":{"type":"number"},"uniqueClickedCount":{"type":"number"},"bouncedCount":{"type":"number"},"unsubscribedCount":{"type":"number"},"openRate":{"type":"number","description":"`uniqueOpenedCount / deliveredCount * 100` — 0 when nothing has delivered yet."},"clickRate":{"type":"number","description":"`uniqueClickedCount / deliveredCount * 100` — 0 when nothing has delivered yet."}},"required":["id","label","isControl","subject","messageTemplate","executionStatus","totalRecipients","deliveredCount","uniqueOpenedCount","uniqueClickedCount","bouncedCount","unsubscribedCount","openRate","clickRate"]},"ExperimentLiveDto":{"type":"object","properties":{"leader":{"type":"string","enum":["A","B"]},"confident":{"type":"boolean"},"confidencePct":{"type":"number"}},"required":["leader","confident","confidencePct"]},"ExperimentResponseDto":{"type":"object","properties":{"status":{"type":"string","enum":["CANCELLED","COMPLETED","RUNNING","AWAITING_APPROVAL"]},"testDimension":{"type":"string","enum":["SUBJECT_LINE","MESSAGE_CONTENT"]},"percentA":{"type":"number"},"percentB":{"type":"number"},"holdoutPercent":{"type":"number"},"winnerCriterion":{"type":"string","enum":["MANUAL","OPEN_RATE","CLICK_RATE"]},"decisionDelayMinutes":{"type":"number"},"requireApproval":{"type":"boolean"},"decideAt":{"format":"date-time","type":"string","nullable":true},"decidedAt":{"format":"date-time","type":"string","nullable":true},"decisionReason":{"type":"string","nullable":true,"enum":["MANUAL","AUTO_CONFIDENT","AUTO_DEADLINE_LOW_CONFIDENCE"]},"confidencePct":{"type":"number","nullable":true},"winnerLabel":{"type":"string","nullable":true,"enum":["A","B"]},"holdoutEstimate":{"type":"number","description":"Estimated eligible-audience size scaled from the two VARIANT_TEST executions' `totalRecipients`, times `holdoutPercent`. 0 when either percent is 0."},"variants":{"type":"array","items":{"$ref":"#/components/schemas/ExperimentVariantDto"}},"live":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ExperimentLiveDto"}]}},"required":["status","testDimension","percentA","percentB","holdoutPercent","winnerCriterion","decisionDelayMinutes","requireApproval","decideAt","decidedAt","decisionReason","confidencePct","winnerLabel","holdoutEstimate","variants","live"]},"ApproveWinnerDto":{"type":"object","properties":{"variantId":{"type":"string","format":"uuid"}},"required":["variantId"]},"CampaignExecutionDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"campaignId":{"type":"string"},"occurrenceIndex":{"type":"number"},"status":{"enum":["FAILED","SCHEDULED","CANCELLED","COMPLETED","PAUSED","EXPANDING","RUNNING"],"type":"string"},"scheduledAt":{"format":"date-time","type":"string","nullable":true},"startedAt":{"format":"date-time","type":"string","nullable":true},"expandedAt":{"format":"date-time","type":"string","nullable":true},"completedAt":{"format":"date-time","type":"string","nullable":true},"pausedAt":{"format":"date-time","type":"string","nullable":true},"cancelledAt":{"format":"date-time","type":"string","nullable":true},"totalRecipients":{"type":"number"},"sentCount":{"type":"number"},"deliveredCount":{"type":"number"},"failedCount":{"type":"number"},"cancelledCount":{"type":"number"},"rejectedCount":{"type":"number","description":"Recipients skipped on purpose at dispatch — consent withdrawn, contact\ngone, or a closed WhatsApp window on a skip-configured step. Its own\ncolumn, deliberately NOT part of `failedCount`: a skip never went out, so\ncounting it as a delivery failure would inflate every failure rate read\noff this response (spec §2)."},"queuedCount":{"type":"number","description":"Rows still awaiting dispatch. Counted from `outbound_messages`, NOT derived —\n `sentCount` and `failedCount` overlap, so subtracting them understates it."},"suppressedCount":{"type":"number","description":"EMAIL only, and a SUBSET of `failedCount`: rows withheld because the\n recipient's address is unsubscribed."},"repliedCount":{"type":"number","description":"Distinct recipients who replied. Channel-agnostic — SMS and EMAIL both\ncount here, unlike the email-only engagement counters below."},"openedCount":{"type":"number","description":"Email engagement counters — aggregated from `EmailEvent` by the provider webhook."},"clickedCount":{"type":"number"},"uniqueOpenedCount":{"type":"number"},"uniqueClickedCount":{"type":"number"},"totalCost":{"type":"number","description":"Provider-confirmed money only — never includes a substituted estimate."},"fallbackCost":{"type":"number","description":"Estimate substituted where the real cost could not be retrieved."},"estimatedCost":{"type":"number","description":"The pre-send estimate, for reference. Never presented as a cost."},"costFinalized":{"type":"boolean","description":"True once every sent message has reached a terminal cost state."},"settledCount":{"type":"number","description":"Sent messages whose cost is terminal (confirmed or written off)."},"unreconciledCount":{"type":"number","description":"Of those, how many fell back to an estimate — the gap in `totalCost`."},"consecutiveFailureCount":{"type":"number"},"autoPausedAt":{"format":"date-time","type":"string","nullable":true},"autoPauseReason":{"type":"string","nullable":true},"heldUntil":{"format":"date-time","type":"string","nullable":true,"description":"Display-only: when a dispatch pass last held this run's rows for quiet hours (null = not held)."},"holdReason":{"type":"string","nullable":true},"lastExpandedContactId":{"type":"string","nullable":true},"expansionAttempt":{"type":"number"},"failureReason":{"type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","organizationId","campaignId","occurrenceIndex","status","scheduledAt","startedAt","expandedAt","completedAt","pausedAt","cancelledAt","totalRecipients","sentCount","deliveredCount","failedCount","cancelledCount","rejectedCount","queuedCount","suppressedCount","repliedCount","openedCount","clickedCount","uniqueOpenedCount","uniqueClickedCount","totalCost","fallbackCost","estimatedCost","costFinalized","settledCount","unreconciledCount","consecutiveFailureCount","autoPausedAt","autoPauseReason","heldUntil","holdReason","lastExpandedContactId","expansionAttempt","failureReason","createdAt","updatedAt"]},"CampaignExecutionAnalyticsDto":{"type":"object","properties":{"executionId":{"type":"string"},"status":{"type":"string","enum":["FAILED","SCHEDULED","CANCELLED","COMPLETED","PAUSED","EXPANDING","RUNNING"]},"totalRecipients":{"type":"number"},"sentCount":{"type":"number"},"deliveredCount":{"type":"number"},"failedCount":{"type":"number"},"cancelledCount":{"type":"number"},"rejectedCount":{"type":"number","description":"Recipients skipped on purpose at dispatch — see `CampaignExecutionDto.rejectedCount`."},"totalCost":{"type":"number"},"fallbackCost":{"type":"number","description":"Estimate substituted where the real cost could not be retrieved."},"estimatedCost":{"type":"number","description":"The pre-send estimate, for reference. Never presented as a cost."},"costFinalized":{"type":"boolean","description":"True once every sent message has reached a terminal cost state."},"settledCount":{"type":"number","description":"Sent messages whose cost is terminal (confirmed or written off)."},"unreconciledCount":{"type":"number","description":"Of those, how many fell back to an estimate — the gap in `totalCost`."},"autoPausedAt":{"format":"date-time","type":"string","nullable":true},"autoPauseReason":{"type":"string","nullable":true},"heldUntil":{"format":"date-time","type":"string","nullable":true,"description":"Display-only: when a dispatch pass last held this run's rows for quiet hours (null = not held)."},"holdReason":{"type":"string","nullable":true}},"required":["executionId","status","totalRecipients","sentCount","deliveredCount","failedCount","cancelledCount","rejectedCount","totalCost","fallbackCost","estimatedCost","costFinalized","settledCount","unreconciledCount","autoPausedAt","autoPauseReason","heldUntil","holdReason"]},"RecipientMessageFilterDto":{"type":"object","properties":{"status":{"type":"string","enum":["QUEUED","SENT","DELIVERED","UNDELIVERED","FAILED","REJECTED","CANCELLED","PROCESSING"]},"errorCode":{"type":"string","description":"e.g. INSUFFICIENT_CREDITS — pair with `status: FAILED`.","maxLength":64},"search":{"type":"string","maxLength":255}}},"RemoveFromSegmentDto":{"type":"object","properties":{"segmentIds":{"description":"Which of the campaign's targeted segments to remove from. Omit to strip the\ncontacts from every STATIC segment the campaign targets; DYNAMIC ones are\nskipped in that case because their membership is rule-derived, but naming\none explicitly is an error rather than a silent no-op.","minItems":1,"type":"array","items":{"type":"string","format":"uuid"}},"contactIds":{"description":"The checkbox selection. Mutually exclusive with `filter`.","minItems":1,"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"description":"\"Select all matching\" — the table's current status/search filter.","allOf":[{"$ref":"#/components/schemas/RecipientMessageFilterDto"}]}}},"AddRecipientsToSegmentDto":{"type":"object","properties":{"targetSegmentId":{"type":"string","description":"Any STATIC segment the org owns — it need not be one this campaign targets;\nthe common case is building a follow-up list out of a run's failures.\nOwnership and the STATIC requirement are enforced by `SegmentsService`.","format":"uuid"},"contactIds":{"description":"The checkbox selection. Mutually exclusive with `filter`.","minItems":1,"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"description":"\"Select all matching\" — the table's current status/search filter.","allOf":[{"$ref":"#/components/schemas/RecipientMessageFilterDto"}]}},"required":["targetSegmentId"]},"AddTagsToRecipientsDto":{"type":"object","properties":{"tagIds":{"description":"Org-owned tags to add; ownership is enforced by the contacts bulk edit.","minItems":1,"type":"array","items":{"type":"string","format":"uuid"}},"contactIds":{"description":"The checkbox selection. Mutually exclusive with `filter`.","minItems":1,"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"description":"\"Select all matching\" — the table's current status/search filter.","allOf":[{"$ref":"#/components/schemas/RecipientMessageFilterDto"}]}},"required":["tagIds"]},"ExportRecipientsDto":{"type":"object","properties":{"contactIds":{"description":"The checkbox selection. Mutually exclusive with `filter`.","minItems":1,"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"description":"\"Select all matching\" — the table's current status/search filter.","allOf":[{"$ref":"#/components/schemas/RecipientMessageFilterDto"}]}}},"CreateEmailTemplateDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":150},"description":{"type":"string","maxLength":500},"category":{"type":"string","enum":["MARKETING","WELCOME","GENERAL","NEWSLETTER","PROMOTIONAL","ANNOUNCEMENT","TRANSACTIONAL","EVENT"]},"subject":{"type":"string","maxLength":500},"previewText":{"type":"string","maxLength":255},"designJson":{"type":"object","description":"The email builder document. Structural validation (zod schema, block\nshapes, merge-tag allow-list) happens downstream in\n`EmailDocumentPipeline.validateAndCompile` - this DTO only guards that\n*something object-shaped* was sent, and passes it through as `unknown`\nso the pipeline stays the single source of truth for the document shape."}},"required":["name","category","designJson"]},"EmailTemplateCreatorDto":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"}},"required":["id","firstName","lastName","email"]},"EmailTemplateListResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"category":{"type":"string","enum":["MARKETING","WELCOME","GENERAL","NEWSLETTER","PROMOTIONAL","ANNOUNCEMENT","TRANSACTIONAL","EVENT"]},"status":{"type":"string","enum":["ACTIVE","ARCHIVED","DRAFT"]},"isSystem":{"type":"boolean"},"isFavorite":{"type":"boolean"},"usedInCampaigns":{"type":"number"},"subject":{"type":"string","nullable":true},"updatedAt":{"format":"date-time","type":"string"},"createdAt":{"format":"date-time","type":"string"},"createdByUser":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/EmailTemplateCreatorDto"}]}},"required":["id","name","description","category","status","isSystem","isFavorite","usedInCampaigns","subject","updatedAt","createdAt","createdByUser"]},"PreviewEmailTemplateDto":{"type":"object","properties":{"designJson":{"type":"object"}},"required":["designJson"]},"EmailTemplateDetailResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"category":{"enum":["MARKETING","WELCOME","GENERAL","NEWSLETTER","PROMOTIONAL","ANNOUNCEMENT","TRANSACTIONAL","EVENT"],"type":"string"},"status":{"enum":["ACTIVE","ARCHIVED","DRAFT"],"type":"string"},"isSystem":{"type":"boolean"},"isFavorite":{"type":"boolean"},"usedInCampaigns":{"type":"number"},"subject":{"type":"string","nullable":true},"updatedAt":{"format":"date-time","type":"string"},"createdAt":{"format":"date-time","type":"string"},"createdByUser":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/EmailTemplateCreatorDto"}]},"previewText":{"type":"string","nullable":true},"designJson":{"type":"object"},"compiledHtml":{"type":"string"},"version":{"type":"number"}},"required":["id","name","description","category","status","isSystem","isFavorite","usedInCampaigns","subject","updatedAt","createdAt","createdByUser","previewText","designJson","compiledHtml","version"]},"UpdateEmailTemplateDto":{"type":"object","properties":{"status":{"type":"string","enum":["ACTIVE","ARCHIVED","DRAFT"]},"expectedVersion":{"type":"number","minimum":0}}},"DuplicateEmailTemplateDto":{"type":"object","properties":{"name":{"type":"string","maxLength":150}}},"CreateShortLinkDto":{"type":"object","properties":{"originalUrl":{"type":"string","maxLength":2048,"format":"uri"},"title":{"type":"string","maxLength":255},"expiresAt":{"type":"string","description":"ISO-8601 datetime. Omit (or empty) for a link that never expires."}},"required":["originalUrl"]},"UpdateShortLinkDto":{"type":"object","properties":{"originalUrl":{"type":"string","maxLength":2048,"format":"uri"},"title":{"type":"string","maxLength":255},"expiresAt":{"type":"string","description":"ISO-8601 datetime, or an empty string to clear the expiry (make the link\npermanent). `ValidateIf` lets the empty-string sentinel through; the\nservice maps it to `null`."}}},"CreateTicketDto":{"type":"object","properties":{"subject":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":10000},"priority":{"type":"string","enum":["LOW","HIGH","URGENT","MEDIUM"]},"assigneeId":{"type":"string","format":"uuid"},"reporterId":{"type":"string","description":"Defaults to the creator when omitted.","format":"uuid"},"dueAt":{"type":"string"},"tagIds":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["subject"]},"EscalateTicketDto":{"type":"object","properties":{"unifiedConversationId":{"type":"string","format":"uuid"},"subject":{"type":"string","description":"Defaults to a subject derived from the conversation's last message.","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":10000},"priority":{"type":"string","enum":["LOW","HIGH","URGENT","MEDIUM"]},"assigneeId":{"type":"string","format":"uuid"}},"required":["unifiedConversationId"]},"UpdateTicketDto":{"type":"object","properties":{"subject":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","nullable":true,"maxLength":10000},"priority":{"type":"string","enum":["LOW","HIGH","URGENT","MEDIUM"]},"assigneeId":{"type":"string","nullable":true,"description":"`null` unassigns the ticket.","format":"uuid"},"reporterId":{"type":"string","format":"uuid"},"dueAt":{"type":"string","nullable":true,"description":"`null` clears the due date."}}},"ChangeTicketStatusDto":{"type":"object","properties":{"status":{"type":"string","enum":["OPEN","CLOSED","IN_PROGRESS","REOPENED","RESOLVED"]}},"required":["status"]},"ManageTicketTagsDto":{"type":"object","properties":{"tagIds":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["tagIds"]},"CreateTicketCommentDto":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":5000}},"required":["body"]},"UpdateTicketCommentDto":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":5000}},"required":["body"]},"GetAttachmentUploadUrlDto":{"type":"object","properties":{"fileName":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","minLength":1,"maxLength":255},"sizeBytes":{"type":"number","minimum":1,"maximum":26214400}},"required":["fileName","contentType","sizeBytes"]},"ConfirmAttachmentDto":{"type":"object","properties":{"storageKey":{"type":"string","minLength":1,"maxLength":1024},"fileName":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","minLength":1,"maxLength":255},"sizeBytes":{"type":"number","minimum":1,"maximum":26214400}},"required":["storageKey","fileName","contentType","sizeBytes"]},"MeetingTypeEmailTemplateDto":{"type":"object","properties":{"subject":{"type":"string","maxLength":200},"body":{"type":"string","maxLength":4000}}},"MeetingTypeMessageTemplatesDto":{"type":"object","properties":{"confirmationSms":{"type":"string","maxLength":480},"reminderSms":{"type":"string","maxLength":480},"confirmationEmail":{"$ref":"#/components/schemas/MeetingTypeEmailTemplateDto"},"reminderEmail":{"$ref":"#/components/schemas/MeetingTypeEmailTemplateDto"}}},"MeetingTypeQuestionDto":{"type":"object","properties":{"id":{"type":"string","description":"Present when editing an existing question (update flow).","format":"uuid"},"label":{"type":"string","minLength":1,"maxLength":255},"type":{"type":"string","enum":["EMAIL","TEXT","PHONE","TEXTAREA","DROPDOWN","CHECKBOX","ADDRESS"]},"required":{"type":"boolean"},"options":{"type":"array","items":{"type":"string","maxLength":100}}},"required":["label","type","required"]},"MeetingTypeTeamMemberDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"weight":{"type":"number","minimum":1,"maximum":10},"priority":{"type":"number","description":"PRIORITY assignment: lower wins; 0 / omitted = unset.","minimum":0,"maximum":50}},"required":["userId"]},"CreateMeetingTypeDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":150},"slug":{"type":"string","minLength":2,"maxLength":100},"description":{"type":"string","maxLength":2000},"color":{"type":"string","enum":["blue","green","red","yellow","purple","orange","gray"]},"durationMin":{"type":"number","minimum":5,"maximum":480},"locationType":{"type":"string","enum":["PHONE","GOOGLE_MEET","MICROSOFT_TEAMS","IN_PERSON","CUSTOM_URL"]},"locationDetail":{"type":"object","additionalProperties":true,"description":"`{ phone? } | { address?, mapsUrl? } | { customUrl? }` depending on locationType.\nValues are checked (links, phone) by `MeetingTypesService`."},"bufferBeforeMin":{"type":"number","minimum":0,"maximum":120},"bufferAfterMin":{"type":"number","minimum":0,"maximum":120},"minNoticeMin":{"type":"number","minimum":0,"maximum":20160},"maxWindowDays":{"type":"number","minimum":1,"maximum":365},"slotIncrementMin":{"type":"number","minimum":5,"maximum":480},"dailyLimit":{"type":"number","minimum":1,"maximum":50},"weeklyLimit":{"type":"number","minimum":1,"maximum":50},"confirmationMessage":{"type":"string","maxLength":2000},"defaultValue":{"type":"number","description":"Default conversion value applied to a booking's completion when no explicit value is given.","minimum":0,"maximum":9999999999},"reminderOffsetsMin":{"type":"array","items":{"type":"number"}},"assignmentType":{"type":"string","enum":["SINGLE_HOST","ROUND_ROBIN","PRIORITY"]},"hostUserId":{"type":"string","format":"uuid"},"scheduleId":{"type":"string","format":"uuid"},"smsIdentityId":{"type":"string","description":"Sender identity for booking SMS; unset means this meeting type sends none.","format":"uuid"},"internalName":{"type":"string","description":"Owner-facing label shown in the app; the public page keeps `name`.","maxLength":150},"thankYouUrl":{"type":"string","description":"Where the invitee lands after booking; unset keeps the built-in page, `''` clears it.","maxLength":2048,"format":"uri"},"outcomeSetId":{"type":"string","description":"Outcome vocabulary for this appointment type; unset uses the organization default.","format":"uuid"},"requireServiceArea":{"type":"boolean","description":"When true, the public page asks for a ZIP and checks it against `serviceAreaIds`."},"serviceAreaIds":{"description":"The accepted areas; on update the list replaces the current one wholesale.","type":"array","items":{"type":"string","format":"uuid"}},"outsideAreaTone":{"type":"string","description":"How a visitor outside every accepted area is told.","enum":["CUSTOM","EXPLICIT","SOFT"]},"outsideAreaText":{"type":"string","description":"The owner's own words; required (non-blank) when the tone is CUSTOM.","maxLength":500},"outsideAreaAction":{"type":"string","description":"What the page offers a visitor outside every accepted area.","enum":["TAKE_MESSAGE_NOTIFY","OFFER_CALLBACK","JUST_DECLINE"]},"messageTemplates":{"$ref":"#/components/schemas/MeetingTypeMessageTemplatesDto"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/MeetingTypeQuestionDto"}},"teamMembers":{"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/MeetingTypeTeamMemberDto"}}},"required":["name","slug","durationMin","locationType","assignmentType"]},"MeetingTypeServiceAreaResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"MeetingTypeQuestionResponseDto":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["EMAIL","TEXT","PHONE","TEXTAREA","DROPDOWN","CHECKBOX","ADDRESS"]},"required":{"type":"boolean"},"options":{"type":"array","items":{"type":"string"}},"sortOrder":{"type":"number"}},"required":["id","label","type","required","options","sortOrder"]},"MeetingTypeTeamMemberResponseDto":{"type":"object","properties":{"userId":{"type":"string"},"weight":{"type":"number"},"priority":{"type":"number"},"assignmentCount":{"type":"number"},"isActive":{"type":"boolean"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"}},"required":["userId","weight","priority","assignmentCount","isActive","firstName","lastName","email"]},"MeetingTypeResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string","nullable":true},"color":{"type":"string","nullable":true},"durationMin":{"type":"number"},"locationType":{"enum":["PHONE","GOOGLE_MEET","MICROSOFT_TEAMS","IN_PERSON","CUSTOM_URL"],"type":"string"},"locationDetail":{"type":"object","additionalProperties":true},"bufferBeforeMin":{"type":"number"},"bufferAfterMin":{"type":"number"},"minNoticeMin":{"type":"number"},"maxWindowDays":{"type":"number"},"slotIncrementMin":{"type":"number","nullable":true},"dailyLimit":{"type":"number","nullable":true},"weeklyLimit":{"type":"number","nullable":true},"confirmationMessage":{"type":"string","nullable":true},"defaultValue":{"type":"number","nullable":true,"description":"Default conversion value applied on booking completion when no explicit value is given."},"reminderOffsetsMin":{"type":"array","items":{"type":"number"}},"assignmentType":{"enum":["SINGLE_HOST","ROUND_ROBIN","PRIORITY"],"type":"string"},"hostUserId":{"type":"string","nullable":true},"hostName":{"type":"string","nullable":true},"scheduleId":{"type":"string","nullable":true},"scheduleName":{"type":"string","nullable":true},"scheduleTimezone":{"type":"string","nullable":true},"smsIdentityId":{"type":"string","nullable":true},"internalName":{"type":"string","nullable":true},"thankYouUrl":{"type":"string","nullable":true},"outcomeSetId":{"type":"string","nullable":true},"outcomeSetName":{"type":"string","nullable":true},"requireServiceArea":{"type":"boolean"},"outsideAreaTone":{"enum":["CUSTOM","EXPLICIT","SOFT"],"type":"string"},"outsideAreaText":{"type":"string","nullable":true},"outsideAreaAction":{"enum":["TAKE_MESSAGE_NOTIFY","OFFER_CALLBACK","JUST_DECLINE"],"type":"string"},"serviceAreas":{"description":"The accepted areas, by name.","type":"array","items":{"$ref":"#/components/schemas/MeetingTypeServiceAreaResponseDto"}},"messageTemplates":{"type":"object"},"status":{"enum":["ACTIVE","ARCHIVED"],"type":"string"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/MeetingTypeQuestionResponseDto"}},"teamMembers":{"type":"array","items":{"$ref":"#/components/schemas/MeetingTypeTeamMemberResponseDto"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","slug","description","color","durationMin","locationType","locationDetail","bufferBeforeMin","bufferAfterMin","minNoticeMin","maxWindowDays","slotIncrementMin","dailyLimit","weeklyLimit","confirmationMessage","defaultValue","reminderOffsetsMin","assignmentType","hostUserId","hostName","scheduleId","scheduleName","scheduleTimezone","smsIdentityId","internalName","thankYouUrl","outcomeSetId","outcomeSetName","requireServiceArea","outsideAreaTone","outsideAreaText","outsideAreaAction","serviceAreas","messageTemplates","status","questions","teamMembers","createdAt","updatedAt"]},"UpdateMeetingTypeDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":150},"slug":{"type":"string","minLength":2,"maxLength":100},"description":{"type":"string","maxLength":2000},"color":{"type":"string","enum":["blue","green","red","yellow","purple","orange","gray"]},"durationMin":{"type":"number","minimum":5,"maximum":480},"locationType":{"enum":["PHONE","GOOGLE_MEET","MICROSOFT_TEAMS","IN_PERSON","CUSTOM_URL"],"type":"string"},"locationDetail":{"type":"object","additionalProperties":true,"description":"`{ phone? } | { address?, mapsUrl? } | { customUrl? }` depending on locationType.\nValues are checked (links, phone) by `MeetingTypesService`."},"bufferBeforeMin":{"type":"number","minimum":0,"maximum":120},"bufferAfterMin":{"type":"number","minimum":0,"maximum":120},"minNoticeMin":{"type":"number","minimum":0,"maximum":20160},"maxWindowDays":{"type":"number","minimum":1,"maximum":365},"slotIncrementMin":{"type":"number","minimum":5,"maximum":480},"dailyLimit":{"type":"number","minimum":1,"maximum":50},"weeklyLimit":{"type":"number","minimum":1,"maximum":50},"confirmationMessage":{"type":"string","maxLength":2000},"defaultValue":{"type":"number","description":"Default conversion value applied to a booking's completion when no explicit value is given.","minimum":0,"maximum":9999999999},"reminderOffsetsMin":{"type":"array","items":{"type":"number"}},"assignmentType":{"enum":["SINGLE_HOST","ROUND_ROBIN","PRIORITY"],"type":"string"},"hostUserId":{"type":"string","format":"uuid"},"scheduleId":{"type":"string","format":"uuid"},"smsIdentityId":{"type":"string","description":"Sender identity for booking SMS; unset means this meeting type sends none.","format":"uuid"},"internalName":{"type":"string","description":"Owner-facing label shown in the app; the public page keeps `name`.","maxLength":150},"thankYouUrl":{"type":"string","description":"Where the invitee lands after booking; unset keeps the built-in page, `''` clears it.","maxLength":2048,"format":"uri"},"outcomeSetId":{"type":"string","description":"Outcome vocabulary for this appointment type; unset uses the organization default.","format":"uuid"},"requireServiceArea":{"type":"boolean","description":"When true, the public page asks for a ZIP and checks it against `serviceAreaIds`."},"serviceAreaIds":{"description":"The accepted areas; on update the list replaces the current one wholesale.","type":"array","items":{"type":"string","format":"uuid"}},"outsideAreaTone":{"description":"How a visitor outside every accepted area is told.","enum":["CUSTOM","EXPLICIT","SOFT"],"type":"string"},"outsideAreaText":{"type":"string","description":"The owner's own words; required (non-blank) when the tone is CUSTOM.","maxLength":500},"outsideAreaAction":{"description":"What the page offers a visitor outside every accepted area.","enum":["TAKE_MESSAGE_NOTIFY","OFFER_CALLBACK","JUST_DECLINE"],"type":"string"},"messageTemplates":{"$ref":"#/components/schemas/MeetingTypeMessageTemplatesDto"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/MeetingTypeQuestionDto"}},"teamMembers":{"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/MeetingTypeTeamMemberDto"}}}},"AvailabilityRuleResponseDto":{"type":"object","properties":{"dayOfWeek":{"type":"number"},"startMinute":{"type":"number"},"endMinute":{"type":"number"}},"required":["dayOfWeek","startMinute","endMinute"]},"AvailabilityIntervalResponseDto":{"type":"object","properties":{"startMinute":{"type":"number"},"endMinute":{"type":"number"}},"required":["startMinute","endMinute"]},"AvailabilityOverrideResponseDto":{"type":"object","properties":{"date":{"type":"string"},"isUnavailable":{"type":"boolean"},"intervals":{"type":"array","items":{"$ref":"#/components/schemas/AvailabilityIntervalResponseDto"}}},"required":["date","isUnavailable","intervals"]},"AvailabilityScheduleResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"timezone":{"type":"string"},"isDefault":{"type":"boolean"},"rules":{"type":"array","items":{"$ref":"#/components/schemas/AvailabilityRuleResponseDto"}},"overrides":{"type":"array","items":{"$ref":"#/components/schemas/AvailabilityOverrideResponseDto"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","timezone","isDefault","rules","overrides","createdAt","updatedAt"]},"AvailabilityRuleDto":{"type":"object","properties":{"dayOfWeek":{"type":"number","minimum":0,"maximum":6},"startMinute":{"type":"number","minimum":0,"maximum":1440},"endMinute":{"type":"number","minimum":0,"maximum":1440}},"required":["dayOfWeek","startMinute","endMinute"]},"CreateAvailabilityScheduleDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"timezone":{"type":"string","maxLength":50},"isDefault":{"type":"boolean"},"rules":{"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/AvailabilityRuleDto"}}},"required":["name","timezone","rules"]},"UpdateAvailabilityScheduleDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"timezone":{"type":"string","maxLength":50},"isDefault":{"type":"boolean"},"rules":{"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/AvailabilityRuleDto"}}}},"OverrideIntervalDto":{"type":"object","properties":{"startMinute":{"type":"number","minimum":0,"maximum":1440},"endMinute":{"type":"number","minimum":0,"maximum":1440}},"required":["startMinute","endMinute"]},"AvailabilityOverrideDto":{"type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"isUnavailable":{"type":"boolean"},"intervals":{"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/OverrideIntervalDto"}}},"required":["date","isUnavailable","intervals"]},"UpsertOverridesDto":{"type":"object","properties":{"overrides":{"maxItems":366,"type":"array","items":{"$ref":"#/components/schemas/AvailabilityOverrideDto"}}},"required":["overrides"]},"PublicBookingAnswerDto":{"type":"object","properties":{"questionId":{"type":"string","format":"uuid"},"value":{"type":"object","description":"string | boolean | string[] — validated against the question type in\n the service (type depends on tenant configuration, not the schema)."}},"required":["questionId","value"]},"CreateStaffBookingDto":{"type":"object","properties":{"meetingTypeId":{"type":"string","format":"uuid"},"hostUserId":{"type":"string","format":"uuid"},"startAt":{"format":"date-time","type":"string"},"timezone":{"type":"string","maxLength":50},"inviteeName":{"type":"string","minLength":1,"maxLength":200},"inviteeEmail":{"type":"string","maxLength":255,"format":"email"},"inviteePhone":{"type":"string","maxLength":32},"inviteeNotes":{"type":"string","maxLength":2000},"contactId":{"type":"string","format":"uuid"},"answers":{"type":"array","items":{"$ref":"#/components/schemas/PublicBookingAnswerDto"}},"postalCode":{"type":"string","maxLength":20}},"required":["meetingTypeId","startAt","timezone","inviteeName"]},"BookingAnswerResponseDto":{"type":"object","properties":{"questionId":{"type":"string"},"questionLabel":{"type":"string"},"value":{"type":"object"}},"required":["questionId","questionLabel","value"]},"BookingResponseDto":{"type":"object","properties":{"id":{"type":"string"},"status":{"enum":["SCHEDULED","CANCELLED","COMPLETED","CONFIRMED","RESCHEDULED","NO_SHOW"],"type":"string"},"meetingTypeId":{"type":"string"},"meetingTypeName":{"type":"string"},"meetingTypeColor":{"type":"string","nullable":true},"meetingTypeSlug":{"type":"string"},"meetingTypeDurationMin":{"type":"number"},"meetingTypeOutcomeSetId":{"type":"string","nullable":true,"description":"The type's own outcome set; null means the org default applies."},"hostUserId":{"type":"string"},"hostName":{"type":"string"},"hostFirstName":{"type":"string"},"hostLastName":{"type":"string"},"contactId":{"type":"string","nullable":true},"inviteeName":{"type":"string"},"inviteeEmail":{"type":"string"},"inviteePhone":{"type":"string","nullable":true},"inviteeCompany":{"type":"string","nullable":true},"inviteeNotes":{"type":"string","nullable":true},"inviteeTimezone":{"type":"string"},"startAt":{"type":"string"},"endAt":{"type":"string"},"locationType":{"enum":["PHONE","GOOGLE_MEET","MICROSOFT_TEAMS","IN_PERSON","CUSTOM_URL"],"type":"string"},"locationValue":{"type":"string","nullable":true},"servicePostalCode":{"type":"string","nullable":true},"cancellationReason":{"type":"string","nullable":true},"cancelledAt":{"type":"string","nullable":true},"cancelledBy":{"nullable":true,"enum":["SYSTEM","INVITEE","HOST"],"type":"string"},"rescheduledFromId":{"type":"string","nullable":true},"source":{"type":"string"},"externalSyncStatus":{"enum":["PENDING","SYNCED","SYNC_FAILED","NOT_APPLICABLE","DESYNCED"],"type":"string"},"answers":{"type":"array","items":{"$ref":"#/components/schemas/BookingAnswerResponseDto"}},"outcomeId":{"type":"string","nullable":true},"outcomeLabel":{"type":"string","nullable":true},"outcomeCategory":{"nullable":true,"enum":["PENDING","LOST","NOT_QUALIFIED","NO_SHOW","PRESENTED_NO_SALE","WON"],"type":"string"},"outcomeNote":{"type":"string","nullable":true},"outcomeValue":{"type":"number","nullable":true},"outcomeAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","status","meetingTypeId","meetingTypeName","meetingTypeColor","meetingTypeSlug","meetingTypeDurationMin","meetingTypeOutcomeSetId","hostUserId","hostName","hostFirstName","hostLastName","contactId","inviteeName","inviteeEmail","inviteePhone","inviteeCompany","inviteeNotes","inviteeTimezone","startAt","endAt","locationType","locationValue","servicePostalCode","cancellationReason","cancelledAt","cancelledBy","rescheduledFromId","source","externalSyncStatus","answers","outcomeId","outcomeLabel","outcomeCategory","outcomeNote","outcomeValue","outcomeAt","createdAt"]},"CancelBookingDto":{"type":"object","properties":{"reason":{"type":"string","maxLength":500}}},"CompleteBookingDto":{"type":"object","properties":{"value":{"type":"number","minimum":0,"maximum":9999999999}}},"MarkOutcomeDto":{"type":"object","properties":{"outcomeId":{"type":"string","format":"uuid"},"note":{"type":"string","maxLength":1000},"value":{"type":"number","minimum":0,"maximum":9999999999}},"required":["outcomeId"]},"ManageRescheduleDto":{"type":"object","properties":{"startAt":{"format":"date-time","type":"string"},"timezone":{"type":"string","maxLength":50}},"required":["startAt"]},"CalendarBlockResponseDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"startDate":{"type":"string"},"endDate":{"type":"string"},"appliesTo":{"enum":["ALL","USERS"],"type":"string"},"userIds":{"type":"array","items":{"type":"string"}}},"required":["id","title","startDate","endDate","appliesTo","userIds"]},"CreateCalendarBlockDto":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":150},"startDate":{"type":"string"},"endDate":{"type":"string"},"appliesTo":{"type":"string","enum":["ALL","USERS"]},"userIds":{"description":"Required and non-empty when `appliesTo` is USERS.","minItems":1,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["title","startDate","endDate","appliesTo"]},"UpdateCalendarBlockDto":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":150},"startDate":{"type":"string"},"endDate":{"type":"string"},"appliesTo":{"type":"string","enum":["ALL","USERS"]},"userIds":{"type":"array","items":{"type":"string","format":"uuid"}}}},"ManageCancelDto":{"type":"object","properties":{"reason":{"type":"string","maxLength":500}}},"PublicOutsideAreaDto":{"type":"object","properties":{"tone":{"type":"string","enum":["CUSTOM","EXPLICIT","SOFT"]},"text":{"type":"string","description":"Already resolved: the owner's words for CUSTOM, else the default for the tone."},"action":{"type":"string","enum":["TAKE_MESSAGE_NOTIFY","OFFER_CALLBACK","JUST_DECLINE"]}},"required":["tone","text","action"]},"PublicBookingQuestionDto":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["EMAIL","TEXT","PHONE","TEXTAREA","DROPDOWN","CHECKBOX","ADDRESS"]},"required":{"type":"boolean"},"options":{"type":"array","items":{"type":"string"}}},"required":["id","label","type","required","options"]},"PublicMeetingTypeDto":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string","nullable":true},"color":{"type":"string","nullable":true},"durationMin":{"type":"number"},"locationType":{"type":"string","enum":["PHONE","GOOGLE_MEET","MICROSOFT_TEAMS","IN_PERSON","CUSTOM_URL"]},"minNoticeMin":{"type":"number"},"maxWindowDays":{"type":"number"},"thankYouUrl":{"type":"string","nullable":true},"requireServiceArea":{"type":"boolean","description":"When true the page asks for a ZIP before it shows times."},"emailOptional":{"type":"boolean","description":"When true the page may be submitted without an email: every phone-call\ntype. Phone types always need a phone."},"outsideArea":{"$ref":"#/components/schemas/PublicOutsideAreaDto"},"questions":{"type":"array","items":{"$ref":"#/components/schemas/PublicBookingQuestionDto"}}},"required":["name","slug","description","color","durationMin","locationType","minNoticeMin","maxWindowDays","thankYouUrl","requireServiceArea","emailOptional","outsideArea","questions"]},"PublicBookingConfigDto":{"type":"object","properties":{"organizationName":{"type":"string"},"hostName":{"type":"string","nullable":true,"description":"Display name of the host; null for round-robin meeting types."},"meetingType":{"$ref":"#/components/schemas/PublicMeetingTypeDto"}},"required":["organizationName","hostName","meetingType"]},"OutsideAreaRequestDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"phone":{"type":"string","description":"Required when a callback is wanted, or when there is no email to reach them by.","minLength":1,"maxLength":32},"email":{"type":"string","maxLength":255,"format":"email"},"postalCode":{"type":"string","minLength":1,"maxLength":20},"message":{"type":"string","maxLength":1000},"wantsCallback":{"type":"boolean"}},"required":["name","postalCode","wantsCallback"]},"CreatePublicBookingDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"email":{"type":"string","description":"Optional here; whether the meeting type needs one is the service's call\n(only phone-call types may skip it). Blank = absent.","maxLength":255,"format":"email"},"phone":{"type":"string","description":"Required for phone-call types — enforced by the service. Blank = absent.","maxLength":32},"company":{"type":"string","maxLength":200},"notes":{"type":"string","maxLength":2000},"timezone":{"type":"string","maxLength":50},"startAt":{"format":"date-time","type":"string"},"answers":{"type":"array","items":{"$ref":"#/components/schemas/PublicBookingAnswerDto"}},"consentGiven":{"type":"boolean"},"postalCode":{"type":"string","description":"The ZIP the invitee passed the service-area check with.","maxLength":20},"utmSource":{"type":"string","maxLength":255},"utmMedium":{"type":"string","maxLength":255},"utmCampaign":{"type":"string","maxLength":255},"utmTerm":{"type":"string","maxLength":255},"utmContent":{"type":"string","maxLength":255}},"required":["name","timezone","startAt","consentGiven"]},"CalendarSelectionItemDto":{"type":"object","properties":{"calendarId":{"type":"string","format":"uuid"},"isBusySource":{"type":"boolean"},"isPrimaryWrite":{"type":"boolean"}},"required":["calendarId"]},"UpdateCalendarSelectionDto":{"type":"object","properties":{"calendars":{"minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/CalendarSelectionItemDto"}}},"required":["calendars"]},"OutcomeResponseDto":{"type":"object","properties":{"id":{"type":"string"},"outcomeSetId":{"type":"string"},"label":{"type":"string"},"systemCategory":{"type":"string","enum":["PENDING","LOST","NOT_QUALIFIED","NO_SHOW","PRESENTED_NO_SALE","WON"]},"repHelpText":{"type":"string","nullable":true},"sortOrder":{"type":"number"},"isActive":{"type":"boolean"}},"required":["id","outcomeSetId","label","systemCategory","repHelpText","sortOrder","isActive"]},"OutcomeSetResponseDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"name":{"type":"string"},"isDefault":{"type":"boolean"},"outcomes":{"type":"array","items":{"$ref":"#/components/schemas/OutcomeResponseDto"}}},"required":["id","organizationId","name","isDefault","outcomes"]},"CreateOutcomeSetDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100}},"required":["name"]},"UpdateOutcomeSetDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"isDefault":{"type":"boolean"}}},"OutcomeDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string","maxLength":100},"systemCategory":{"type":"string","enum":["PENDING","LOST","NOT_QUALIFIED","NO_SHOW","PRESENTED_NO_SALE","WON"]},"repHelpText":{"type":"string","maxLength":500},"isActive":{"type":"boolean"}},"required":["label","systemCategory","isActive"]},"ReplaceOutcomesDto":{"type":"object","properties":{"outcomes":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/OutcomeDto"}}},"required":["outcomes"]},"ServiceAreaResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"enum":["ZIP_CODES","RADIUS","STATES","COUNTIES"],"type":"string"},"zipCodes":{"type":"array","items":{"type":"string"}},"centerPostalCode":{"type":"string","nullable":true},"centerLat":{"type":"number","nullable":true},"centerLng":{"type":"number","nullable":true},"radiusMiles":{"type":"number","nullable":true},"states":{"type":"array","items":{"type":"string"}},"counties":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"}},"required":["id","name","kind","zipCodes","centerPostalCode","centerLat","centerLng","radiusMiles","states","counties","isActive"]},"UpsertServiceAreaDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"kind":{"enum":["ZIP_CODES","RADIUS","STATES","COUNTIES"],"type":"string"},"zipCodes":{"type":"array","items":{"type":"string","maxLength":20}},"centerPostalCode":{"type":"string","maxLength":20},"centerLat":{"type":"number","minimum":-90,"maximum":90},"centerLng":{"type":"number","minimum":-180,"maximum":180},"radiusMiles":{"type":"number","minimum":1,"maximum":500},"states":{"maxItems":60,"type":"array","items":{"type":"string","maxLength":50}},"counties":{"maxItems":200,"type":"array","items":{"type":"string","maxLength":100}},"isActive":{"type":"boolean"}},"required":["name","kind"]},"GenerationParamsDto":{"type":"object","properties":{"temperature":{"type":"number","minimum":0,"maximum":2},"topP":{"type":"number","minimum":0,"maximum":1},"maxOutputTokens":{"type":"number","minimum":1}}},"GuardrailsDto":{"type":"object","properties":{"toneInstruction":{"type":"string","maxLength":2000},"refusalTopics":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":200}},"maxToolLoops":{"type":"number","minimum":1},"contextTokenCap":{"type":"number","minimum":1},"replyCharCap":{"type":"number","minimum":1}}},"PersonaDto":{"type":"object","properties":{"primaryPurpose":{"type":"string","enum":["customer_support","sales","appointment_booking","general_assistant","custom"]},"customPurpose":{"type":"string","maxLength":200},"toneOfVoice":{"type":"string","enum":["friendly_casual","professional_warm","formal_professional","neutral_informative"]},"languages":{"type":"array","items":{"type":"string","maxLength":40}},"welcomeMessage":{"type":"string","maxLength":480}}},"HandoverConfigDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"courtesyMessage":{"type":"string","maxLength":480},"phrases":{"description":"Custom phrases — an inbound message containing any (CONTAINS, case-insensitive) hands over.","type":"array","items":{"type":"string","maxLength":200}}}},"RetrievalSettingsDto":{"type":"object","properties":{"includeCitations":{"type":"boolean"},"provideLinks":{"type":"boolean"},"minScore":{"type":"number","description":"Cosine-similarity floor (confidence threshold) passed to retrieval `minScore`.","minimum":0,"maximum":1}}},"BookAppointmentSkillSettingsDto":{"type":"object","properties":{"meetingTypeIds":{"description":"The meeting types this employee may offer and book. When more than one is\nconfigured the employee must ask the customer to choose before looking up\nslots — see `runtime/tools/meeting-type-selection.ts`.","type":"array","items":{"type":"string","format":"uuid"}},"meetingTypeId":{"type":"string","description":"Legacy single-meeting-type form, still written by clients that predate the\nmulti-select. Read as a one-element fallback by `resolveSkillSettings`;\nnever written by the current wizard.","deprecated":true,"format":"uuid"}}},"StartFollowUpSkillSettingsDto":{"type":"object","properties":{"sequenceId":{"type":"string","nullable":true,"description":"A published sequence's id; `null` clears it (the tool then stays unmounted).","format":"uuid"}}},"NoReplyFollowUpSkillSettingsDto":{"type":"object","properties":{"delayMinutes":{"type":"number","description":"Minutes to wait for the customer's reply before the nudge goes out.","minimum":5,"maximum":20160},"message":{"type":"string","description":"The message the employee sends; blank keeps the skill inert.","maxLength":1000}}},"CreateTaskSkillSettingsDto":{"type":"object","properties":{"assigneeId":{"type":"string","nullable":true,"description":"A teammate's user id; `null`/absent leaves new tasks unassigned.","format":"uuid"}}},"BookingRulesSkillSettingsDto":{"type":"object","properties":{"maxSlotsOffered":{"type":"number","description":"Times offered per message (1-5).","minimum":1,"maximum":5},"changeCutoffHours":{"type":"number","description":"Hours before a visit inside which the customer cannot change it by message (0-168).","minimum":0,"maximum":168},"routingFormId":{"type":"string","nullable":true,"description":"Stored for the qualification step; `null` clears it.","format":"uuid"}}},"SkillSettingsDto":{"type":"object","properties":{"bookAppointment":{"$ref":"#/components/schemas/BookAppointmentSkillSettingsDto"},"startFollowUp":{"$ref":"#/components/schemas/StartFollowUpSkillSettingsDto"},"noReplyFollowUp":{"$ref":"#/components/schemas/NoReplyFollowUpSkillSettingsDto"},"createTask":{"$ref":"#/components/schemas/CreateTaskSkillSettingsDto"},"booking":{"$ref":"#/components/schemas/BookingRulesSkillSettingsDto"}}},"ToolConfigDto":{"type":"object","properties":{"retrievalEnabled":{"type":"boolean"},"retrievalTopK":{"type":"number","minimum":1,"maximum":50},"handover":{"$ref":"#/components/schemas/HandoverConfigDto"},"retrieval":{"$ref":"#/components/schemas/RetrievalSettingsDto"},"composioToolIds":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":200}},"skillSettings":{"$ref":"#/components/schemas/SkillSettingsDto"}}},"GoalChecklistItemDto":{"type":"object","properties":{"key":{"type":"string","maxLength":60},"label":{"type":"string","minLength":1,"maxLength":80}},"required":["label"]},"GoalConfigDto":{"type":"object","properties":{"presetKey":{"type":"string","enum":["BOOK_APPOINTMENTS","QUALIFY_LEADS","RESOLVE_SUPPORT","COLLECT_INFORMATION","COLLECT_REVIEWS","ANSWER_FAQS","TRACK_ORDERS","GENERATE_OPPORTUNITIES","FILL_QUESTIONNAIRE","CUSTOM"]},"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":2000},"completedWhen":{"type":"string","enum":["APPOINTMENT_BOOKED","SUPPORT_TICKET_RESOLVED","LEAD_QUALIFIED","INFORMATION_COLLECTED","WORKFLOW_COMPLETED","CUSTOMER_CONFIRMED","HUMAN_MARKED_COMPLETE","CUSTOM_EVENT","LINK_CLICKED"]},"failureConditions":{"type":"array","items":{"type":"string","enum":["CUSTOMER_OPT_OUT","CONVERSATION_CLOSED","MAX_ATTEMPTS","NO_RESPONSE","CUSTOMER_REQUESTED_HUMAN"]}},"onFailure":{"type":"string","enum":["ASK_HUMAN","CREATE_TASK","NOTIFY_TEAM","CLOSE_CONVERSATION","RETRY_LATER"]},"maxAttempts":{"type":"number","minimum":1,"maximum":50},"retryAfterHours":{"type":"number","description":"RETRY_LATER only: how long to wait before following up (default 48).","minimum":1,"maximum":720},"settings":{"type":"object","description":"What the owner told the goal: the review link, the questions, the details\nto collect, a Custom goal's prompt. Its shape depends on `presetKey`, so\nonly \"an object\" is checked here; the service refuses anything that does\nnot fit the goal (`validateGoalSettings`) before it is stored."},"checklistItems":{"maxItems":8,"type":"array","items":{"$ref":"#/components/schemas/GoalChecklistItemDto"}}},"required":["presetKey","name","completedWhen","failureConditions","onFailure"]},"HumanHelpActionsDto":{"type":"object","properties":{"assigneeUserIds":{"description":"The teammates a handover goes to, taking turns. Replaces the single `assignToUserId`.","type":"array","items":{"type":"string","format":"uuid"}},"assignToUserId":{"type":"string","description":"The single assignee older clients still send. Read as a one-person list; a\nsave that brings `assigneeUserIds` drops it from the stored config.","format":"uuid"},"leaveSummary":{"type":"boolean"},"notifyTeam":{"type":"boolean"}}},"OutOfServiceAreaDto":{"type":"object","properties":{"tone":{"type":"string","enum":["CUSTOM","EXPLICIT","SOFT"]},"text":{"type":"string","maxLength":500}},"required":["tone"]},"HumanHelpConfigDto":{"type":"object","properties":{"presetTriggers":{"type":"array","items":{"type":"string","enum":["CUSTOMER_ASKS_HUMAN","CUSTOMER_REQUESTS_MANAGER","REPEATED_MISUNDERSTANDING","SENSITIVE_QUESTION","LEGAL_REQUEST","MEDICAL_REQUEST","EMERGENCY_REQUEST","OUT_OF_SERVICE_AREA","BOOKING_NEEDS_PERSON","REFUND_REQUEST","NEGATIVE_SENTIMENT","AI_NOT_CONFIDENT","PAYMENT_ISSUE","PRICING_EXCEPTION"]}},"actions":{"$ref":"#/components/schemas/HumanHelpActionsDto"},"outOfServiceArea":{"$ref":"#/components/schemas/OutOfServiceAreaDto"}}},"ScenarioDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","maxLength":80},"useWhen":{"type":"string","maxLength":300},"response":{"type":"string","maxLength":1000}},"required":["id","name","useWhen","response"]},"MessageVariantDto":{"type":"object","properties":{"text":{"type":"string","maxLength":1600},"mediaUrls":{"type":"array","items":{"type":"string"}}},"required":["text"]},"WhatsAppTemplateVariantDto":{"type":"object","properties":{"templateId":{"type":"string","format":"uuid"},"text":{"type":"string","maxLength":1600}},"required":["templateId"]},"OutboundEmailVariantDto":{"type":"object","properties":{"text":{"type":"string","maxLength":5000},"subject":{"type":"string","maxLength":200},"mediaUrls":{"type":"array","items":{"type":"string"}},"html":{"type":"string","maxLength":200000},"previewText":{"type":"string","maxLength":255},"format":{"type":"string","enum":["PLAIN","DESIGNED"]},"emailTemplateId":{"type":"string","format":"uuid"}}},"OutboundVariantsDto":{"type":"object","properties":{"default":{"$ref":"#/components/schemas/MessageVariantDto"},"SMS":{"$ref":"#/components/schemas/MessageVariantDto"},"WHATSAPP":{"$ref":"#/components/schemas/WhatsAppTemplateVariantDto"},"EMAIL":{"$ref":"#/components/schemas/OutboundEmailVariantDto"}}},"OutboundFirstMessageDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"variants":{"$ref":"#/components/schemas/OutboundVariantsDto"}},"required":["enabled","variants"]},"EmailVariantDto":{"type":"object","properties":{"text":{"type":"string","maxLength":5000},"subject":{"type":"string","maxLength":200},"mediaUrls":{"type":"array","items":{"type":"string"}}},"required":["text"]},"InboundVariantsDto":{"type":"object","properties":{"default":{"$ref":"#/components/schemas/MessageVariantDto"},"SMS":{"$ref":"#/components/schemas/MessageVariantDto"},"WHATSAPP":{"$ref":"#/components/schemas/MessageVariantDto"},"EMAIL":{"$ref":"#/components/schemas/EmailVariantDto"}}},"InboundFirstMessageDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"variants":{"$ref":"#/components/schemas/InboundVariantsDto"}},"required":["enabled","variants"]},"FirstMessageDto":{"type":"object","properties":{"outbound":{"$ref":"#/components/schemas/OutboundFirstMessageDto"},"inbound":{"$ref":"#/components/schemas/InboundFirstMessageDto"}},"required":["outbound","inbound"]},"ReplyScheduleDto":{"type":"object","properties":{"pauseDuringBusinessHours":{"type":"boolean"},"hours":{"type":"string","enum":["ORG","CUSTOM"]},"weekly":{"$ref":"#/components/schemas/BusinessHoursWeeklyDto"}},"required":["pauseDuringBusinessHours","hours"]},"FollowUpDelayDto":{"type":"object","properties":{"value":{"type":"number","minimum":1},"unit":{"type":"string","enum":["MINUTES","HOURS","DAYS"]}},"required":["value","unit"]},"FollowUpStepDto":{"type":"object","properties":{"id":{"type":"string","maxLength":64},"delay":{"$ref":"#/components/schemas/FollowUpDelayDto"},"channel":{"type":"string","enum":["SAME","SMS","WHATSAPP","EMAIL"]},"type":{"type":"string","enum":["AI","EXACT","TEMPLATE"]},"aiHint":{"type":"string","maxLength":300},"text":{"type":"string","maxLength":1600},"subject":{"type":"string","maxLength":200},"mediaUrls":{"type":"array","items":{"type":"string"}},"ifWindowClosed":{"type":"string","enum":["SKIP","TEMPLATE"]},"fallbackTemplateId":{"type":"string","format":"uuid"},"whatsappTemplateId":{"type":"string","format":"uuid"},"html":{"type":"string","maxLength":200000},"previewText":{"type":"string","maxLength":255},"format":{"type":"string","enum":["PLAIN","DESIGNED"]},"emailTemplateId":{"type":"string","format":"uuid"}},"required":["id","delay","channel","type"]},"FollowUpStopWhenDto":{"type":"object","properties":{"booked":{"type":"boolean"},"conversationClosed":{"type":"boolean"},"tagIds":{"type":"array","items":{"type":"string","format":"uuid"}},"opportunityStageIds":{"type":"array","items":{"type":"string","format":"uuid"}},"phrases":{"type":"array","items":{"type":"string","maxLength":100}}},"required":["booked","conversationClosed","tagIds","opportunityStageIds","phrases"]},"FollowUpsDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"templateKey":{"type":"string","maxLength":40},"steps":{"type":"array","items":{"$ref":"#/components/schemas/FollowUpStepDto"}},"stopWhen":{"$ref":"#/components/schemas/FollowUpStopWhenDto"}},"required":["enabled","steps","stopWhen"]},"KnowledgeFaqDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"question":{"type":"string","maxLength":300},"answer":{"type":"string","maxLength":1000}},"required":["id","question","answer"]},"CreateAgentDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"kind":{"type":"string","description":"CHAT (conversations) or VOICE (the phone) — chosen at hire time, never changed. Default CHAT.","enum":["VOICE","CHAT"]},"provider":{"type":"string","enum":["OPENAI","GEMINI","OPENROUTER"]},"modelId":{"type":"string","minLength":1,"maxLength":120},"fallbackChain":{"description":"Ordered LiteLLM model names the proxy executes on retryable errors.","type":"array","items":{"type":"string","maxLength":120}},"generationParams":{"$ref":"#/components/schemas/GenerationParamsDto"},"guardrails":{"$ref":"#/components/schemas/GuardrailsDto"},"persona":{"description":"Persona persisted on the dedicated `ai_agents.persona` column.","allOf":[{"$ref":"#/components/schemas/PersonaDto"}]},"toolConfig":{"$ref":"#/components/schemas/ToolConfigDto"},"knowledgeBaseIds":{"description":"Knowledge bases attached to this agent (real join rows, §2.5).","maxItems":50,"type":"array","items":{"type":"string","format":"uuid"}},"jobTitle":{"type":"string","nullable":true,"maxLength":120},"avatarKey":{"type":"string","description":"Ignored: a new employee's avatar follows its kind. Still accepted, so older clients validate.","maxLength":60},"description":{"type":"string","nullable":true,"maxLength":2000},"language":{"type":"string","maxLength":20},"timezone":{"type":"string","nullable":true,"maxLength":60},"communicationStyle":{"type":"string","enum":["FRIENDLY","PROFESSIONAL","FORMAL","CASUAL"]},"brandVoice":{"type":"string","maxLength":2000},"templateKey":{"type":"string","description":"The employee's TYPE — one of the job-template catalogue keys (`JOB_TEMPLATE_KEYS`).","enum":["receptionist","sales_representative","lead_qualification","customer_support","follow_up_specialist","appointment_scheduler","marketing_assistant","collections_officer","faq_assistant","review_collector","lead_responder","custom"]},"setupStep":{"type":"string","description":"The hiring-wizard step the new draft opens on — where \"Finish setup\" resumes.","enum":["type","role","profile","goal","calendar","appointments","channels","knowledge","skills","humanHelp","voiceGreeting","callHandling","phoneNumber","journeys","test","review","basics","instructions","followUps","services","callForwarding","advanced"]},"setupVersion":{"type":"number","description":"Which setup hires it (`AI_EMPLOYEE_SETUP_VERSIONS`): the v2 wizard sends 2; absent means 1.","enum":[1,2]},"goalConfig":{"description":"`GoalConfig` (§4.2) — woven into the composed system prompt.","allOf":[{"$ref":"#/components/schemas/GoalConfigDto"}]},"skills":{"description":"Enabled skill keys — validated against the code-defined skill registry.","maxItems":30,"type":"array","items":{"type":"string"}},"humanHelpConfig":{"description":"`HumanHelpConfig` (§4.3) — preset triggers + post-handover actions.","allOf":[{"$ref":"#/components/schemas/HumanHelpConfigDto"}]},"instructions":{"type":"string","nullable":true,"description":"The owner's script (Instructions → Script). `{{agent_name}}` and\n`{{business_name}}` are filled in when the prompt is built.","maxLength":8000},"scenarios":{"description":"\"When this happens, do that\" (Instructions → Scenarios).","type":"array","items":{"$ref":"#/components/schemas/ScenarioDto"}},"firstMessage":{"description":"Who speaks first (Instructions → First message): the message new leads\nget, and the greeting for customers who write first. Saved whole, both\nsides; never null.","allOf":[{"$ref":"#/components/schemas/FirstMessageDto"}]},"replySchedule":{"description":"Pause auto-reply during business hours (Advanced). Saved whole; never null.\nTurning it off is `pauseDuringBusinessHours: false`.","allOf":[{"$ref":"#/components/schemas/ReplyScheduleDto"}]},"followUps":{"description":"Follow-ups: what the employee sends when a customer goes quiet, and what ends\nthe sequence. Saved whole; never null. Turning them off is `enabled: false`.","allOf":[{"$ref":"#/components/schemas/FollowUpsDto"}]},"knowledgeGeneral":{"type":"string","nullable":true,"description":"What the employee knows about the business (Knowledge → General): rich\ntext, sanitized before it is stored. `null` clears it.","maxLength":60000},"knowledgeFaqs":{"description":"Common questions and their answers (Knowledge → FAQ). Saved whole.","type":"array","items":{"$ref":"#/components/schemas/KnowledgeFaqDto"}}},"required":["name"]},"EmployeeAssistDto":{"type":"object","properties":{"action":{"type":"string","enum":["DRAFT_GOAL","DRAFT_SCRIPT","IMPROVE_TEXT","DRAFT_FIRST_MESSAGE","DRAFT_FOLLOW_UP_EMAIL","SUGGEST_SCENARIOS","DRAFT_KNOWLEDGE","SUGGEST_FAQS"]},"employeeId":{"type":"string","description":"The employee being set up, when it exists yet; read within the workspace only.","format":"uuid"},"goalName":{"type":"string","maxLength":120},"text":{"type":"string","description":"What the field holds now — notes to draft from, or text to make clearer."},"channel":{"type":"string","description":"The channel a first message is for; absent reads as a text message.","enum":["SMS","WHATSAPP","EMAIL","VOICE"]},"instruction":{"type":"string","description":"Anything the owner typed in the Ask AI box.","maxLength":500},"existingQuestions":{"description":"The questions already in the FAQ, so Ask AI does not suggest them again.","type":"array","items":{"type":"string","maxLength":300}}},"required":["action"]},"SetDefaultAssignmentDto":{"type":"object","properties":{"agentId":{"type":"string","nullable":true,"format":"uuid"}},"required":["agentId"]},"SetChannelAssignmentDto":{"type":"object","properties":{"agentId":{"type":"string","nullable":true,"format":"uuid"},"expectedHolderId":{"type":"string","nullable":true,"format":"uuid"}},"required":["agentId"]},"UpdateAgentDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"kind":{"type":"string","description":"Accepted only so a full-payload PATCH round-trips: the kind is fixed at\ncreate, and `AiAgentService.update` refuses a different value\n(`AI_AGENT_KIND_IMMUTABLE`).","enum":["VOICE","CHAT"]},"provider":{"type":"string","enum":["OPENAI","GEMINI","OPENROUTER"]},"modelId":{"type":"string","minLength":1,"maxLength":120},"fallbackChain":{"type":"array","items":{"type":"string","maxLength":120}},"generationParams":{"$ref":"#/components/schemas/GenerationParamsDto"},"guardrails":{"$ref":"#/components/schemas/GuardrailsDto"},"persona":{"description":"Persona persisted on the dedicated `ai_agents.persona` column.","allOf":[{"$ref":"#/components/schemas/PersonaDto"}]},"toolConfig":{"$ref":"#/components/schemas/ToolConfigDto"},"knowledgeBaseIds":{"description":"Replaces the agent's attached knowledge bases when present (§2.5).","maxItems":50,"type":"array","items":{"type":"string","format":"uuid"}},"jobTitle":{"type":"string","nullable":true,"maxLength":120},"avatarKey":{"type":"string","maxLength":60},"description":{"type":"string","nullable":true,"maxLength":2000},"language":{"type":"string","maxLength":20},"timezone":{"type":"string","nullable":true,"maxLength":60},"communicationStyle":{"type":"string","enum":["FRIENDLY","PROFESSIONAL","FORMAL","CASUAL"]},"brandVoice":{"type":"string","maxLength":2000},"templateKey":{"type":"string","description":"The employee's TYPE. Any short string here — the wizard sends the row's\ncurrent key back on every PATCH, and rows written before the catalogue\nwas enforced may hold a key it no longer lists. `AiAgentService.update`\nchecks the catalogue only when the value changes.","maxLength":60},"goalConfig":{"description":"`GoalConfig` (§4.2) — woven into the composed system prompt.","allOf":[{"$ref":"#/components/schemas/GoalConfigDto"}]},"skills":{"description":"Enabled skill keys — validated against the code-defined skill registry.","maxItems":30,"type":"array","items":{"type":"string"}},"humanHelpConfig":{"description":"`HumanHelpConfig` (§4.3) — preset triggers + post-handover actions.","allOf":[{"$ref":"#/components/schemas/HumanHelpConfigDto"}]},"instructions":{"type":"string","nullable":true,"description":"The owner's script (Instructions → Script). `{{agent_name}}` and\n`{{business_name}}` are filled in when the prompt is built.","maxLength":8000},"scenarios":{"description":"\"When this happens, do that\" (Instructions → Scenarios).","type":"array","items":{"$ref":"#/components/schemas/ScenarioDto"}},"firstMessage":{"description":"Who speaks first (Instructions → First message): the message new leads\nget, and the greeting for customers who write first. Saved whole, both\nsides; never null.","allOf":[{"$ref":"#/components/schemas/FirstMessageDto"}]},"replySchedule":{"description":"Pause auto-reply during business hours (Advanced). Saved whole; never null.\nTurning it off is `pauseDuringBusinessHours: false`.","allOf":[{"$ref":"#/components/schemas/ReplyScheduleDto"}]},"followUps":{"description":"Follow-ups: what the employee sends when a customer goes quiet, and what ends\nthe sequence. Saved whole; never null. Turning them off is `enabled: false`.","allOf":[{"$ref":"#/components/schemas/FollowUpsDto"}]},"knowledgeGeneral":{"type":"string","nullable":true,"description":"What the employee knows about the business (Knowledge → General): rich\ntext, sanitized before it is stored. `null` clears it.","maxLength":60000},"knowledgeFaqs":{"description":"Common questions and their answers (Knowledge → FAQ). Saved whole.","type":"array","items":{"$ref":"#/components/schemas/KnowledgeFaqDto"}}}},"SetSetupStepDto":{"type":"object","properties":{"step":{"type":"string","enum":["type","role","profile","goal","calendar","appointments","channels","knowledge","skills","humanHelp","voiceGreeting","callHandling","phoneNumber","journeys","test","review","basics","instructions","followUps","services","callForwarding","advanced"]}},"required":["step"]},"JourneyChoicesDto":{"type":"object","properties":{"off":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":80}}},"required":["off"]},"ActivateAgentDto":{"type":"object","properties":{"journeyChoices":{"description":"Honoured only by the first-ever install: these recommended journeys are stored OFF, never published.","allOf":[{"$ref":"#/components/schemas/JourneyChoicesDto"}]},"setupVersion":{"type":"number","description":"Sent by the goal-first wizard: a DRAFT finished there is hired as this version. Only up to 2.","enum":[2]}}},"AdvancedRetrievalDto":{"type":"object","properties":{"retrievalTopK":{"type":"number","description":"Passages the `search_knowledge_base` tool may return per call.","minimum":1,"maximum":50},"minScore":{"type":"number","description":"Cosine floor below which a passage is not admitted at all.","minimum":0,"maximum":1},"includeCitations":{"type":"boolean","description":"Emit `[n]` markers and record citations on the run."}}},"AdvancedConfigDto":{"type":"object","properties":{"provider":{"type":"string","enum":["OPENAI","GEMINI","OPENROUTER"]},"modelId":{"type":"string","minLength":1,"maxLength":120},"fallbackChain":{"type":"array","items":{"type":"string","maxLength":120}},"generationParams":{"$ref":"#/components/schemas/GenerationParamsDto"},"guardrails":{"$ref":"#/components/schemas/GuardrailsDto"},"systemPrompt":{"type":"string","minLength":1,"maxLength":20000},"retrieval":{"$ref":"#/components/schemas/AdvancedRetrievalDto"},"promptOverride":{"type":"boolean"}}},"SyntheticTurnDto":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string","minLength":1,"maxLength":4000}},"required":["role","content"]},"TestChatDto":{"type":"object","properties":{"message":{"type":"string","minLength":1,"maxLength":4000},"syntheticHistory":{"maxItems":80,"type":"array","items":{"$ref":"#/components/schemas/SyntheticTurnDto"}}},"required":["message"]},"SetMessageFeedbackDto":{"type":"object","properties":{"verdict":{"type":"string","enum":["INCORRECT","HELPFUL"]},"note":{"type":"string","description":"Optional: what was wrong with it. Team-facing only.","maxLength":500}},"required":["verdict"]},"AssignAgentDto":{"type":"object","properties":{"agentId":{"type":"string","format":"uuid"}},"required":["agentId"]},"SetAutopilotDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"`true` → AI_ACTIVE (the agent replies automatically);\n`false` → AI_SUPERVISED (replies wait for human approval)."}},"required":["enabled"]},"DiscardPendingReplyDto":{"type":"object","properties":{"kind":{"type":"string","enum":["REJECTED","EDITED"]},"reason":{"type":"string","description":"Optional: what was wrong with it. Shown to nobody but the team.","maxLength":280}},"required":["kind"]},"CreateHandoverRuleDto":{"type":"object","properties":{"matchType":{"type":"string","enum":["SEMANTIC","EXACT","CONTAINS"]},"phrase":{"type":"string","minLength":1,"maxLength":1000},"agentId":{"type":"string","description":"Org-wide when omitted; an agent id scopes the rule to one agent.","format":"uuid"},"threshold":{"type":"number","description":"SEMANTIC cosine threshold in [0, 1]; service default 0.82 when omitted.","minimum":0,"maximum":1},"enabled":{"type":"boolean","description":"Rules are enabled by default; pass `false` to create a disabled rule."}},"required":["matchType","phrase"]},"UpdateHandoverRuleDto":{"type":"object","properties":{"matchType":{"type":"string","enum":["SEMANTIC","EXACT","CONTAINS"]},"phrase":{"type":"string","minLength":1,"maxLength":1000},"threshold":{"type":"number","minimum":0,"maximum":1},"enabled":{"type":"boolean"}}},"ChunkingConfigDto":{"type":"object","properties":{"strategy":{"type":"string","maxLength":64},"chunkSize":{"type":"number","minimum":64,"maximum":2048},"chunkOverlap":{"type":"number","minimum":0,"maximum":512}}},"CreateKnowledgeBaseDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":2000},"embeddingModel":{"type":"string","maxLength":100},"embeddingProvider":{"type":"string","maxLength":50},"embeddingDims":{"type":"number","minimum":1},"chunkingConfig":{"$ref":"#/components/schemas/ChunkingConfigDto"}},"required":["name"]},"SearchPreviewDto":{"type":"object","properties":{"queryText":{"type":"string","maxLength":2000},"topK":{"type":"number","description":"Passages to return. Defaults to the agent runtime's own top-K.","default":8,"minimum":1,"maximum":50},"minScore":{"type":"number","description":"Cosine floor. Defaults to the configured retrieval floor, so the preview\nshows what an employee would actually see. Pass `0` to inspect what the\nfloor is excluding.","minimum":0,"maximum":1},"expandNeighbours":{"type":"number","description":"Neighbour radius. Defaults to the runtime default; pass `0` to see the raw\nranking, which is what you want when judging whether a chunk scores well\nrather than whether the stitched passage reads well.","minimum":0,"maximum":3}},"required":["queryText"]},"UpdateKnowledgeBaseDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":2000},"embeddingModel":{"type":"string","maxLength":100},"embeddingProvider":{"type":"string","maxLength":50},"embeddingDims":{"type":"number","minimum":1},"isOrgDefault":{"type":"boolean","description":"`true` makes this the org's shared knowledge (the previous one is cleared)."},"chunkingConfig":{"$ref":"#/components/schemas/ChunkingConfigDto"}}},"GetSourceUploadUrlDto":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":512},"mime":{"type":"string","minLength":1,"maxLength":255},"sizeBytes":{"type":"number","description":"Declared upload size. Optional, and deliberately so: `ValidationPipe` runs\nwith `forbidNonWhitelisted`, so making this required would 400 every\nrequest from a client that omits it — including a cached frontend bundle\nmid-deploy. It is a courtesy that saves a doomed upload its bandwidth, not\nan enforcement point; a client can lie or omit it freely. The size that\nactually decides anything is read from object storage — at registration\n(`KbSourceService.createFileSource`) and again, authoritatively, before\nthe worker transfers a byte (`FileSourceLoader`).","minimum":1,"maximum":20971520}},"required":["filename","mime"]},"CreateFileSourceDto":{"type":"object","properties":{"storageKey":{"type":"string","minLength":1,"maxLength":1024},"title":{"type":"string","minLength":1,"maxLength":150},"mime":{"type":"string","minLength":1,"maxLength":255},"chunkingConfig":{"description":"Optional per-source chunking override (falls back to the KB config).","allOf":[{"$ref":"#/components/schemas/ChunkingConfigDto"}]}},"required":["storageKey","title","mime"]},"CreateTextSourceDto":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":150},"content":{"type":"string","minLength":1,"maxLength":1048576},"chunkingConfig":{"description":"Optional per-source chunking override (falls back to the KB config).","allOf":[{"$ref":"#/components/schemas/ChunkingConfigDto"}]}},"required":["title","content"]},"CreateWebsiteSourceDto":{"type":"object","properties":{"rootUrl":{"type":"string","maxLength":2048,"format":"uri"},"title":{"type":"string","maxLength":150},"maxPages":{"type":"number","minimum":1,"maximum":200},"crawlDepth":{"type":"number","minimum":0,"maximum":5},"includePaths":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":1024}},"excludePaths":{"maxItems":50,"type":"array","items":{"type":"string","maxLength":1024}},"chunkingConfig":{"description":"Optional per-source chunking override (falls back to the KB config).","allOf":[{"$ref":"#/components/schemas/ChunkingConfigDto"}]}},"required":["rootUrl"]},"UpdateKbSourceDto":{"type":"object","properties":{"title":{"type":"string","description":"Applies to every type, and never triggers a re-ingest on its own.","minLength":1,"maxLength":150},"content":{"type":"string","description":"TEXT only. Same 1 MB ceiling as `CreateTextSourceDto`.","minLength":1,"maxLength":1048576},"rootUrl":{"type":"string","description":"WEBSITE only.","maxLength":2048,"format":"uri"},"maxPages":{"type":"number","description":"WEBSITE only.","minimum":1,"maximum":200},"crawlDepth":{"type":"number","description":"WEBSITE only.","minimum":0,"maximum":5},"includePaths":{"description":"WEBSITE only.","maxItems":50,"type":"array","items":{"type":"string","maxLength":1024}},"excludePaths":{"description":"WEBSITE only.","maxItems":50,"type":"array","items":{"type":"string","maxLength":1024}}}},"UnifiedConversationContactWhatsAppDto":{"type":"object","properties":{"optIn":{"type":"boolean","nullable":true},"windowState":{"type":"string","enum":["none","open","expired"]},"lastInboundAt":{"format":"date-time","type":"string","nullable":true}},"required":["optIn","windowState","lastInboundAt"]},"UnifiedConversationContactDto":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","nullable":true},"avatarBgColor":{"type":"string","nullable":true},"isOptedOut":{"type":"boolean"},"isDeleted":{"type":"boolean"},"stage":{"type":"string","description":"Sales stage — shipped on list and detail so the inbox rail can filter on it.","enum":["ARCHIVED","NEW_LEAD","ENGAGED","QUALIFIED","APPOINTMENT_BOOKED","CUSTOMER","LOST","BOOKING_PENDING","ESTIMATE_GIVEN","DECIDING","NOT_QUALIFIED"]},"status":{"type":"string","enum":["ACTIVE","INVALID","ARCHIVED"]},"whatsapp":{"$ref":"#/components/schemas/UnifiedConversationContactWhatsAppDto"}},"required":["id","firstName","lastName","phone","email","avatarBgColor","isOptedOut","isDeleted","stage"]},"UnifiedConversationAiStateDto":{"type":"object","properties":{"agentId":{"type":"string","nullable":true},"state":{"type":"string","enum":["AI_SUSPENDED","AI_ACTIVE","HANDOVER_PENDING","HUMAN_CONTROLLED","AI_SUPERVISED"]}},"required":["agentId","state"]},"UnifiedConversationListItemDto":{"type":"object","properties":{"contact":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UnifiedConversationContactDto"}]},"aiState":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UnifiedConversationAiStateDto"}]},"lastMessageSubject":{"type":"string","nullable":true,"description":"Subject of the email in `lastMessageId`, resolved on read from the 1:1\n`EmailMessageDetail` row so the list can render \"Subject — preview\" the way\nan email client does. `null` on every non-EMAIL row."},"isSample":{"type":"boolean","description":"True for a thread from the removable sample dataset."},"isMuted":{"type":"boolean","description":"Whether the REQUESTING user has muted this conversation. Per user — a\nteammate's mute never shows here. Not carried by WS payloads or the sync\ndelta; the client keeps its cached value across those merges."},"id":{"type":"string"},"organizationId":{"type":"string"},"contactId":{"type":"string","nullable":true},"isOpen":{"type":"boolean"},"isArchived":{"type":"boolean"},"isPinned":{"type":"boolean"},"pinnedAt":{"format":"date-time","type":"string","nullable":true},"priority":{"type":"string","enum":["LOW","NORMAL","HIGH","URGENT"]},"status":{"type":"string","enum":["OPEN","PENDING","CLOSED","SNOOZED","SPAM","TRASH"]},"assignedTo":{"type":"string","nullable":true},"assignedAt":{"format":"date-time","type":"string","nullable":true},"unreadCount":{"type":"number"},"lastMessageAt":{"format":"date-time","type":"string","nullable":true},"lastMessagePreview":{"type":"string","nullable":true},"lastMessageDirection":{"type":"string","nullable":true,"enum":["OUTBOUND","INBOUND"]},"lastMessageChannel":{"type":"string","nullable":true,"enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"lastMessageId":{"type":"string","nullable":true},"lastCallOutcome":{"type":"string","nullable":true,"description":"Outcome of the last call — lets the list colour a row by what happened\nrather than re-deriving it from the preview text. Only meaningful while\n`lastMessageChannel` is VOICE; null for every other channel and for rows\nlast touched before this field existed.","enum":["MISSED","VOICEMAIL","COMPLETED_INBOUND","COMPLETED_OUTBOUND","NO_ANSWER"]},"closedAt":{"format":"date-time","type":"string","nullable":true},"snoozedUntil":{"format":"date-time","type":"string","nullable":true,"description":"When a SNOOZED conversation wakes back to OPEN, and who snoozed it. Only\nmeaningful while `status` is SNOOZED; null otherwise, and on conversations\nsnoozed before wake times existed."},"snoozedById":{"type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["contact","aiState","lastMessageSubject","isSample","isMuted","id","organizationId","contactId","isOpen","isArchived","isPinned","pinnedAt","priority","status","assignedTo","assignedAt","unreadCount","lastMessageAt","lastMessagePreview","lastMessageDirection","lastMessageChannel","lastMessageId","lastCallOutcome","closedAt","snoozedUntil","snoozedById","createdAt","updatedAt"]},"UnifiedConversationListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/UnifiedConversationListItemDto"}},"nextCursor":{"type":"string","nullable":true}},"required":["data","nextCursor"]},"UnifiedByContactResponseDto":{"type":"object","properties":{"unifiedConversationId":{"type":"string","nullable":true}},"required":["unifiedConversationId"]},"ResolveUnifiedConversationDto":{"type":"object","properties":{"contactId":{"type":"string","format":"uuid"},"channel":{"description":"Optional fail-fast hint. SMS/WHATSAPP composes pass their channel so a\ncontact without a phone is rejected BEFORE any row is created; EMAIL\nneeds no pre-check (recipients are explicit `toEmails` on the send).","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"],"type":"string"}},"required":["contactId"]},"ResolveUnifiedResponseDto":{"type":"object","properties":{"id":{"type":"string"},"created":{"type":"boolean"}},"required":["id","created"]},"ConversationChannelDto":{"type":"object","properties":{"provider":{"type":"string","nullable":true,"description":"Null for an internal channel that isn't fronted by a provider.","enum":["WEBCHAT","TWILIO","TELNYX","SENDGRID","META","RESEND","AWS_SES","GOOGLE_RCS"]},"name":{"type":"string"}},"required":["provider","name"]},"ConversationChannelIdentityDto":{"type":"object","properties":{"identity":{"type":"string","description":"E.164 number for SMS/WhatsApp/Voice; an address for Email."},"displayName":{"type":"string","nullable":true},"channel":{"$ref":"#/components/schemas/ConversationChannelDto"}},"required":["identity","displayName","channel"]},"ConversationDetailDto":{"type":"object","properties":{"channelIdentity":{"$ref":"#/components/schemas/ConversationChannelIdentityDto"},"id":{"type":"string"},"organizationId":{"type":"string"},"unifiedConversationId":{"type":"string"},"contactId":{"type":"string","nullable":true},"channelIdentityId":{"type":"string"},"channel":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"unreadCount":{"type":"number"},"lastMessageAt":{"format":"date-time","type":"string","nullable":true},"lastMessagePreview":{"type":"string","nullable":true},"lastMessageDirection":{"type":"string","nullable":true,"enum":["OUTBOUND","INBOUND"]},"lastMessageId":{"type":"string","nullable":true},"isOpen":{"type":"boolean"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["channelIdentity","id","organizationId","unifiedConversationId","contactId","channelIdentityId","channel","unreadCount","lastMessageAt","lastMessagePreview","lastMessageDirection","lastMessageId","isOpen","createdAt","updatedAt"]},"ConversationNoteAuthorDto":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"}},"required":["id","firstName","lastName","email"]},"NoteAttachmentDto":{"type":"object","properties":{"id":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"sizeBytes":{"type":"number"}},"required":["id","filename","mimeType","sizeBytes"]},"MentionedUserDto":{"type":"object","properties":{"userId":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"type":"string"}},"required":["userId","firstName","lastName","email"]},"ConversationNoteDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"unifiedConversationId":{"type":"string"},"authorId":{"type":"string","nullable":true,"description":"`null` for AI-authored notes — see `authorAgentId`."},"authorAgentId":{"type":"string","nullable":true,"description":"The authoring AI employee for AI-authored notes (`null` for human ones).\nMutually exclusive with `authorId`; the client resolves the employee's\nname + avatar from this id."},"systemAuthor":{"type":"string","nullable":true,"description":"The platform feature that wrote the note when neither a person nor an AI\nemployee did (e.g. \"AI Phone Answering\" for a message taken on a call with\nno employee linked); `null` otherwise. Exactly one of the three authors\nis set (DB CHECK)."},"body":{"type":"string"},"bodyFormat":{"description":"How to render `body`: `PLAIN` is literal text (the historical shape and\nthe default), `HTML` is sanitized rich text from the shared composer.","enum":["PLAIN","HTML"],"type":"string"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"author":{"nullable":true,"description":"`null` for AI-authored notes (no human author to hydrate).","type":"object","allOf":[{"$ref":"#/components/schemas/ConversationNoteAuthorDto"}]},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/NoteAttachmentDto"}},"mentions":{"description":"Teammates @-mentioned in the body (resolved server-side).","type":"array","items":{"$ref":"#/components/schemas/MentionedUserDto"}},"clientNoteId":{"type":"string","description":"Echoed client correlation id (present only on the create response)."}},"required":["id","organizationId","unifiedConversationId","authorId","authorAgentId","systemAuthor","body","bodyFormat","createdAt","updatedAt","author","attachments","mentions"]},"UnifiedConversationDetailDto":{"type":"object","properties":{"contact":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UnifiedConversationContactDto"}]},"aiState":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UnifiedConversationAiStateDto"}]},"lastMessageSubject":{"type":"string","nullable":true,"description":"Subject of the email in `lastMessageId`, resolved on read from the 1:1\n`EmailMessageDetail` row so the list can render \"Subject — preview\" the way\nan email client does. `null` on every non-EMAIL row."},"isSample":{"type":"boolean","description":"True for a thread from the removable sample dataset."},"isMuted":{"type":"boolean","description":"Whether the REQUESTING user has muted this conversation. Per user — a\nteammate's mute never shows here. Not carried by WS payloads or the sync\ndelta; the client keeps its cached value across those merges."},"id":{"type":"string"},"organizationId":{"type":"string"},"contactId":{"type":"string","nullable":true},"isOpen":{"type":"boolean"},"isArchived":{"type":"boolean"},"isPinned":{"type":"boolean"},"pinnedAt":{"format":"date-time","type":"string","nullable":true},"priority":{"enum":["LOW","NORMAL","HIGH","URGENT"],"type":"string"},"status":{"enum":["OPEN","PENDING","CLOSED","SNOOZED","SPAM","TRASH"],"type":"string"},"assignedTo":{"type":"string","nullable":true},"assignedAt":{"format":"date-time","type":"string","nullable":true},"unreadCount":{"type":"number"},"lastMessageAt":{"format":"date-time","type":"string","nullable":true},"lastMessagePreview":{"type":"string","nullable":true},"lastMessageDirection":{"nullable":true,"enum":["OUTBOUND","INBOUND"],"type":"string"},"lastMessageChannel":{"nullable":true,"enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"],"type":"string"},"lastMessageId":{"type":"string","nullable":true},"lastCallOutcome":{"nullable":true,"description":"Outcome of the last call — lets the list colour a row by what happened\nrather than re-deriving it from the preview text. Only meaningful while\n`lastMessageChannel` is VOICE; null for every other channel and for rows\nlast touched before this field existed.","enum":["MISSED","VOICEMAIL","COMPLETED_INBOUND","COMPLETED_OUTBOUND","NO_ANSWER"],"type":"string"},"closedAt":{"format":"date-time","type":"string","nullable":true},"snoozedUntil":{"format":"date-time","type":"string","nullable":true,"description":"When a SNOOZED conversation wakes back to OPEN, and who snoozed it. Only\nmeaningful while `status` is SNOOZED; null otherwise, and on conversations\nsnoozed before wake times existed."},"snoozedById":{"type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"conversations":{"type":"array","items":{"$ref":"#/components/schemas/ConversationDetailDto"}},"notes":{"type":"array","items":{"$ref":"#/components/schemas/ConversationNoteDto"}}},"required":["contact","aiState","lastMessageSubject","isSample","isMuted","id","organizationId","contactId","isOpen","isArchived","isPinned","pinnedAt","priority","status","assignedTo","assignedAt","unreadCount","lastMessageAt","lastMessagePreview","lastMessageDirection","lastMessageChannel","lastMessageId","lastCallOutcome","closedAt","snoozedUntil","snoozedById","createdAt","updatedAt","conversations","notes"]},"InboxMessageFollowUpDto":{"type":"object","properties":{"reason":{"type":"string","nullable":true,"description":"The AI follow-up's one-sentence reason; `null` for a fixed-text send."},"journeyName":{"type":"string","nullable":true},"employeeName":{"type":"string","nullable":true}},"required":["reason","journeyName","employeeName"]},"InboxMessageSenderDto":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"type":"string"}},"required":["id","firstName","lastName","email"]},"InboxMessageAttachmentDto":{"type":"object","properties":{"id":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"sizeBytes":{"type":"number"}},"required":["id","filename","mimeType","sizeBytes"]},"InboxAiRunApproverDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","description":"Already composed — the wire never carries raw name columns."}},"required":["id","name"]},"InboxMessageAiRunDto":{"type":"object","properties":{"id":{"type":"string"},"sendPolicy":{"type":"string","nullable":true,"enum":["DRAFT_FOR_APPROVAL","AUTO_SEND"]},"policySource":{"type":"string","nullable":true,"enum":["ORG_DEFAULT","CONVERSATION_OVERRIDE"]},"approvedBy":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/InboxAiRunApproverDto"}]},"approvedAt":{"format":"date-time","type":"string","nullable":true},"handoverReason":{"type":"string","nullable":true}},"required":["id","sendPolicy","policySource","approvedBy","approvedAt","handoverReason"]},"InboxMessageFeedbackDto":{"type":"object","properties":{"verdict":{"type":"string","enum":["INCORRECT","HELPFUL"]},"note":{"type":"string","nullable":true}},"required":["verdict","note"]},"InboxMessageReactionDto":{"type":"object","properties":{"reactorType":{"type":"string","enum":["CONTACT","AGENT"]},"emoji":{"type":"string"},"userId":{"type":"string","nullable":true,"description":"Teammate who set the AGENT slot; null on CONTACT rows."},"contactId":{"type":"string","nullable":true},"reactedAt":{"format":"date-time","type":"string"}},"required":["reactorType","emoji","userId","contactId","reactedAt"]},"InboxMessageQuoteDto":{"type":"object","properties":{"id":{"type":"string"},"body":{"type":"string"},"direction":{"type":"string","enum":["OUTBOUND","INBOUND"]},"contactId":{"type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"}},"required":["id","body","direction","contactId","createdAt"]},"InboxMessageLocationDto":{"type":"object","properties":{"latitude":{"type":"number"},"longitude":{"type":"number"},"name":{"type":"string","nullable":true},"address":{"type":"string","nullable":true},"url":{"type":"string","nullable":true}},"required":["latitude","longitude","name","address","url"]},"InboxMessageSharedContactPhoneDto":{"type":"object","properties":{"phone":{"type":"string"},"waId":{"type":"string","nullable":true,"description":"The number's WhatsApp id, when Meta knows it is on WhatsApp."},"type":{"type":"string","nullable":true}},"required":["phone","waId","type"]},"InboxMessageSharedContactEmailDto":{"type":"object","properties":{"email":{"type":"string"},"type":{"type":"string","nullable":true}},"required":["email","type"]},"InboxMessageSharedContactDto":{"type":"object","properties":{"name":{"type":"string"},"phones":{"type":"array","items":{"$ref":"#/components/schemas/InboxMessageSharedContactPhoneDto"}},"emails":{"type":"array","items":{"$ref":"#/components/schemas/InboxMessageSharedContactEmailDto"}},"organization":{"type":"string","nullable":true},"title":{"type":"string","nullable":true}},"required":["name","phones","emails","organization","title"]},"InboxMessageDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"channelIdentityId":{"type":"string"},"contactId":{"type":"string","nullable":true},"conversationId":{"type":"string","nullable":true},"emailThreadId":{"type":"string","nullable":true,"description":"Subject chain this email belongs to; `null` on every non-EMAIL row."},"fromPhone":{"type":"string","nullable":true,"description":"Nullable since Phase 3 — EMAIL rows carry addresses in the email fields below."},"toPhone":{"type":"string","nullable":true},"body":{"type":"string"},"mediaUrls":{"type":"array","items":{"type":"string"}},"mediaAttachments":{"description":"What each `mediaUrls` entry is, for the attachments we host. URLs we\ncannot resolve — provider-hosted inbound media — are absent, and the\nclient falls back to an unnamed chip for those.","type":"array","items":{"type":"object"}},"provider":{"type":"string","enum":["WEBCHAT","TWILIO","TELNYX","SENDGRID","META","RESEND","AWS_SES","GOOGLE_RCS"]},"providerMessageId":{"type":"string","nullable":true},"direction":{"type":"string","enum":["OUTBOUND","INBOUND"]},"channel":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"status":{"type":"string","enum":["QUEUED","SENDING","SENT","DELIVERED","UNDELIVERED","FAILED","REJECTED","SCHEDULED","CANCELLED"]},"clientMessageId":{"type":"string","nullable":true},"errorCode":{"type":"string","nullable":true},"errorMessage":{"type":"string","nullable":true},"segmentCount":{"type":"number","nullable":true},"source":{"type":"string","enum":["UNCLASSIFIED","OPT_OUT","POLL_RESPONSE","CAMPAIGN_REPLY","TEXT_LINK","GENERAL_INBOX","AI_AGENT","VOICE_CALL","JOIN_KEYWORD","AI_HANDOVER_NOTE","CONVERSATION_ASSIGNED","CONVERSATION_SNOOZED"]},"sourceId":{"type":"string","nullable":true},"origin":{"type":"string","description":"Who wrote it: a person, an AI employee's reply, or an automation.","enum":["HUMAN","AI_REPLY","AUTOMATION"]},"outboundMessageId":{"type":"string","nullable":true,"description":"AUTOMATION rows: the queued `outbound_messages` row this mirrors."},"followUp":{"nullable":true,"description":"AUTOMATION rows: who sent it and why; `null` otherwise.","type":"object","allOf":[{"$ref":"#/components/schemas/InboxMessageFollowUpDto"}]},"whatsappTemplateId":{"type":"string","nullable":true,"description":"WHATSAPP template sends only — the approved template this message was\nrendered from, so the thread can redraw its header media, offer strip,\nfooter, buttons and carousel. `body` carries the BODY component alone,\nwhich is everything a free-form message has and everything the thread\ncould show before this. `null` on every other message."},"receivedAt":{"format":"date-time","type":"string"},"sentAt":{"format":"date-time","type":"string","nullable":true},"deliveredAt":{"format":"date-time","type":"string","nullable":true},"failedAt":{"format":"date-time","type":"string","nullable":true},"scheduledAt":{"format":"date-time","type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"createdByUser":{"nullable":true,"description":"Sending teammate; `null` for inbound, AI and system-generated rows.","type":"object","allOf":[{"$ref":"#/components/schemas/InboxMessageSenderDto"}]},"subject":{"type":"string","nullable":true},"htmlBody":{"type":"string","nullable":true},"fromEmail":{"type":"string","nullable":true},"fromName":{"type":"string","nullable":true},"toEmails":{"type":"array","items":{"type":"string"}},"ccEmails":{"type":"array","items":{"type":"string"}},"bccEmails":{"type":"array","items":{"type":"string"}},"replyToEmail":{"type":"string","nullable":true,"description":"INBOUND only — the sender's own `Reply-To:`, or null. Our minted routing\n addresses are nulled out by the projection and never ride the wire."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/InboxMessageAttachmentDto"}},"aiRun":{"nullable":true,"description":"The AI run that produced this message; `null` for every human, inbound\nand system row. Resolved in one batched query per page — never one\nlookup per message.","type":"object","allOf":[{"$ref":"#/components/schemas/InboxMessageAiRunDto"}]},"myFeedback":{"nullable":true,"description":"This reader's verdict on this reply; `null` when they have not judged it,\non every non-AI row, and for an API-key caller. Resolved in the same\nbatched read as `aiRun` — one more query per page at most.","type":"object","allOf":[{"$ref":"#/components/schemas/InboxMessageFeedbackDto"}]},"reactions":{"type":"array","items":{"$ref":"#/components/schemas/InboxMessageReactionDto"}},"replyToMessageId":{"type":"string","nullable":true,"description":"WhatsApp quoted reply — the id, plus a preview so the bubble can render\n the quote without the original being in the loaded page."},"replyTo":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/InboxMessageQuoteDto"}]},"location":{"nullable":true,"description":"WhatsApp shared location, or null. `body` carries a readable fallback.","type":"object","allOf":[{"$ref":"#/components/schemas/InboxMessageLocationDto"}]},"sharedContacts":{"nullable":true,"description":"WhatsApp shared contact cards, or null. `body` carries a readable fallback.","type":"array","items":{"$ref":"#/components/schemas/InboxMessageSharedContactDto"}},"forwardState":{"type":"string","nullable":true,"description":"WhatsApp's \"Forwarded\" / \"Forwarded many times\" label; null otherwise.","enum":["FORWARDED","FREQUENTLY_FORWARDED"]},"isStarred":{"type":"boolean","description":"Whether the REQUESTING user has starred this message. Per user — set on\n thread reads only; sync deltas and realtime payloads omit it."}},"required":["id","organizationId","channelIdentityId","contactId","conversationId","emailThreadId","fromPhone","toPhone","body","mediaUrls","mediaAttachments","provider","providerMessageId","direction","channel","status","clientMessageId","errorCode","errorMessage","segmentCount","source","sourceId","origin","outboundMessageId","followUp","whatsappTemplateId","receivedAt","sentAt","deliveredAt","failedAt","scheduledAt","createdAt","updatedAt","createdByUser","subject","htmlBody","fromEmail","fromName","toEmails","ccEmails","bccEmails","replyToEmail","attachments","aiRun","myFeedback","reactions","replyToMessageId","replyTo","location","sharedContacts","forwardState"]},"MessageListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InboxMessageDto"}},"nextCursor":{"type":"string","nullable":true},"prevCursor":{"type":"string","nullable":true},"totalCount":{"type":"number","description":"Total messages in the thread matching `q`, for the \"3 of 17\" counter.\nSearch reads only — and only on the first page, since later pages already\nknow the total."}},"required":["data","nextCursor","prevCursor"]},"StarredMessageDto":{"type":"object","properties":{"id":{"type":"string"},"channel":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"direction":{"type":"string","enum":["OUTBOUND","INBOUND"]},"preview":{"type":"string","description":"Whitespace-collapsed, clipped body. Empty for a media-only message."},"hasMedia":{"type":"boolean"},"subject":{"type":"string","nullable":true,"description":"Email only — the subject line."},"emailThreadId":{"type":"string","nullable":true,"description":"Email only — the subject chain to open when jumping to the message."},"sentAt":{"format":"date-time","type":"string"},"starredAt":{"format":"date-time","type":"string"}},"required":["id","channel","direction","preview","hasMedia","subject","emailThreadId","sentAt","starredAt"]},"EmailThreadDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"conversationId":{"type":"string"},"subject":{"type":"string","nullable":true,"description":"Chain title — the first message's subject, `Re:`/`Fwd:` stripped."},"messageCount":{"type":"number"},"unreadCount":{"type":"number"},"lastMessageAt":{"format":"date-time","type":"string","nullable":true},"lastMessagePreview":{"type":"string","nullable":true},"lastMessageDirection":{"type":"string","nullable":true,"enum":["OUTBOUND","INBOUND"]},"lastMessageId":{"type":"string","nullable":true},"lastMessageStatus":{"type":"string","nullable":true,"description":"Delivery status of the message `lastMessageId` points at, so a collapsed\nthread row can show whether the last thing WE sent actually landed.\nMeaningful only when `lastMessageDirection === 'OUTBOUND'` — inbound\nmessages are persisted DELIVERED by definition.","enum":["QUEUED","SENDING","SENT","DELIVERED","UNDELIVERED","FAILED","REJECTED","SCHEDULED","CANCELLED"]},"hasAttachments":{"type":"boolean"},"lastMessageParticipants":{"description":"The people on the chain's NEWEST message — its From/To/Cc, deduped, with\nour own reply-routing addresses stripped and `bcc` excluded.\n\nScoped to that one message, never a union over the chain: a party who\ndropped off earlier will not appear. The name carries that limit so no\nclient presents it as the thread's full participant list. Empty when the\nthread's last message predates the 1:1 email-detail row.","type":"array","items":{"type":"string"}},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","organizationId","conversationId","subject","messageCount","unreadCount","lastMessageAt","lastMessagePreview","lastMessageDirection","lastMessageId","lastMessageStatus","hasAttachments","lastMessageParticipants","createdAt","updatedAt"]},"EmailThreadListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailThreadDto"}}},"required":["data"]},"StagedAttachmentDto":{"type":"object","properties":{"storageKey":{"type":"string","maxLength":512},"filename":{"type":"string","minLength":1,"maxLength":255},"mimeType":{"type":"string","minLength":1,"maxLength":150},"sizeBytes":{"type":"number","minimum":1},"contentId":{"type":"string","maxLength":255}},"required":["storageKey","filename","mimeType","sizeBytes"]},"SendMessageDto":{"type":"object","properties":{"body":{"type":"string","minLength":1},"clientMessageId":{"type":"string","format":"uuid"},"channel":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"channelIdentityId":{"type":"string","format":"uuid"},"whatsappTemplateId":{"type":"string","description":"WhatsApp template send (SP2 Task 8). When set on a `channel: 'WHATSAPP'`\nsend, the send service dispatches the referenced APPROVED template\ninstead of a free-form message — the one path Meta allows outside the\n24h customer-service window. Ignored for every other channel.","format":"uuid"},"mediaUrls":{"type":"array","items":{"type":"string"}},"mediaCaptions":{"type":"object","additionalProperties":{"type":"string"},"description":"WhatsApp per-attachment captions, keyed by the `mediaUrls` entry they\nbelong to. A WhatsApp send fans out into one Meta message per\nattachment, each carrying its own caption inside the media bubble —\nwhich is why this cannot be folded into `body`, the separate leading\nTEXT message. WHATSAPP-only; see the validator for the full contract."},"subject":{"type":"string","maxLength":998},"html":{"type":"string","minLength":1,"maxLength":500000},"toEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"ccEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"bccEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/StagedAttachmentDto"}},"signatureId":{"type":"string","format":"uuid"},"suppressSignature":{"type":"boolean"},"emailThreadId":{"type":"string","description":"Subject chain this reply belongs to. Omit for a brand-new email — the\nserver opens a chain for it. Supplying it is what keeps a reply on the\nchain the agent was reading rather than on the conversation's newest mail.","format":"uuid"},"inReplyToMessageId":{"type":"string","description":"The exact message being replied to, when a per-message Reply was used.\n\nEMAIL — narrows threading within the chain. Consumed by\n`EmailDraftsService`; the immediate-send composer still derives\n`In-Reply-To` from the chain's newest message, so this is inert on that\npath and always has been.\n\nWHATSAPP — becomes Meta's `context: { message_id: <wamid> }` on the\noutbound call, and is persisted as `Message.replyToMessageId` so our own\nthread renders the quote. The target must be a META/WHATSAPP message\nbelonging to the SAME contact and already carrying a wamid; the send\nservice validates all three and throws 98014 otherwise.\n\nNot forwarded by the scheduled-send path (`ScheduleMessageDto` inherits\nthe field, but the controller does not pass it through), so a scheduled\nWhatsApp reply sends without its quote.","format":"uuid"}},"required":["clientMessageId","channel"]},"SendMessageResponseDto":{"type":"object","properties":{"id":{"type":"string"},"replay":{"type":"boolean"},"status":{"enum":["QUEUED","SENDING","SENT","DELIVERED","UNDELIVERED","FAILED","REJECTED","SCHEDULED","CANCELLED"],"type":"string"},"body":{"type":"string"},"subject":{"type":"string","nullable":true}},"required":["id","replay"]},"ScheduleMessageDto":{"type":"object","properties":{"body":{"type":"string","minLength":1},"clientMessageId":{"type":"string","format":"uuid"},"channel":{"enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"],"type":"string"},"channelIdentityId":{"type":"string","format":"uuid"},"whatsappTemplateId":{"type":"string","description":"WhatsApp template send (SP2 Task 8). When set on a `channel: 'WHATSAPP'`\nsend, the send service dispatches the referenced APPROVED template\ninstead of a free-form message — the one path Meta allows outside the\n24h customer-service window. Ignored for every other channel.","format":"uuid"},"mediaUrls":{"type":"array","items":{"type":"string"}},"mediaCaptions":{"type":"object","additionalProperties":{"type":"string"},"description":"WhatsApp per-attachment captions, keyed by the `mediaUrls` entry they\nbelong to. A WhatsApp send fans out into one Meta message per\nattachment, each carrying its own caption inside the media bubble —\nwhich is why this cannot be folded into `body`, the separate leading\nTEXT message. WHATSAPP-only; see the validator for the full contract."},"subject":{"type":"string","maxLength":998},"html":{"type":"string","minLength":1,"maxLength":500000},"toEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"ccEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"bccEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/StagedAttachmentDto"}},"signatureId":{"type":"string","format":"uuid"},"suppressSignature":{"type":"boolean"},"emailThreadId":{"type":"string","description":"Subject chain this reply belongs to. Omit for a brand-new email — the\nserver opens a chain for it. Supplying it is what keeps a reply on the\nchain the agent was reading rather than on the conversation's newest mail.","format":"uuid"},"inReplyToMessageId":{"type":"string","description":"The exact message being replied to, when a per-message Reply was used.\n\nEMAIL — narrows threading within the chain. Consumed by\n`EmailDraftsService`; the immediate-send composer still derives\n`In-Reply-To` from the chain's newest message, so this is inert on that\npath and always has been.\n\nWHATSAPP — becomes Meta's `context: { message_id: <wamid> }` on the\noutbound call, and is persisted as `Message.replyToMessageId` so our own\nthread renders the quote. The target must be a META/WHATSAPP message\nbelonging to the SAME contact and already carrying a wamid; the send\nservice validates all three and throws 98014 otherwise.\n\nNot forwarded by the scheduled-send path (`ScheduleMessageDto` inherits\nthe field, but the controller does not pass it through), so a scheduled\nWhatsApp reply sends without its quote.","format":"uuid"},"scheduledAt":{"type":"string"}},"required":["clientMessageId","channel","scheduledAt"]},"RescheduleMessageDto":{"type":"object","properties":{"scheduledAt":{"type":"string"},"body":{"type":"string","minLength":1,"maxLength":1600},"mediaUrls":{"type":"array","items":{"type":"string"}}}},"ReactToMessageDto":{"type":"object","properties":{"emoji":{"type":"string"}},"required":["emoji"]},"NoteAttachmentInputDto":{"type":"object","properties":{"storageKey":{"type":"string","minLength":1,"maxLength":512},"filename":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","description":"May be empty — see `CreateNoteAttachmentUploadDto.contentType`.","maxLength":150},"sizeBytes":{"type":"number","minimum":1}},"required":["storageKey","filename","contentType","sizeBytes"]},"SendInternalNoteDto":{"type":"object","properties":{"body":{"type":"string"},"bodyFormat":{"type":"string","description":"Omitted by existing clients, which keeps them on the historical\nplain-text behaviour — the column default is `PLAIN` too.","enum":["PLAIN","HTML"]},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/NoteAttachmentInputDto"}},"clientNoteId":{"type":"string","description":"Client-generated correlation id (UUID). Echoed back on the POST response\nand the `note:new` WS payload so the sender can reconcile its optimistic row\nwith its own realtime echo instead of rendering a duplicate.","format":"uuid"}},"required":["body"]},"UpdateInternalNoteDto":{"type":"object","properties":{"body":{"type":"string"},"bodyFormat":{"type":"string","description":"Omitted by existing clients, which keeps them on the historical\nplain-text behaviour. A plain note becomes `HTML` only when it is\nactually saved through the rich editor.","enum":["PLAIN","HTML"]},"removeAttachmentIds":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["body"]},"MentionCandidateDto":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"type":"string"}},"required":["id","firstName","lastName","email"]},"ContactFilterCandidateDto":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true}},"required":["id","firstName","lastName","email","phone"]},"CreateNoteAttachmentUploadDto":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","description":"May be EMPTY, and must be allowed through. Browsers report `''` for `.md`,\n`.log` and (on some systems) `.csv`, and a `@MinLength(1)` here meant the\nglobal ValidationPipe rejected those uploads before the service could\nderive the real type from the filename — the allow-list's own\nby-extension arm was unreachable over HTTP because of it.","maxLength":150},"sizeBytes":{"type":"number","minimum":1}},"required":["filename","contentType","sizeBytes"]},"NoteAttachmentUploadUrlDto":{"type":"object","properties":{"uploadUrl":{"type":"string"},"storageKey":{"type":"string"},"contentType":{"type":"string","description":"The content type that SIGNED the PUT. The client must send exactly this\nas the `Content-Type` header or S3 rejects the signature, and it is also\nwhat it echoes back on the note-save payload."}},"required":["uploadUrl","storageKey","contentType"]},"NoteAttachmentUrlResponseDto":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"NotePreviewSheetDto":{"type":"object","properties":{"name":{"type":"string"},"rows":{"type":"array","items":{"required":true,"type":"array","items":{"type":"string"}}}},"required":["name","rows"]},"NoteAttachmentPreviewDto":{"type":"object","properties":{"kind":{"type":"string","enum":["html","sheets","unsupported"]},"html":{"type":"string","description":"`kind === 'html'` — sanitized DOCX markup."},"sheets":{"description":"`kind === 'sheets'` — worksheets, or a CSV's single sheet.","type":"array","items":{"$ref":"#/components/schemas/NotePreviewSheetDto"}},"reason":{"type":"string","description":"`kind === 'unsupported'` — why no preview could be produced.","enum":["legacy_format","unsupported_format","too_large","empty","conversion_failed"]},"truncated":{"type":"boolean","description":"A row/column/sheet/character cap was hit."},"omittedImages":{"type":"boolean","description":"`kind === 'html'` — the document had images and they are not shown."}},"required":["kind","truncated","omittedImages"]},"MarkConversationReadDto":{"type":"object","properties":{}},"PinUnifiedDto":{"type":"object","properties":{"isPinned":{"type":"boolean"}},"required":["isPinned"]},"PinResponseDto":{"type":"object","properties":{"id":{"type":"string"},"isPinned":{"type":"boolean"}},"required":["id","isPinned"]},"MuteUnifiedDto":{"type":"object","properties":{"isMuted":{"type":"boolean"}},"required":["isMuted"]},"MuteResponseDto":{"type":"object","properties":{"id":{"type":"string"},"isMuted":{"type":"boolean"}},"required":["id","isMuted"]},"ArchiveUnifiedDto":{"type":"object","properties":{"isArchived":{"type":"boolean"}},"required":["isArchived"]},"ArchiveResponseDto":{"type":"object","properties":{"id":{"type":"string"},"isArchived":{"type":"boolean"}},"required":["id","isArchived"]},"AssignUnifiedDto":{"type":"object","properties":{"assignedTo":{"type":"string","nullable":true,"format":"uuid"}}},"AssignResponseDto":{"type":"object","properties":{"id":{"type":"string"},"assignedTo":{"type":"string","nullable":true}},"required":["id","assignedTo"]},"SetStatusDto":{"type":"object","properties":{"status":{"type":"string","enum":["OPEN","PENDING","CLOSED","SNOOZED","SPAM","TRASH"]},"snoozedUntil":{"type":"string"}},"required":["status"]},"StatusResponseDto":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["OPEN","PENDING","CLOSED","SNOOZED","SPAM","TRASH"]}},"required":["id","status"]},"SyncRequestDto":{"type":"object","properties":{"since":{"type":"string"}},"required":["since"]},"UnifiedConversationSyncItemDto":{"type":"object","properties":{"aiState":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/UnifiedConversationAiStateDto"}]},"id":{"type":"string"},"organizationId":{"type":"string"},"contactId":{"type":"string","nullable":true},"isOpen":{"type":"boolean"},"isArchived":{"type":"boolean"},"isPinned":{"type":"boolean"},"pinnedAt":{"format":"date-time","type":"string","nullable":true},"priority":{"type":"string","enum":["LOW","NORMAL","HIGH","URGENT"]},"status":{"type":"string","enum":["OPEN","PENDING","CLOSED","SNOOZED","SPAM","TRASH"]},"assignedTo":{"type":"string","nullable":true},"assignedAt":{"format":"date-time","type":"string","nullable":true},"unreadCount":{"type":"number"},"lastMessageAt":{"format":"date-time","type":"string","nullable":true},"lastMessagePreview":{"type":"string","nullable":true},"lastMessageDirection":{"type":"string","nullable":true,"enum":["OUTBOUND","INBOUND"]},"lastMessageChannel":{"type":"string","nullable":true,"enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"lastMessageId":{"type":"string","nullable":true},"lastCallOutcome":{"type":"string","nullable":true,"description":"Outcome of the last call — lets the list colour a row by what happened\nrather than re-deriving it from the preview text. Only meaningful while\n`lastMessageChannel` is VOICE; null for every other channel and for rows\nlast touched before this field existed.","enum":["MISSED","VOICEMAIL","COMPLETED_INBOUND","COMPLETED_OUTBOUND","NO_ANSWER"]},"closedAt":{"format":"date-time","type":"string","nullable":true},"snoozedUntil":{"format":"date-time","type":"string","nullable":true,"description":"When a SNOOZED conversation wakes back to OPEN, and who snoozed it. Only\nmeaningful while `status` is SNOOZED; null otherwise, and on conversations\nsnoozed before wake times existed."},"snoozedById":{"type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["aiState","id","organizationId","contactId","isOpen","isArchived","isPinned","pinnedAt","priority","status","assignedTo","assignedAt","unreadCount","lastMessageAt","lastMessagePreview","lastMessageDirection","lastMessageChannel","lastMessageId","lastCallOutcome","closedAt","snoozedUntil","snoozedById","createdAt","updatedAt"]},"ConversationDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"unifiedConversationId":{"type":"string"},"contactId":{"type":"string","nullable":true},"channelIdentityId":{"type":"string"},"channel":{"type":"string","enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"]},"unreadCount":{"type":"number"},"lastMessageAt":{"format":"date-time","type":"string","nullable":true},"lastMessagePreview":{"type":"string","nullable":true},"lastMessageDirection":{"type":"string","nullable":true,"enum":["OUTBOUND","INBOUND"]},"lastMessageId":{"type":"string","nullable":true},"isOpen":{"type":"boolean"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","organizationId","unifiedConversationId","contactId","channelIdentityId","channel","unreadCount","lastMessageAt","lastMessagePreview","lastMessageDirection","lastMessageId","isOpen","createdAt","updatedAt"]},"InboxSyncResponseDto":{"type":"object","properties":{"tooStale":{"type":"boolean"},"unifieds":{"type":"array","items":{"$ref":"#/components/schemas/UnifiedConversationSyncItemDto"}},"conversations":{"type":"array","items":{"$ref":"#/components/schemas/ConversationDto"}},"messages":{"type":"array","items":{"$ref":"#/components/schemas/InboxMessageDto"}},"serverTime":{"type":"string"},"truncated":{"type":"boolean"}},"required":["tooStale","unifieds","conversations","messages","serverTime","truncated"]},"DraftAttachmentKeyDto":{"type":"object","properties":{"storageKey":{"type":"string","maxLength":512},"filename":{"type":"string","maxLength":255},"mimeType":{"type":"string","maxLength":150},"sizeBytes":{"type":"number","minimum":1}},"required":["storageKey","filename","mimeType","sizeBytes"]},"EmailDraftViewDto":{"type":"object","properties":{"id":{"type":"string"},"unifiedConversationId":{"type":"string","nullable":true},"emailSenderId":{"type":"string","nullable":true},"toEmails":{"type":"array","items":{"type":"string"}},"ccEmails":{"type":"array","items":{"type":"string"}},"bccEmails":{"type":"array","items":{"type":"string"}},"subject":{"type":"string","nullable":true},"htmlBody":{"type":"string","nullable":true},"attachmentKeys":{"type":"array","items":{"$ref":"#/components/schemas/DraftAttachmentKeyDto"}},"inReplyToMessageId":{"type":"string","nullable":true},"origin":{"enum":["INBOX","CONTACT_COMPOSER"],"type":"string"},"contactId":{"type":"string","nullable":true},"emailTemplateId":{"type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"emailThreadId":{"type":"string","nullable":true}},"required":["id","unifiedConversationId","emailSenderId","toEmails","ccEmails","bccEmails","subject","htmlBody","attachmentKeys","inReplyToMessageId","origin","contactId","emailTemplateId","createdAt","updatedAt","emailThreadId"]},"UpsertEmailDraftDto":{"type":"object","properties":{"unifiedConversationId":{"type":"string","nullable":true,"format":"uuid"},"emailSenderId":{"type":"string","nullable":true,"format":"uuid"},"toEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"ccEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"bccEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"subject":{"type":"string","nullable":true,"maxLength":998},"htmlBody":{"type":"string","nullable":true,"maxLength":500000},"attachmentKeys":{"type":"array","items":{"$ref":"#/components/schemas/DraftAttachmentKeyDto"}},"inReplyToMessageId":{"type":"string","nullable":true,"format":"uuid"},"emailThreadId":{"type":"string","nullable":true,"description":"Subject chain this draft replies into — keeps a half-written reply with\n the thread it belongs to instead of the contact as a whole.","format":"uuid"},"origin":{"description":"Which composer is writing. Optional so every existing inbox caller keeps\n working untouched; the service enforces the per-origin invariants.","enum":["INBOX","CONTACT_COMPOSER"],"type":"string","default":"INBOX"},"contactId":{"type":"string","nullable":true,"description":"Required when `origin` is CONTACT_COMPOSER; rejected otherwise.","format":"uuid"},"emailTemplateId":{"type":"string","nullable":true,"format":"uuid"}},"required":["toEmails","ccEmails","bccEmails","attachmentKeys"]},"ComposeEmailDto":{"type":"object","properties":{"contactIds":{"maxItems":50,"description":"Recipient contact ids","type":"array","items":{"type":"string","format":"uuid"}},"toEmails":{"maxItems":50,"description":"Raw recipient addresses for people not in Contacts","type":"array","items":{"type":"string","format":"email"}},"emailSenderId":{"type":"string","format":"uuid","description":"EmailSender id (Settings → Email → Senders)"},"subject":{"type":"string","maxLength":998},"html":{"type":"string","minLength":1,"maxLength":500000,"description":"Rich HTML body"},"ccEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"bccEmails":{"maxItems":50,"type":"array","items":{"type":"string","format":"email"}},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/StagedAttachmentDto"}},"signatureId":{"type":"string","format":"uuid"},"suppressSignature":{"type":"boolean"},"clientMessageId":{"type":"string","format":"uuid","description":"Idempotency key (UUID) — replays return the existing message"},"scheduledAt":{"type":"string","description":"ISO fire time — schedules instead of sending now"}},"required":["emailSenderId","html","clientMessageId"]},"ComposeEmailResultEntryDto":{"type":"object","properties":{"contactId":{"type":"string"},"email":{"type":"string","description":"The address this copy went to"},"unifiedConversationId":{"type":"string","nullable":true},"messageId":{"type":"string"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["contactId","email","unifiedConversationId"]},"ComposeEmailResponseDto":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/ComposeEmailResultEntryDto"}}},"required":["results"]},"SuggestEmailSubjectDto":{"type":"object","properties":{"text":{"type":"string","maxLength":4800,"description":"Plain-text composer body the subject should describe. Preferred over `html` — the composer already holds the text, and the model only ever reads text."},"html":{"type":"string","maxLength":500000,"description":"Composer body HTML. Fallback for clients that only hold markup.","deprecated":true},"subject":{"type":"string","maxLength":998,"description":"Whatever is already typed in Subject — a hint"}}},"SuggestedEmailSubjectDto":{"type":"object","properties":{"subject":{"type":"string","description":"The suggested subject line"}},"required":["subject"]},"EmailAttachmentUploadUrlDto":{"type":"object","properties":{"uploadUrl":{"type":"string"},"storageKey":{"type":"string"}},"required":["uploadUrl","storageKey"]},"MessageAttachmentViewDto":{"type":"object","properties":{"id":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"sizeBytes":{"type":"number"},"url":{"type":"string"}},"required":["id","filename","mimeType","sizeBytes","url"]},"ContactMessageDraftViewDto":{"type":"object","properties":{"id":{"type":"string"},"contactId":{"type":"string"},"channel":{"enum":["SMS","WHATSAPP"],"type":"string"},"body":{"type":"string"},"channelIdentityId":{"type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","contactId","channel","body","channelIdentityId","createdAt","updatedAt"]},"ContactDraftsViewDto":{"type":"object","properties":{"email":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/EmailDraftViewDto"}]},"sms":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ContactMessageDraftViewDto"}]},"expiredAttachmentCount":{"type":"number","description":"Staged attachments on the email draft whose storage objects have since\ndisappeared, already stripped from `email.attachmentKeys`. Surfaced so the\ncomposer can say so on open instead of letting the send fail later."}},"required":["email","sms","expiredAttachmentCount"]},"UpsertContactMessageDraftDto":{"type":"object","properties":{"contactId":{"type":"string","format":"uuid"},"channel":{"enum":["SMS","WHATSAPP"],"type":"string"},"body":{"type":"string","description":"Raw composer text with merge tags UNEXPANDED. Capped at the send DTO's\n1600, not the composer's 500-char product cap: that cap applies to the raw\ntext the user types, and expansion happens at send time.","maxLength":1600},"channelIdentityId":{"type":"string","nullable":true,"format":"uuid"}},"required":["contactId","channel","body"]},"ComposeSmsDto":{"type":"object","properties":{"contactIds":{"maxItems":50,"description":"Recipient contact ids","type":"array","items":{"type":"string","format":"uuid"}},"phones":{"maxItems":50,"description":"Raw recipient numbers for people not in Contacts. Normalised to E.164 server-side using the org default country, then find-or-created as MANUAL contacts tagged \"New\".","type":"array","items":{"type":"string","maxLength":32}},"channelIdentityId":{"type":"string","format":"uuid","description":"Sending number (channel identity id)"},"body":{"type":"string","minLength":1,"maxLength":1600,"description":"Required unless `mediaUrls` has an attachment"},"clientMessageId":{"type":"string","format":"uuid","description":"Batch idempotency key (UUID). Per-contact sends derive uuidv5(contactId, thisKey), so an identical retry replays instead of re-sending."},"mediaUrls":{"description":"Media to attach — turns each per-recipient send into an MMS. Same contract and 10-item cap as every other send path (`IsMessageMediaUrls`). Carries the org contact card when the composer's toggle is on.","type":"array","items":{"type":"string"}},"scheduledAt":{"type":"string","description":"ISO fire time — schedules instead of sending now"}},"required":["channelIdentityId","clientMessageId"]},"ComposeSmsResultEntryDto":{"type":"object","properties":{"contactId":{"type":"string"},"phone":{"type":"string","description":"The raw number this entry came from, when addressed by number"},"unifiedConversationId":{"type":"string","nullable":true},"messageId":{"type":"string"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["contactId","unifiedConversationId"]},"ComposeSmsResponseDto":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/ComposeSmsResultEntryDto"}}},"required":["results"]},"ComposeWhatsAppDto":{"type":"object","properties":{"contactIds":{"maxItems":50,"description":"Recipient contact ids","type":"array","items":{"type":"string","format":"uuid"}},"phones":{"maxItems":50,"description":"Raw recipient numbers for people not in Contacts. Normalised to E.164 server-side using the org default country, then find-or-created as MANUAL contacts tagged \"New\". With no 24h window, these need `whatsappTemplateId`.","type":"array","items":{"type":"string","maxLength":32}},"whatsappTemplateId":{"type":"string","format":"uuid","description":"APPROVED template id. When set, the free-form body + 24h service-window rule is bypassed (Meta's own re-engagement mechanism) — mirrors SendMessageDto.whatsappTemplateId."},"clientMessageId":{"type":"string","format":"uuid","description":"Batch idempotency key (UUID). Per-contact sends derive uuidv5(contactId, thisKey), so an identical retry replays instead of re-sending."},"body":{"type":"string","minLength":1,"maxLength":4096}},"required":["clientMessageId"]},"ComposeWhatsAppResultEntryDto":{"type":"object","properties":{"contactId":{"type":"string"},"phone":{"type":"string","description":"The raw number this entry came from, when addressed by number"},"unifiedConversationId":{"type":"string","nullable":true},"messageId":{"type":"string"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["contactId","unifiedConversationId"]},"ComposeWhatsAppResponseDto":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/ComposeWhatsAppResultEntryDto"}}},"required":["results"]},"RoutingFormResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"status":{"enum":["ACTIVE","ARCHIVED"],"type":"string"},"tree":{"type":"object"},"qrDesign":{"type":"object","additionalProperties":true,"nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","name","slug","status","tree","qrDesign","createdAt","updatedAt"]},"UpsertRoutingFormDto":{"type":"object","properties":{"name":{"type":"string","description":"Trimmed first, so a name of only spaces is refused as empty.","maxLength":150},"slug":{"type":"string","minLength":2,"maxLength":100},"tree":{"type":"object"},"qrDesign":{"type":"object","additionalProperties":true,"nullable":true,"description":"Omit to keep the stored design; send `null` to clear it."}},"required":["name","slug","tree"]},"PublicRoutingFormDto":{"type":"object","properties":{"organizationName":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"tree":{"type":"object"}},"required":["organizationName","name","slug","tree"]},"CreateApiKeyDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","nullable":true,"maxLength":2000},"expiresAt":{"format":"date-time","type":"string","nullable":true,"description":"Optional expiration timestamp. `null` / omitted = never expires.\nThe strategy validates against this on every authenticated request."},"roleId":{"type":"string","nullable":true,"description":"Role this key authenticates as. Omitted = the org's OWNER role.\nValidated server-side against roles owned by the caller's org (or\nglobal system roles), so another tenant's role id cannot be supplied.","format":"uuid"}},"required":["name"]},"ApiKeyRoleSummaryDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"ApiKeyCreatedDto":{"type":"object","properties":{"plaintext":{"type":"string","description":"The full API key, shown only once at creation/rotation time."},"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"prefix":{"type":"string"},"lastFour":{"type":"string"},"status":{"enum":["active","revoked","expired"],"type":"string"},"role":{"$ref":"#/components/schemas/ApiKeyRoleSummaryDto"},"expiresAt":{"format":"date-time","type":"string","nullable":true},"lastUsedAt":{"format":"date-time","type":"string","nullable":true},"revokedAt":{"format":"date-time","type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["plaintext","id","name","description","prefix","lastFour","status","role","expiresAt","lastUsedAt","revokedAt","createdAt","updatedAt"]},"ApiKeyResponseDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"prefix":{"type":"string"},"lastFour":{"type":"string"},"status":{"enum":["active","revoked","expired"],"type":"string"},"role":{"$ref":"#/components/schemas/ApiKeyRoleSummaryDto"},"expiresAt":{"format":"date-time","type":"string","nullable":true},"lastUsedAt":{"format":"date-time","type":"string","nullable":true},"revokedAt":{"format":"date-time","type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","name","description","prefix","lastFour","status","role","expiresAt","lastUsedAt","revokedAt","createdAt","updatedAt"]},"ApiKeyAuditEventDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"userId":{"type":"string","nullable":true},"apiKeyId":{"type":"string","nullable":true},"action":{"type":"string"},"resourceType":{"type":"string"},"resourceId":{"type":"string","nullable":true},"ipAddress":{"type":"string","nullable":true},"userAgent":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":true},"createdAt":{"format":"date-time","type":"string"}},"required":["id","organizationId","userId","apiKeyId","action","resourceType","resourceId","ipAddress","userAgent","metadata","createdAt"]},"ApiKeyDetailDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"prefix":{"type":"string"},"lastFour":{"type":"string"},"status":{"enum":["active","revoked","expired"],"type":"string"},"role":{"$ref":"#/components/schemas/ApiKeyRoleSummaryDto"},"expiresAt":{"format":"date-time","type":"string","nullable":true},"lastUsedAt":{"format":"date-time","type":"string","nullable":true},"revokedAt":{"format":"date-time","type":"string","nullable":true},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"recentAuditEvents":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyAuditEventDto"}}},"required":["id","name","description","prefix","lastFour","status","role","expiresAt","lastUsedAt","revokedAt","createdAt","updatedAt","recentAuditEvents"]},"UpdateApiKeyDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","nullable":true,"maxLength":2000},"expiresAt":{"format":"date-time","type":"string","nullable":true}}},"RegisterUserDto":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","description":"Last name is now optional — many real-world locales use single-name identities.","maxLength":100},"email":{"type":"string","maxLength":255,"format":"email"},"password":{"type":"string","minLength":8},"phone":{"type":"string","description":"Optional phone for account contact metadata.","maxLength":32},"planSlug":{"type":"string","description":"Plan carried from the pricing page (?plan=<catalog slug>) — Phase A\ncarry-through. Signup never collects payment: the selection only picks\nwhich plan the card-free trial starts on.","maxLength":60,"pattern":"^[a-z0-9][a-z0-9-]*$"},"billingPeriod":{"type":"string","description":"Billing preference carried from the pricing page (?billing=…).","enum":["monthly","yearly"]}},"required":["firstName","email","password"]},"RegisterViaInvitationDto":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","maxLength":100},"password":{"type":"string","minLength":8},"phone":{"type":"string","maxLength":32},"invitationToken":{"type":"string"}},"required":["firstName","password","invitationToken"]},"LoginViaInvitationDto":{"type":"object","properties":{"invitationToken":{"type":"string"},"password":{"type":"string","minLength":8}},"required":["invitationToken","password"]},"LoginUserDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":8},"rememberMe":{"type":"boolean"}},"required":["email","password"]},"OAuthExchangeDto":{"type":"object","properties":{"ticket":{"type":"string","minLength":43,"maxLength":43}},"required":["ticket"]},"ForgotPasswordDto":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]},"VerifyResetTokenDto":{"type":"object","properties":{"token":{"type":"string","minLength":1}},"required":["token"]},"ResetPasswordDto":{"type":"object","properties":{"token":{"type":"string"},"email":{"type":"string","format":"email"},"newPassword":{"type":"string","minLength":8}},"required":["token","email","newPassword"]},"CreateInvitationDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"inviteeName":{"type":"string","maxLength":255},"roleId":{"type":"string","format":"uuid"},"message":{"type":"string","maxLength":1000}},"required":["email","roleId"]},"BulkInviteeDto":{"type":"object","properties":{"email":{"type":"string","format":"email"},"inviteeName":{"type":"string","description":"Persisted on the invitation so the invite card shows a real name.","maxLength":255},"roleId":{"type":"string","description":"Overrides the payload-level `roleId` — lets one request mix roles.","format":"uuid"}},"required":["email"]},"BulkCreateInvitationDto":{"type":"object","properties":{"invitees":{"description":"Preferred shape: one entry per person, so a single request can carry\nper-invitee names and roles.","minItems":1,"type":"array","items":{"$ref":"#/components/schemas/BulkInviteeDto"}},"emails":{"description":"Legacy shape: bare emails that all share the payload-level `roleId` and\ncarry no name. Required only when `invitees` is absent.","minItems":1,"type":"array","items":{"type":"string","format":"email"}},"roleId":{"type":"string","description":"Default role for entries that don't name their own.","format":"uuid"},"message":{"type":"string","maxLength":1000}},"required":["roleId"]},"AnswerInvitationDto":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]},"CreateAgencyDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255}},"required":["name"]},"CreateClientDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"timezone":{"type":"string"},"defaultCountryCode":{"type":"string"},"website":{"type":"string","maxLength":500,"format":"uri"},"industry":{"type":"string","maxLength":100},"planSlug":{"type":"string","minLength":1,"maxLength":80},"billingMode":{"type":"string","enum":["AGENCY_PAYS","CLIENT_PAYS"]},"brandingMode":{"type":"string","description":"How this client sees the platform — agency branding by default (§17).","enum":["AGENCY","CLIENT"]},"retailMonthlyCents":{"type":"number","description":"Omit to inherit the agency's default retail price for the plan.","minimum":0},"inviteEmail":{"type":"string","maxLength":255,"format":"email"},"setupId":{"type":"string","description":"Agency Setup to install into the new workspace after creation.","format":"uuid"},"contactName":{"type":"string","maxLength":255},"email":{"type":"string","maxLength":255,"format":"email"},"phone":{"type":"string","maxLength":32}},"required":["name","planSlug","billingMode"]},"PlanPricingRuleDto":{"type":"object","properties":{"planSlug":{"type":"string","minLength":1,"maxLength":80},"retailMonthlyCents":{"type":"number","minimum":0},"retailAnnualCents":{"type":"number","minimum":0}},"required":["planSlug","retailMonthlyCents"]},"UpdatePlanPricingDto":{"type":"object","properties":{"rules":{"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/PlanPricingRuleDto"}}},"required":["rules"]},"UpdateAgencySettingsDto":{"type":"object","properties":{"defaultMarginPct":{"type":"number","nullable":true,"description":"Suggested-pricing rule, e.g. 40 = suggest wholesale + 40 %. Null clears it.","minimum":0,"maximum":500}}},"UpdateClientPricingDto":{"type":"object","properties":{"billingMode":{"type":"string","enum":["AGENCY_PAYS","CLIENT_PAYS"]},"usagePayer":{"type":"string","description":"§56 — who pays for usage overages (informational until rebilling).","enum":["AGENCY","CLIENT","INCLUDED"]},"retailMonthlyCents":{"type":"number","nullable":true,"description":"Explicit null clears the override (client inherits the agency default).","minimum":0},"retailAnnualCents":{"type":"number","nullable":true,"minimum":0},"note":{"type":"string","nullable":true,"maxLength":500}}},"CreateSetupDto":{"type":"object","properties":{"organizationId":{"type":"string","description":"The client workspace to capture the setup from.","format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":1000},"industry":{"type":"string","maxLength":100}},"required":["organizationId","name"]},"UpdateSetupDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","nullable":true,"maxLength":1000},"industry":{"type":"string","nullable":true,"maxLength":100}}},"UpdateBrandingDto":{"type":"object","properties":{"primaryColor":{"type":"string","nullable":true,"description":"Explicit null clears the value.","pattern":"^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"},"supportEmail":{"type":"string","nullable":true,"maxLength":255,"format":"email"},"supportPhone":{"type":"string","nullable":true,"maxLength":32},"useLogo":{"type":"boolean"},"useColors":{"type":"boolean"},"useDomain":{"type":"boolean"},"hideAutocampaignBranding":{"type":"boolean"},"useSupportInfo":{"type":"boolean"}}},"SetDomainDto":{"type":"object","properties":{"domain":{"type":"string","maxLength":255}},"required":["domain"]},"ConnectStripeDto":{"type":"object","properties":{"secretKey":{"type":"string","description":"The AGENCY's own Stripe secret key — encrypted at rest, never echoed back.","maxLength":255,"pattern":"^sk_(test|live)_"}},"required":["secretKey"]},"CreateSmsTemplateDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":150},"description":{"type":"string","nullable":true,"maxLength":500},"type":{"type":"string","description":"Discriminates the template's use case. Defaults to TEXT_LINK at the\nservice layer when omitted — the only currently-active type. Type is\nimmutable post-create (UpdateSmsTemplateDto omits it).","enum":["TEXT_LINK","WELCOME"]},"category":{"type":"string","enum":["MARKETING","WELCOME","REMINDER","GENERAL","PROMOTIONAL","TRANSACTIONAL","NOTIFICATION"]},"body":{"type":"string","minLength":1,"maxLength":1600},"tagIds":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["name","category","body"]},"SmsTemplateTagColorDto":{"type":"object","properties":{"fg":{"type":"string"},"bg":{"type":"string"}},"required":["fg","bg"]},"SmsTemplateTagDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/SmsTemplateTagColorDto"}]}},"required":["id","name","color"]},"SmsTemplateResponseDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string","nullable":true},"isSystem":{"type":"boolean"},"type":{"enum":["TEXT_LINK","WELCOME"],"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"category":{"enum":["MARKETING","WELCOME","REMINDER","GENERAL","PROMOTIONAL","TRANSACTIONAL","NOTIFICATION"],"type":"string"},"body":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}},"status":{"enum":["ACTIVE","ARCHIVED"],"type":"string"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/SmsTemplateTagDto"}}},"required":["id","organizationId","isSystem","type","name","description","category","body","variables","status","createdAt","updatedAt","tags"]},"UpdateSmsTemplateDto":{"type":"object","properties":{"status":{"type":"string","enum":["ACTIVE","ARCHIVED"]}}},"CloneSmsTemplateDto":{"type":"object","properties":{}},"LeadFormDesignDto":{"type":"object","properties":{"themePreset":{"type":"string","enum":["minimal","modern","corporate","dark","rounded","sunset","ocean","forest","slate","blossom","sand","midnight"]},"primaryColor":{"type":"string"},"backgroundColor":{"type":"string"},"fontFamily":{"type":"string","maxLength":200},"buttonStyle":{"type":"string","enum":["rounded","square","pill"]},"logoUrl":{"type":"string","nullable":true,"description":"`@IsOptional()` skips both `undefined` and `null` — `null` is how the\nwizard sends \"unset\", the same shape as `redirectUrl`. Length is capped\nas well as validated: a pasted base64 `data:` image fails the scheme\ncheck, but a legitimate-looking URL should not be unbounded either.","maxLength":2000},"backgroundImageUrl":{"type":"string","nullable":true,"maxLength":2000},"displayMode":{"type":"string","description":"Absent on pre-Phase-4 rows ⇒ classic.","enum":["classic","conversational"]}},"required":["themePreset","primaryColor","backgroundColor","fontFamily","buttonStyle"]},"ThankYouSmsFollowUpDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"body":{"type":"string","maxLength":1600},"fromIdentityId":{"type":"string","nullable":true,"description":"`ChannelIdentity.id` to send from. `@ValidateIf` makes it required only\nwhile the action is on, so a `{ enabled: false }` blob (and every seeded\ntemplate) still validates. Org ownership + ACTIVE status are checked\nseparately in `LeadFormsService.assertOwnedSenderIds` — a UUID from the\nclient is otherwise unverified cross-tenant, since ids inside the\n`follow_up` JSONB carry no foreign key.","format":"uuid"}},"required":["enabled","body"]},"ThankYouEmailFollowUpDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"subject":{"type":"string","maxLength":255},"body":{"type":"string","maxLength":10000},"emailSenderId":{"type":"string","nullable":true,"description":"`EmailSender.id` to send from — required while enabled (see above).","format":"uuid"}},"required":["enabled","subject","body"]},"NotifyTeamFollowUpDto":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"]},"CreateOpportunityFollowUpDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"pipelineId":{"type":"string","nullable":true,"format":"uuid"},"stageId":{"type":"string","nullable":true,"format":"uuid"},"ownerId":{"type":"string","nullable":true,"format":"uuid"}},"required":["enabled"]},"LeadFormFollowUpDto":{"type":"object","properties":{"successMessage":{"type":"string","maxLength":1000},"redirectUrl":{"type":"string","nullable":true,"description":"`require_protocol: true` + the `http`/`https` allow-list is what\nrejects `javascript:`/`data:` schemes — a redirect target is handed\nstraight to `window.location.assign` on the public form, so anything\nelse is a stored-XSS payload against every anonymous submitter.","maxLength":2000,"format":"uri"},"segmentId":{"type":"string","nullable":true,"format":"uuid"},"workflowId":{"type":"string","nullable":true,"format":"uuid"},"tagIds":{"type":"array","items":{"type":"string","format":"uuid"}},"thankYouSms":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ThankYouSmsFollowUpDto"}]},"thankYouEmail":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ThankYouEmailFollowUpDto"}]},"notifyTeam":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/NotifyTeamFollowUpDto"}]},"createOpportunity":{"nullable":true,"description":"Phase II: create an opportunity for the resolved contact on submit.","type":"object","allOf":[{"$ref":"#/components/schemas/CreateOpportunityFollowUpDto"}]},"createContact":{"type":"boolean","description":"Author opt-outs for the three steps that otherwise always run on submit\n(contact match/merge, custom-field mapping, and the domain event that\npowers the activity log + `workflowId` automation). Optional — an absent\nflag reads as `true` (on) in the submit pipeline, so legacy rows and any\npartial payload keep the pre-toggle \"always run\" behavior."},"mapCustomFields":{"type":"boolean"},"emitWorkflowEvent":{"type":"boolean"}},"required":["successMessage","tagIds"]},"CreateLeadFormDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":500},"templateKey":{"type":"string","maxLength":60},"questions":{"description":"Deep-validated server-side by LeadFormAnswerValidatorService.validateQuestions.","type":"array","items":{"type":"object"}},"design":{"$ref":"#/components/schemas/LeadFormDesignDto"},"followUp":{"$ref":"#/components/schemas/LeadFormFollowUpDto"},"language":{"type":"string","maxLength":10},"folder":{"type":"string","maxLength":100},"tagIds":{"description":"Org `Tag` ids to associate with this form (written to `lead_form_tags`).\nWas a free-text `string[]` of labels with no backing entity; the wizard's\nBasics step now picks from — and creates in — the Tags module, so these\nare real uuids. The service additionally verifies every id belongs to the\ncaller's org before writing.\n\nNOTE: the old `tags` key is gone. The global ValidationPipe runs\n`forbidNonWhitelisted: true`, so a stale client sending `tags` gets a 400\nrather than having it silently dropped.","maxItems":20,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["name"]},"CreateLeadFormThemeDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"design":{"description":"Same validation class as `CreateLeadFormDto.design`. A saved theme is\nlater re-applied to a DIFFERENT form, so an unvalidated image URL stored\nhere resurfaces as an error the author cannot trace back to this dialog.","allOf":[{"$ref":"#/components/schemas/LeadFormDesignDto"}]}},"required":["name","design"]},"UpdateLeadFormDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":500},"questions":{"description":"Deep-validated server-side by LeadFormAnswerValidatorService.validateQuestions.","type":"array","items":{"type":"object"}},"design":{"$ref":"#/components/schemas/LeadFormDesignDto"},"followUp":{"$ref":"#/components/schemas/LeadFormFollowUpDto"},"language":{"type":"string","maxLength":10},"folder":{"type":"string","maxLength":100},"tagIds":{"description":"Org `Tag` ids to associate with this form (written to `lead_form_tags`).\nWas a free-text `string[]` of labels with no backing entity; the wizard's\nBasics step now picks from — and creates in — the Tags module, so these\nare real uuids. The service additionally verifies every id belongs to the\ncaller's org before writing.\n\nNOTE: the old `tags` key is gone. The global ValidationPipe runs\n`forbidNonWhitelisted: true`, so a stale client sending `tags` gets a 400\nrather than having it silently dropped.","maxItems":20,"type":"array","items":{"type":"string","format":"uuid"}}}},"TrackLeadFormEventDto":{"type":"object","properties":{"utmSource":{"type":"string","maxLength":255},"utmMedium":{"type":"string","maxLength":255},"utmCampaign":{"type":"string","maxLength":255},"utmTerm":{"type":"string","maxLength":255},"utmContent":{"type":"string","maxLength":255},"sourceUrl":{"type":"string","maxLength":500},"embedMode":{"enum":["HOSTED","INLINE","POPUP","SLIDE_IN"],"type":"string"}}},"RequestLeadFormUploadUrlDto":{"type":"object","properties":{"questionId":{"type":"string","minLength":1,"maxLength":200},"fileName":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","minLength":1,"maxLength":150},"sizeBytes":{"type":"number","minimum":1}},"required":["questionId","fileName","contentType","sizeBytes"]},"SubmitLeadFormDto":{"type":"object","properties":{"answers":{"type":"object","additionalProperties":true,"description":"{ [questionId]: value } — deep-validated by LeadFormAnswerValidatorService."},"utmSource":{"type":"string","maxLength":255},"utmMedium":{"type":"string","maxLength":255},"utmCampaign":{"type":"string","maxLength":255},"utmTerm":{"type":"string","maxLength":255},"utmContent":{"type":"string","maxLength":255},"sourceUrl":{"type":"string","maxLength":500},"embedMode":{"type":"string","enum":["HOSTED","INLINE","POPUP","SLIDE_IN"]}},"required":["answers"]},"WidgetInstanceDto":{"type":"object","properties":{"instanceId":{"type":"string","description":"Client-generated id, stable across moves/resizes/renames.","format":"uuid"},"type":{"type":"string","enum":["kpi_active_conversations","kpi_opt_out_rate","kpi_reply_rate","kpi_ai_vs_human","campaign_performance","channels_engagement","opt_out_trends","poll_insights","join_link_performance","link_performance","recent_inbox","quick_actions","appointments_today","unread_conversations","usage_snapshot","setup_progress","business_kpis","conversion_funnel","pipeline_snapshot","opportunities_overview","revenue_performance","upcoming_appointments","recent_leads","ai_activity","lead_sources","recent_activity"]},"size":{"type":"string","enum":["sm","md","lg","xl","full"]},"title":{"type":"string","maxLength":60},"settings":{"type":"object","additionalProperties":true,"description":"Widget-type-specific settings bag. Opaque to the backend in Phase 1."}},"required":["instanceId","type","size"]},"DashboardConfigDto":{"type":"object","properties":{"version":{"type":"number","description":"Locked to DASHBOARD_CONFIG_VERSION for Phase 1 — future breaking shape changes bump it."},"widgets":{"type":"array","items":{"$ref":"#/components/schemas/WidgetInstanceDto"}}},"required":["version","widgets"]},"CreateDashboardDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60},"config":{"$ref":"#/components/schemas/DashboardConfigDto"},"isDefault":{"type":"boolean"}},"required":["name"]},"UpdateDashboardDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60},"config":{"$ref":"#/components/schemas/DashboardConfigDto"}}},"DashboardGrantDto":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"permission":{"type":"string","enum":["VIEW","EDIT"]}},"required":["userId","permission"]},"UpdateDashboardSharingDto":{"type":"object","properties":{"visibility":{"type":"string","enum":["PRIVATE","WORKSPACE","SELECTED"]},"grants":{"type":"array","items":{"$ref":"#/components/schemas/DashboardGrantDto"}}},"required":["visibility"]},"BulkDeleteDto":{"type":"object","properties":{"ids":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"$ref":"#/components/schemas/ContactQueryDto"},"confirmTriggers":{"type":"boolean","description":"Above the sync limit, a bulk action that would start published workflows (tag\nadded/removed) is refused until the user confirms it. Ignored on the sync path."}}},"BulkEditDto":{"type":"object","properties":{"status":{"type":"string","enum":["ACTIVE","INVALID","ARCHIVED"]},"addTagIds":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid"}},"removeTagIds":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid"}},"isOptedOut":{"type":"boolean","description":"When provided, bulk flips the opt-in/out state for all selected contacts.\ntrue → mark as opted out (skip those already opted out).\nfalse → mark as opted in  (skip those already opted in)."},"ids":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"$ref":"#/components/schemas/ContactQueryDto"},"confirmTriggers":{"type":"boolean","description":"Above the sync limit, a bulk action that would start published workflows (tag\nadded/removed) is refused until the user confirms it. Ignored on the sync path."}}},"BulkPreflightDto":{"type":"object","properties":{"addTagIds":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid"}},"removeTagIds":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid"}},"segmentId":{"type":"string","description":"The STATIC segment contacts would be added to.","format":"uuid"},"status":{"type":"string","description":"Field edits — checked against DYNAMIC segment rules (segment entered/left).","enum":["ACTIVE","INVALID","ARCHIVED"]},"isOptedOut":{"type":"boolean"},"ids":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"$ref":"#/components/schemas/ContactQueryDto"},"confirmTriggers":{"type":"boolean","description":"Above the sync limit, a bulk action that would start published workflows (tag\nadded/removed) is refused until the user confirms it. Ignored on the sync path."}}},"TriggerPreflightDto":{"type":"object","properties":{"addTagIds":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid"}},"segmentId":{"type":"string","description":"The STATIC segment contacts would be added to (\"segment entered\" triggers).","format":"uuid"}}},"CreateSegmentDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"type":{"type":"string","enum":["STATIC","DYNAMIC"]},"rules":{"type":"object","additionalProperties":true},"contactIds":{"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"description":"Alternative to `contactIds` for a STATIC segment: create it from ALL contacts matching a\ncontacts filter. The backend resolves the filter to the concrete member set (org-scoped,\nsoft-delete-aware, bounded by `CONTACTS_BULK_SYNC_MAX`). Takes precedence over `contactIds`.","allOf":[{"$ref":"#/components/schemas/ContactQueryDto"}]}},"required":["name","type"]},"ManageContactsSelectorDto":{"type":"object","properties":{"contactIds":{"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}},"filter":{"$ref":"#/components/schemas/ContactQueryDto"},"confirmTriggers":{"type":"boolean","description":"Above the sync limit, confirms starting published \"segment entered\" workflows."}}},"GetUploadUrlDto":{"type":"object","properties":{"fileName":{"type":"string","minLength":5,"maxLength":255,"pattern":"\\.csv$"}},"required":["fileName"]},"CreateImportDto":{"type":"object","properties":{"s3Key":{"type":"string","minLength":1,"maxLength":512},"fileName":{"type":"string","minLength":1,"maxLength":255},"fieldMapping":{"type":"object","additionalProperties":{"type":"string"}},"tagIds":{"type":"array","items":{"type":"string","format":"uuid"}},"duplicateStrategy":{"type":"string","enum":["skip","update","merge"]},"segmentId":{"type":"string","format":"uuid"},"fieldActions":{"type":"object","additionalProperties":{"type":"string"}}},"required":["s3Key","fileName","fieldMapping"]},"VoiceGreetingDto":{"type":"object","properties":{"mode":{"type":"string","enum":["TTS","AUDIO"]},"text":{"type":"string","maxLength":1000},"storageKey":{"type":"string","maxLength":512},"voice":{"type":"string","description":"Twilio TTS voice id (e.g. \"Polly.Joanna\"); unset = Twilio default. Only meaningful for mode TTS.","maxLength":64,"pattern":"^Polly\\.[A-Za-z]+$"},"language":{"type":"string","description":"Twilio language/locale code (e.g. \"en-US\"); unset = Twilio default. Only meaningful for mode TTS.","maxLength":16,"pattern":"^[a-z]{2}(-[A-Z]{2})?$"}},"required":["mode"]},"UpdateVoiceSettingsDto":{"type":"object","properties":{"defaultVoiceIdentityId":{"type":"string","nullable":true,"description":"Org-wide default outgoing caller ID; explicit null clears it.","format":"uuid"},"defaultVoicemailGreeting":{"nullable":true,"description":"Org-wide default voicemail greeting — TTS text or an uploaded audio file\n(same shape as the per-number greeting); explicit null clears it back to\nthe system default.","type":"object","allOf":[{"$ref":"#/components/schemas/VoiceGreetingDto"}]},"unavailableMessage":{"nullable":true,"description":"Org-wide \"currently unavailable\" announcement played before hanging up\nwhen voicemail is off; same greeting shape, explicit null clears it back\nto the system default.","type":"object","allOf":[{"$ref":"#/components/schemas/VoiceGreetingDto"}]}}},"BusinessHoursHolidayDto":{"type":"object","properties":{"date":{"type":"string"},"name":{"type":"string","maxLength":100}},"required":["date","name"]},"BusinessHoursDto":{"type":"object","properties":{"timezone":{"type":"string","maxLength":64},"weekly":{"$ref":"#/components/schemas/BusinessHoursWeeklyDto"},"holidays":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursHolidayDto"}}},"required":["timezone","weekly"]},"VoiceRouteActionDto":{"type":"object","properties":{"type":{"type":"string","enum":["RING_USERS","FORWARD_NUMBER","VOICEMAIL"]},"userIds":{"maxItems":20,"type":"array","items":{"type":"string","format":"uuid"}},"number":{"type":"string"},"greeting":{"description":"VOICEMAIL: greeting override for this route (falls back to the number-level greeting).","allOf":[{"$ref":"#/components/schemas/VoiceGreetingDto"}]}},"required":["type"]},"IvrMenuOptionDto":{"type":"object","properties":{"digit":{"type":"string","pattern":"^[0-9*#]$"},"label":{"type":"string","maxLength":100},"action":{"$ref":"#/components/schemas/VoiceRouteActionDto"}},"required":["digit","label","action"]},"IvrConfigDto":{"type":"object","properties":{"greeting":{"$ref":"#/components/schemas/VoiceGreetingDto"},"menu":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IvrMenuOptionDto"}},"invalidRetries":{"type":"number","minimum":0,"maximum":5},"timeoutSec":{"type":"number","minimum":1,"maximum":30},"menuRepeatLimit":{"type":"number","description":"How many times the whole menu may replay before the timeout action.","minimum":0,"maximum":5},"timeoutAction":{"$ref":"#/components/schemas/VoiceRouteActionDto"}},"required":["greeting","menu","invalidRetries","timeoutSec","timeoutAction"]},"IvrAfterHoursDto":{"type":"object","properties":{"mode":{"type":"string","enum":["IVR","VOICEMAIL","FORWARD_NUMBER"]},"ivr":{"$ref":"#/components/schemas/IvrConfigDto"},"greeting":{"$ref":"#/components/schemas/VoiceGreetingDto"},"number":{"type":"string"}},"required":["mode"]},"IvrScheduleDto":{"type":"object","properties":{"businessHours":{"$ref":"#/components/schemas/IvrConfigDto"},"afterHours":{"$ref":"#/components/schemas/IvrAfterHoursDto"}}},"ForwardingRuleDto":{"type":"object","properties":{"type":{"type":"string","enum":["FORWARD_NUMBER","VOICEMAIL","RING_USERS"]},"userIds":{"description":"RING_USERS: teammates to ring simultaneously.","maxItems":20,"type":"array","items":{"type":"string","format":"uuid"}},"number":{"type":"string"},"greeting":{"description":"VOICEMAIL: greeting override for this rule (falls back to the number-level greeting).","allOf":[{"$ref":"#/components/schemas/VoiceGreetingDto"}]}},"required":["type"]},"ForwardingSlotDto":{"type":"object","properties":{"ringTargets":{"maxItems":20,"type":"array","items":{"type":"string","format":"uuid"}},"busy":{"$ref":"#/components/schemas/ForwardingRuleDto"},"noAnswer":{"$ref":"#/components/schemas/ForwardingRuleDto"},"unavailable":{"$ref":"#/components/schemas/ForwardingRuleDto"}}},"ForwardingDto":{"type":"object","properties":{"businessHours":{"$ref":"#/components/schemas/ForwardingSlotDto"},"afterHours":{"$ref":"#/components/schemas/ForwardingSlotDto"}}},"UpsertVoiceNumberConfigDto":{"type":"object","properties":{"voiceEnabled":{"type":"boolean"},"routingMode":{"type":"string","description":"Whole-number strategy: only the matching config (ivrConfig / forwarding)\n is honored at routing time.","enum":["AI_AGENT","FORWARDING","IVR"]},"recordingPolicy":{"type":"string","enum":["ALWAYS","NEVER","INCOMING_ONLY","OUTGOING_ONLY","BUSINESS_HOURS_ONLY"]},"businessHours":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/BusinessHoursDto"}]},"ivrConfig":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/IvrScheduleDto"}]},"ringTimeoutSec":{"type":"number","minimum":5,"maximum":600},"maxWaitSeconds":{"type":"number","description":"Max seconds to hold a caller for a busy teammate before the forwarding\n \"all agents busy\" rule fires. 0 = don't wait.","minimum":0,"maximum":300},"holdQueueEnabled":{"type":"boolean","description":"Hold queue: park an unanswered inbound caller on hold instead of dropping\n them to voicemail; any online agent can then pick them up."},"maxHoldSeconds":{"type":"number","minimum":30,"maximum":900},"forwarding":{"$ref":"#/components/schemas/ForwardingDto"},"voicemailEnabled":{"type":"boolean"},"voicemailGreeting":{"$ref":"#/components/schemas/VoiceGreetingDto"},"voicemailMaxLengthSec":{"type":"number","minimum":5,"maximum":600}},"required":["voiceEnabled","routingMode","recordingPolicy","ringTimeoutSec","voicemailEnabled","voicemailMaxLengthSec"]},"GetGreetingUploadUrlDto":{"type":"object","properties":{"fileName":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","enum":["audio/mpeg","audio/wav","audio/x-wav","audio/mp4"]},"sizeBytes":{"type":"number","minimum":1,"maximum":10485760}},"required":["fileName","contentType","sizeBytes"]},"InitiateCallDto":{"type":"object","properties":{"contactId":{"type":"string","format":"uuid"},"toNumber":{"type":"string"},"fromIdentityId":{"type":"string","description":"Explicit caller-ID override (channel identity id).","format":"uuid"},"callId":{"type":"string","description":"Client-generated call id — lets the widget render the call optimistically\nbefore the round trip; the server generates one when absent. A replayed\nid is rejected with 409, never re-used.","format":"uuid"}}},"TransferCallDto":{"type":"object","properties":{"targetUserId":{"type":"string","format":"uuid"},"targetNumber":{"type":"string"}}},"LinkCallContactDto":{"type":"object","properties":{"contactId":{"type":"string","format":"uuid"}},"required":["contactId"]},"UpdateCallDispositionDto":{"type":"object","properties":{"disposition":{"type":"string","enum":["INTERESTED","NOT_INTERESTED","FOLLOW_UP","OTHERS"]},"description":{"type":"string","maxLength":2000},"notes":{"type":"string","maxLength":5000}}},"BlockNumberDto":{"type":"object","properties":{"phone":{"type":"string"},"reason":{"type":"string","maxLength":500},"sourceCallId":{"type":"string","description":"The call the agent blocked from (widget post-call card).","format":"uuid"}},"required":["phone"]},"UpdateBlockedNumberDto":{"type":"object","properties":{"reason":{"type":"string","description":"Omit to leave unchanged; empty string clears the note.","maxLength":500}}},"UpdatePresenceDto":{"type":"object","properties":{"status":{"type":"string","enum":["ACTIVE","BUSY","AWAY","OFFLINE"]}},"required":["status"]},"ConnectWhatsAppDto":{"type":"object","properties":{"code":{"type":"string","description":"OAuth authorization code, exchanged server-side for an access token.","minLength":1},"wabaId":{"type":"string","description":"WhatsApp Business Account id selected during Embedded Signup.","minLength":1},"phoneNumberId":{"type":"string","description":"Meta phone-number id the user selected — must be among `fetchPhoneNumbers`'s results.","minLength":1}},"required":["code","wabaId","phoneNumberId"]},"WhatsAppTemplateLocationDto":{"type":"object","properties":{"latitude":{"type":"string"},"longitude":{"type":"string"},"name":{"type":"string","minLength":1,"maxLength":100},"address":{"type":"string","minLength":1,"maxLength":200}},"required":["latitude","longitude","name","address"]},"WhatsAppTemplateButtonDto":{"type":"object","properties":{"type":{"type":"string","enum":["QUICK_REPLY","URL","PHONE_NUMBER","COPY_CODE"]},"text":{"type":"string","description":"WhatsApp labels a COPY_CODE button itself (\"Copy offer code\"), so that\none type carries no author text — every other type requires it.","minLength":1,"maxLength":25},"url":{"type":"string","description":"Required for a `URL` button (Meta rejects a URL button with no url) —\n`@ValidateIf` gates `@IsUrl` on `type`, rather than `@IsOptional`,\nwhich had let a `URL` button through with `url` entirely absent\n(SP2 final-review adjacent minor). Stays untouched/unvalidated for\nevery other type, none of which carry a url.","format":"uri"},"phoneNumber":{"type":"string","description":"Required for a `PHONE_NUMBER` button — Meta dials exactly this.","pattern":"^\\+[1-9]\\d{6,14}$"},"example":{"type":"string","description":"Required for a `COPY_CODE` button — the coupon, at submit AND at send.","minLength":1,"maxLength":15}},"required":["type","text"]},"WhatsAppTemplateCardDto":{"type":"object","properties":{"mediaAssetId":{"type":"string","format":"uuid"},"mediaUrl":{"type":"string","nullable":true,"maxLength":2048},"filename":{"type":"string","nullable":true,"maxLength":255},"contentType":{"type":"string","nullable":true,"maxLength":255},"body":{"type":"string","nullable":true,"description":"Meta's card caption ceiling is 160, far below the 1024 of a body.","maxLength":160},"buttons":{"maxItems":2,"type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateButtonDto"}}},"required":["mediaAssetId"]},"WhatsAppTemplateOfferDto":{"type":"object","properties":{"text":{"type":"string","description":"Meta renders this next to the countdown and caps it at 16 characters.","minLength":1,"maxLength":16},"hasExpiration":{"type":"boolean"},"expirationHours":{"type":"number","nullable":true,"description":"Hours from send until the countdown ends — required once `hasExpiration`\nis on, and meaningless otherwise. A duration rather than a date because a\ntemplate is sent many times.","minimum":1,"maximum":8760}},"required":["text","hasExpiration"]},"WhatsAppTemplateVariableFallbackDto":{"type":"object","properties":{"key":{"type":"string","description":"A merge tag (`first_name`), a position (`1`) or a Meta parameter name."},"value":{"type":"string","maxLength":120}},"required":["key","value"]},"CreateWhatsAppTemplateDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"purpose":{"type":"string","enum":["appointment_reminder","order_update","welcome","follow_up","promotion","other"]},"category":{"type":"string","description":"Required ONLY when `purpose === 'other'` — every mapped purpose derives\nits category from `PURPOSE_CATEGORY_MAP` at the service layer instead.\nWhen `purpose !== 'other'` a supplied value is still validated (rather\nthan silently accepted) but otherwise ignored by the service.","enum":["MARKETING","UTILITY"]},"language":{"type":"string","pattern":"^[a-z]{2}(_[A-Z]{2})?$"},"headerFormat":{"type":"string","description":"Which component the message leads with. Omitted means `NONE`.","enum":["NONE","TEXT","IMAGE","VIDEO","DOCUMENT","LOCATION"]},"headerText":{"type":"string","maxLength":60},"headerMediaAssetId":{"type":"string","description":"The media-library asset behind an IMAGE/VIDEO/DOCUMENT header. Required\nfor those formats — Meta needs a sample to approve and a link to send.","format":"uuid"},"headerLocation":{"description":"Required for a LOCATION header, meaningless for every other format.","allOf":[{"$ref":"#/components/schemas/WhatsAppTemplateLocationDto"}]},"bodyText":{"type":"string","minLength":1,"maxLength":1024},"footerText":{"type":"string","maxLength":60},"buttons":{"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateButtonDto"}},"cards":{"description":"CAROUSEL only. Sending a non-empty array is what MAKES a template a\ncarousel — there is no separate type field. Meta's 2-card floor is checked\nat submit rather than here so a half-built draft can still be saved.","minItems":0,"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateCardDto"}},"limitedTimeOffer":{"nullable":true,"description":"LIMITED_TIME_OFFER only. Present is what MAKES it an offer template.","type":"object","allOf":[{"$ref":"#/components/schemas/WhatsAppTemplateOfferDto"}]},"variableFallbacks":{"description":"What each variable becomes when the contact has no value for it. A send\nsetting, not part of what Meta approves — see `variable_fallbacks`.","type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateVariableFallbackDto"}}},"required":["name","purpose","bodyText"]},"UpdateWhatsAppTemplateDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"purpose":{"type":"string","enum":["appointment_reminder","order_update","welcome","follow_up","promotion","other"]},"category":{"type":"string","description":"Required ONLY when `purpose === 'other'`; validated when supplied otherwise.","enum":["MARKETING","UTILITY"]},"language":{"type":"string","pattern":"^[a-z]{2}(_[A-Z]{2})?$"},"headerFormat":{"type":"string","enum":["NONE","TEXT","IMAGE","VIDEO","DOCUMENT","LOCATION"]},"headerText":{"type":"string","maxLength":60},"headerMediaAssetId":{"type":"string","description":"See `CreateWhatsAppTemplateDto` — required for a media header.","format":"uuid"},"headerLocation":{"$ref":"#/components/schemas/WhatsAppTemplateLocationDto"},"bodyText":{"type":"string","minLength":1,"maxLength":1024},"footerText":{"type":"string","maxLength":60},"buttons":{"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateButtonDto"}},"cards":{"description":"CAROUSEL only — pass `[]` to turn a carousel back into a plain template.","minItems":0,"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateCardDto"}},"limitedTimeOffer":{"nullable":true,"description":"LIMITED_TIME_OFFER only — pass `null` to drop the offer strip.","type":"object","allOf":[{"$ref":"#/components/schemas/WhatsAppTemplateOfferDto"}]},"variableFallbacks":{"description":"What each variable becomes when the contact has no value for it. A send\nsetting, not part of what Meta approves — see `variable_fallbacks`.","type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateVariableFallbackDto"}}}},"WhatsAppTemplateButtonSendSettingDto":{"type":"object","properties":{"index":{"type":"number","minimum":0,"maximum":9},"urlSuffix":{"type":"string","description":"Replaces `{{1}}` in the button's url. Empty clears the operator's value.","maxLength":2000}},"required":["index","urlSuffix"]},"UpdateWhatsAppTemplateSendSettingsDto":{"type":"object","properties":{"headerLocation":{"$ref":"#/components/schemas/WhatsAppTemplateLocationDto"},"offerExpirationHours":{"type":"number","description":"Same bounds as `WhatsAppTemplateOfferDto.expirationHours` — 1 hour to 1 year.","minimum":1,"maximum":8760},"buttons":{"type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateButtonSendSettingDto"}},"variableFallbacks":{"description":"Replaces the whole fallback map. Allowed in any status: Meta never sees a\nfallback, so changing one needs no re-submission.","type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplateVariableFallbackDto"}}}},"UpdateWhatsAppConsentDto":{"type":"object","properties":{"optedIn":{"type":"boolean","description":"`true` opts the contact in to WhatsApp, `false` opts them out."}},"required":["optedIn"]},"MockInboundSmsDto":{"type":"object","properties":{"channelIdentityId":{"type":"string","format":"uuid"},"toNumber":{"type":"string"},"fromNumber":{"type":"string"},"body":{"type":"string"}},"required":["fromNumber","body"]},"CreateJoinLinkDto":{"type":"object","properties":{"type":{"type":"string","enum":["WEB_FORM"]},"name":{"type":"string","minLength":1,"maxLength":255},"slug":{"type":"string","minLength":3,"maxLength":50},"description":{"type":"string","nullable":true,"maxLength":500},"segmentId":{"type":"string","nullable":true,"format":"uuid"},"tagIds":{"type":"array","items":{"type":"string","format":"uuid"}},"optionalFields":{"type":"array","items":{"type":"string","enum":["EMAIL","STATE","LAST_NAME","STREET_ADDRESS","ADDRESS_LINE_2","CITY","POSTAL_CODE","COUNTRY"]}},"consentRequired":{"type":"boolean"},"consentMessage":{"type":"string","minLength":1,"maxLength":500},"requireOtp":{"type":"boolean"},"welcomeTemplateId":{"type":"string","nullable":true,"description":"Optional reference to the welcome-message template the message was seeded\nfrom. Stored for provenance only — `welcomeMessage` is what gets sent.","format":"uuid"},"welcomeMessage":{"type":"string","nullable":true,"description":"The actual welcome SMS text (raw body with merge tags) sent to a new\ncontact after submission. Source of truth at send time; null/empty = no\nwelcome message.","maxLength":1600},"welcomeMediaUrls":{"type":"array","items":{"type":"string"}},"thankYouMessage":{"type":"string","nullable":true,"maxLength":1000},"redirectUrl":{"type":"string","nullable":true,"maxLength":500,"format":"uri"},"primaryColor":{"type":"string"},"backgroundColor":{"type":"string"},"status":{"type":"string","enum":["ACTIVE","INACTIVE","ARCHIVED"]}},"required":["type","name"]},"JoinLinkSegmentRefDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"JoinLinkTagColorDto":{"type":"object","properties":{"fg":{"type":"string"},"bg":{"type":"string"}},"required":["fg","bg"]},"JoinLinkTagRefDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/JoinLinkTagColorDto"}]}},"required":["id","name","color"]},"JoinLinkWelcomeTemplateRefDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"category":{"type":"string","enum":["MARKETING","SALES","GENERAL","PROMOTIONAL","TRANSACTIONAL","EVENT","ONBOARDING","SUPPORT"]}},"required":["id","name","category"]},"JoinLinkAdminResponseDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"type":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"segmentId":{"type":"string","nullable":true},"optionalFields":{"type":"array","items":{"type":"string","enum":["EMAIL","STATE","LAST_NAME","STREET_ADDRESS","ADDRESS_LINE_2","CITY","POSTAL_CODE","COUNTRY"]}},"consentRequired":{"type":"boolean"},"consentMessage":{"type":"string"},"requireOtp":{"type":"boolean"},"welcomeTemplateId":{"type":"string","nullable":true},"welcomeMessage":{"type":"string","nullable":true},"thankYouMessage":{"type":"string","nullable":true},"redirectUrl":{"type":"string","nullable":true},"primaryColor":{"type":"string"},"backgroundColor":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE","ARCHIVED"],"type":"string"},"qrCodeKey":{"type":"string","nullable":true},"scanCount":{"type":"number"},"viewCount":{"type":"number"},"submissionCount":{"type":"number"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"segment":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/JoinLinkSegmentRefDto"}]},"tags":{"type":"array","items":{"$ref":"#/components/schemas/JoinLinkTagRefDto"}},"welcomeTemplate":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/JoinLinkWelcomeTemplateRefDto"}]},"publicUrl":{"type":"string","description":"Canonical public share URL computed from `PUBLIC_APP_URL`."},"qrUrl":{"type":"string","description":"`publicUrl` + `?qr=1` — the exact string this join link's QR code\n encodes. Encode verbatim; scan analytics depend on the `?qr=1` suffix."},"qrDesign":{"nullable":true,"description":"Saved QR design, or `null` until the owner customizes it via `PUT :id/qr-design`.","type":"object","allOf":[{"$ref":"#/components/schemas/QrDesignDto"}]}},"required":["id","organizationId","type","slug","name","description","segmentId","optionalFields","consentRequired","consentMessage","requireOtp","welcomeTemplateId","welcomeMessage","thankYouMessage","redirectUrl","primaryColor","backgroundColor","status","qrCodeKey","scanCount","viewCount","submissionCount","createdAt","updatedAt","segment","tags","welcomeTemplate","publicUrl","qrUrl","qrDesign"]},"JoinLinkStatsDto":{"type":"object","properties":{"totalLinks":{"type":"number"},"totalSubmissions":{"type":"number"},"activeLinks":{"type":"number"}},"required":["totalLinks","totalSubmissions","activeLinks"]},"SuggestSlugDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255}},"required":["name"]},"UpdateJoinLinkDto":{"type":"object","properties":{}},"BulkDeleteJoinLinksDto":{"type":"object","properties":{"ids":{"minItems":1,"type":"array","items":{"type":"string","format":"uuid"}}},"required":["ids"]},"PublicJoinLinkConfigDto":{"type":"object","properties":{"type":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"organizationDisplayName":{"type":"string"},"description":{"type":"string","nullable":true},"primaryColor":{"type":"string"},"backgroundColor":{"type":"string"},"thankYouMessage":{"type":"string","nullable":true},"optionalFields":{"type":"array","items":{"type":"string","enum":["EMAIL","STATE","LAST_NAME","STREET_ADDRESS","ADDRESS_LINE_2","CITY","POSTAL_CODE","COUNTRY"]}},"consentRequired":{"type":"boolean"},"consentMessage":{"type":"string","nullable":true},"requireOtp":{"type":"boolean"},"redirectUrl":{"type":"string","nullable":true}},"required":["type","slug","name","organizationDisplayName","description","primaryColor","backgroundColor","thankYouMessage","optionalFields","consentRequired","consentMessage","requireOtp","redirectUrl"]},"TrackViewDto":{"type":"object","properties":{"visitorId":{"type":"string","format":"uuid"},"source":{"type":"string","enum":["WEB","QR"]},"utmSource":{"type":"string","maxLength":255},"utmMedium":{"type":"string","maxLength":255},"utmCampaign":{"type":"string","maxLength":255},"utmContent":{"type":"string","maxLength":255},"utmTerm":{"type":"string","maxLength":255},"fbclid":{"type":"string","maxLength":255},"gclid":{"type":"string","maxLength":255},"msclkid":{"type":"string","maxLength":255},"landingUrl":{"type":"string","maxLength":2000,"format":"uri"}}},"SendJoinLinkOtpDto":{"type":"object","properties":{"phone":{"type":"string","maxLength":32}},"required":["phone"]},"SubmitJoinLinkDto":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"phone":{"type":"string","maxLength":32},"lastName":{"type":"string","maxLength":100},"email":{"type":"string","maxLength":255,"format":"email"},"streetAddress":{"type":"string","maxLength":255},"addressLine2":{"type":"string","maxLength":255},"city":{"type":"string","maxLength":100},"state":{"type":"string","maxLength":100},"postalCode":{"type":"string","maxLength":20,"pattern":"^[\\p{L}\\p{N}\\s-]+$"},"country":{"type":"string","maxLength":100},"consent":{"type":"boolean"},"otp":{"type":"string","minLength":4,"maxLength":10},"utmSource":{"type":"string","maxLength":255},"utmMedium":{"type":"string","maxLength":255},"utmCampaign":{"type":"string","maxLength":255},"utmContent":{"type":"string","maxLength":255},"utmTerm":{"type":"string","maxLength":255},"fbclid":{"type":"string","maxLength":255},"gclid":{"type":"string","maxLength":255},"msclkid":{"type":"string","maxLength":255},"landingUrl":{"type":"string","maxLength":2000,"format":"uri"}},"required":["firstName","phone"]},"JoinLinkSubmitResponseDto":{"type":"object","properties":{"contactId":{"type":"string"},"redirectUrl":{"type":"string","nullable":true},"thankYouMessage":{"type":"string","nullable":true}},"required":["contactId","redirectUrl","thankYouMessage"]},"WelcomeTemplateResponseDto":{"type":"object","properties":{"id":{"type":"string"},"organizationId":{"type":"string","nullable":true},"isSystem":{"type":"boolean"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"category":{"enum":["MARKETING","SALES","GENERAL","PROMOTIONAL","TRANSACTIONAL","EVENT","ONBOARDING","SUPPORT"],"type":"string"},"body":{"type":"string"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","organizationId","isSystem","name","description","category","body","createdAt","updatedAt"]},"WizardBusinessHoursDto":{"type":"object","properties":{"weekly":{"$ref":"#/components/schemas/BusinessHoursWeeklyDto"},"overrides":{"type":"array","items":{"$ref":"#/components/schemas/BusinessHoursOverrideDto"}}},"required":["weekly"]},"ServiceAreaDto":{"type":"object","properties":{"zipCodes":{"type":"array","items":{"type":"string","maxLength":20}},"radiusMiles":{"type":"number","minimum":0,"maximum":500},"centerPostalCode":{"type":"string","maxLength":20},"description":{"type":"string","maxLength":500}}},"BookingDestinationDto":{"type":"object","properties":{"kind":{"enum":["MEETING_TYPE","URL","PHONE"],"type":"string"},"meetingTypeId":{"type":"string","format":"uuid"},"url":{"type":"string","maxLength":2048,"format":"uri"},"phone":{"type":"string","maxLength":50}},"required":["kind"]},"WizardLeadProfileDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"timezone":{"type":"string"},"businessHours":{"$ref":"#/components/schemas/WizardBusinessHoursDto"},"primaryTrade":{"type":"string","enum":["HVAC","PLUMBING","ELECTRICAL","ROOFING","OTHER"]},"serviceArea":{"$ref":"#/components/schemas/ServiceAreaDto"},"afterHoursPolicy":{"type":"string","enum":["AI_RESPONDS","ACK_ONLY","EMERGENCY_LINE"]},"emergencyPhone":{"type":"string","maxLength":50},"bookingDestination":{"$ref":"#/components/schemas/BookingDestinationDto"}}},"WizardLeadSourceDto":{"type":"object","properties":{"choice":{"type":"string","enum":["WEBSITE_FORM","WEB_CHAT","SMS","IMPORT","SAMPLE_LEAD"]}},"required":["choice"]},"WizardAiPolicyDto":{"type":"object","properties":{"aiReplyPolicy":{"type":"string","enum":["DRAFT_FOR_APPROVAL","AUTO_SEND"]},"autoAcknowledge":{"type":"boolean"},"escalationPresets":{"type":"array","description":"Retired triggers are accepted (stale browsers) and dropped by the service.","items":{"type":"string","enum":["CUSTOMER_ASKS_HUMAN","CUSTOMER_REQUESTS_MANAGER","REPEATED_MISUNDERSTANDING","SENSITIVE_QUESTION","LEGAL_REQUEST","MEDICAL_REQUEST","EMERGENCY_REQUEST","OUT_OF_SERVICE_AREA","BOOKING_NEEDS_PERSON","REFUND_REQUEST","NEGATIVE_SENTIMENT","AI_NOT_CONFIDENT","PAYMENT_ISSUE","PRICING_EXCEPTION"]}}},"required":["aiReplyPolicy","autoAcknowledge","escalationPresets"]},"WizardAdvanceDto":{"type":"object","properties":{"step":{"type":"number","minimum":1,"maximum":6}},"required":["step"]},"WizardBusinessDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"website":{"type":"string","maxLength":500,"format":"uri"},"industry":{"type":"string","maxLength":100},"timezone":{"type":"string"}}},"CreateWebhookEndpointDto":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri"},"label":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":2000},"subscribedEvents":{"minItems":1,"type":"array","items":{"type":"string"}},"customHeaders":{"type":"object","additionalProperties":{"type":"string"}},"isActive":{"type":"boolean"},"enableSigning":{"type":"boolean","description":"Optional payload signing (default true). When false, deliveries are unsigned."}},"required":["url","label","subscribedEvents"]},"UpdateWebhookEndpointDto":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri"},"label":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":2000},"subscribedEvents":{"minItems":1,"type":"array","items":{"type":"string"}},"customHeaders":{"type":"object","additionalProperties":{"type":"string"}},"isActive":{"type":"boolean"},"enableSigning":{"type":"boolean","description":"Set false to clear the signing secret (endpoint becomes unsigned)."}}},"AiDraftRequestDto":{"type":"object","properties":{"action":{"enum":["REPHRASE_FORMAL","REPHRASE_CASUAL","CORRECT_GRAMMAR","BRIEF","EXPAND","COMPOSE"],"type":"string"},"target":{"default":"REPLY","enum":["REPLY","NOTE"],"type":"string"},"channel":{"enum":["SMS","WHATSAPP","EMAIL","WEBCHAT","VOICE"],"type":"string"},"text":{"type":"string","description":"The composer's current contents. PLAIN TEXT ONLY, and capped far below the\nemail body limit: sending rendered HTML would blow the context window and\nmake the model emit HTML the sanitizer then has to fight. Over the cap is\na 400 rather than a silent truncation — rewriting half of someone's\nmessage without telling them is the worse failure.","minLength":1,"maxLength":4000},"instruction":{"type":"string","description":"Optional steer for AI Compose. Ignored by the rewrite actions.","maxLength":500},"useConversationContext":{"type":"boolean","description":"Opt-in to recent-thread context. Defaults false so a plain rewrite never\nships customer message bodies to the LLM proxy as a side effect.","default":false},"unifiedConversationId":{"type":"string","description":"Required (and tenant-checked) whenever context is requested; otherwise\noptional so conversation-less surfaces (the contact-drawer compose) can\ndraft without a thread. Deliberately NOT `@IsOptional()` + `@IsUUID()`:\nthat combination would skip validation on `undefined` even when\n`useConversationContext` is true, letting an id-less context request\nreach the service. The two-branch `@ValidateIf` makes the id\nrequired-when-context and UUID-validated-whenever-present.","format":"uuid"}},"required":["action","target","channel"]},"AiDraftResponseDto":{"type":"object","properties":{"action":{"description":"Echoed back so a composer that fired two actions can discard a response\nthat arrives out of order instead of applying the wrong rewrite.","enum":["REPHRASE_FORMAL","REPHRASE_CASUAL","CORRECT_GRAMMAR","BRIEF","EXPAND","COMPOSE"],"type":"string"},"target":{"enum":["REPLY","NOTE"],"type":"string"},"text":{"type":"string","description":"Sanitized draft. Guaranteed non-empty — the service fails instead."},"modelId":{"type":"string"},"draftId":{"type":"string","description":"Credit-hold reference id, for correlating a ledger entry with a click.","format":"uuid"},"inputTokens":{"type":"number","nullable":true},"outputTokens":{"type":"number","nullable":true}},"required":["action","target","text","modelId","draftId","inputTokens","outputTokens"]},"ConnectJobNimbusDto":{"type":"object","properties":{"apiKey":{"type":"string","minLength":8,"maxLength":4096}},"required":["apiKey"]},"StatusMapEntryDto":{"type":"object","properties":{"recordTypeName":{"type":"string","description":"JobNimbus `record_type_name` — the workflow the status lives in, or `''`\nfor a record that has none.\n\n**Blank is a real value here, not a missing field**, which is why there is\nno `@MinLength(1)`. JobNimbus estimates and invoices carry no\n`record_type_name`: `composeJobNimbusStatus` stores the status on its own,\nand `listObserved` hands the pair back with a blank workflow. Requiring a\ncharacter refused the whole PUT over one such row — 400 for the request,\nevery other row's edit on the screen lost with it, and those statuses\nunmappable for good, which meant their finished jobs stayed OPEN and never\nbecame revenue. The lookup already keys on the composite, and for these\nrecords the composite IS the bare status, so a blank workflow maps exactly\nthe records it came from.","maxLength":120},"statusName":{"type":"string","description":"JobNimbus `status_name` — free text the business typed.\n\nStill required: with no workflow it is the whole of the mapping's key, so a\nblank one is a row that maps nothing.","minLength":1,"maxLength":120},"state":{"type":"string","description":"What that status means here: Open / Won / Lost / Completed / Cancelled.","enum":["OPEN","CANCELLED","LOST","COMPLETED","WON"]}},"required":["recordTypeName","statusName","state"]},"UpdateStatusMapDto":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/StatusMapEntryDto"}}},"required":["entries"]},"MatchLinkDto":{"type":"object","properties":{"contactId":{"type":"string","format":"uuid"}},"required":["contactId"]},"SendLeadDto":{"type":"object","properties":{"connectionId":{"type":"string","format":"uuid"}},"required":["connectionId"]},"VoiceSettingsDto":{"type":"object","properties":{"voiceId":{"type":"string","maxLength":80},"model":{"type":"string","enum":["eleven_multilingual_v2","eleven_turbo_v2","eleven_turbo_v2_5","eleven_flash_v2","eleven_flash_v2_5","eleven_monolingual_v1","eleven_v3"]},"stability":{"type":"number","minimum":0,"maximum":1},"similarityBoost":{"type":"number","minimum":0,"maximum":1},"style":{"type":"number","minimum":0,"maximum":1},"useSpeakerBoost":{"type":"boolean"},"speed":{"type":"number","minimum":0.7,"maximum":1.2},"optimizeStreamingLatency":{"type":"number","minimum":0,"maximum":4}}},"TranscriberSettingsDto":{"type":"object","properties":{"language":{"type":"string","enum":["en","en-US","en-GB","en-AU","en-CA","es","fr","de","pt","pt-BR","it","nl","multi"]}}},"StartSpeakingPlanDto":{"type":"object","properties":{"waitSeconds":{"type":"number","minimum":0,"maximum":5}}},"StopSpeakingPlanDto":{"type":"object","properties":{"numWords":{"type":"number","minimum":0,"maximum":10},"voiceSeconds":{"type":"number","minimum":0,"maximum":0.5},"backoffSeconds":{"type":"number","minimum":0,"maximum":10}}},"AudioSettingsDto":{"type":"object","properties":{"backgroundSound":{"type":"string","description":"`off` | `office` | a URL — the mapper decides which it is.","maxLength":500},"denoisingEnabled":{"type":"boolean"},"maxDurationSeconds":{"type":"number","minimum":10,"maximum":900},"startSpeakingPlan":{"$ref":"#/components/schemas/StartSpeakingPlanDto"},"stopSpeakingPlan":{"$ref":"#/components/schemas/StopSpeakingPlanDto"}}},"VoicemailSettingsDto":{"type":"object","properties":{"enabled":{"type":"boolean"},"beepMaxAwaitSeconds":{"type":"number","minimum":0,"maximum":30},"message":{"type":"string","maxLength":1000}}},"UpdateVoiceAgentConfigDto":{"type":"object","properties":{"aiAgentId":{"type":"string","nullable":true,"deprecated":true,"format":"uuid"},"monthlyMinuteAlert":{"type":"number","deprecated":true,"minimum":0,"maximum":100000},"firstMessage":{"type":"string","maxLength":2000},"firstMessageMode":{"type":"string","enum":["assistant-speaks-first","assistant-speaks-first-with-model-generated-message","assistant-waits-for-user"]},"systemPromptOverride":{"type":"string","nullable":true,"maxLength":20000},"voice":{"$ref":"#/components/schemas/VoiceSettingsDto"},"transcriber":{"$ref":"#/components/schemas/TranscriberSettingsDto"},"audio":{"$ref":"#/components/schemas/AudioSettingsDto"},"voicemail":{"$ref":"#/components/schemas/VoicemailSettingsDto"},"endCallMessage":{"type":"string","nullable":true,"maxLength":1000},"endCallPhrases":{"type":"array","items":{"type":"string","maxLength":140,"minLength":2}},"transferNumber":{"type":"string","nullable":true},"outsideAreaTransferNumber":{"type":"string","nullable":true},"forwardWhen":{"type":"string","enum":["ALWAYS","BUSINESS_HOURS"]},"transferMode":{"type":"string","enum":["WARM","COLD"]},"forwardingRules":{"type":"array","items":{"$ref":"#/components/schemas/ForwardingRuleDto"}},"answerSchedule":{"description":"Pause answering while the team is open — Phase 8's reply schedule, saved whole.","allOf":[{"$ref":"#/components/schemas/ReplyScheduleDto"}]},"afterHoursBehavior":{"type":"string","enum":["FOLLOW_LEAD_PROFILE","AGENT_ANSWERS","MESSAGE_ONLY","TRANSFER"]},"recordingEnabled":{"type":"boolean"},"recordingDisclosure":{"type":"string","nullable":true,"maxLength":300}},"required":["firstMessage","firstMessageMode","afterHoursBehavior","recordingEnabled"]},"AdoptVoiceDto":{"type":"object","properties":{"voiceId":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[A-Za-z0-9_-]+$"}},"required":["voiceId"]},"AttachVoiceAgentNumberDto":{"type":"object","properties":{"mode":{"enum":["buy","import","existing"],"type":"string"},"areaCode":{"type":"string","description":"Buy only (secondary) — three digits.","pattern":"^\\d{3}$"},"channelIdentityId":{"type":"string","description":"Import only — the organisation's ChannelIdentity.","format":"uuid"},"telnyxCredentialId":{"type":"string","description":"Import of a TELNYX identity only, and required then: the Telnyx credential\nthe operator created in the VAPI dashboard (dashboard.vapi.ai/keys). An id,\nnot a secret. Refused on a Twilio identity.","maxLength":80},"vapiPhoneNumberId":{"type":"string","description":"Existing only, and required then: the id of a number bought in the owner's voice account — a UUID (F-M1).","format":"uuid"}},"required":["mode"]},"TestCallDto":{"type":"object","properties":{"toNumber":{"type":"string"}},"required":["toNumber"]},"CreateEmployeePhoneDto":{"type":"object","properties":{"voiceId":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[A-Za-z0-9_-]+$"}}},"UpdateEmployeePhoneDto":{"type":"object","properties":{"firstMessage":{"type":"string","maxLength":2000},"firstMessageMode":{"type":"string","enum":["assistant-speaks-first","assistant-speaks-first-with-model-generated-message","assistant-waits-for-user"]},"systemPromptOverride":{"type":"string","nullable":true,"maxLength":20000},"voice":{"$ref":"#/components/schemas/VoiceSettingsDto"},"transcriber":{"$ref":"#/components/schemas/TranscriberSettingsDto"},"audio":{"$ref":"#/components/schemas/AudioSettingsDto"},"voicemail":{"$ref":"#/components/schemas/VoicemailSettingsDto"},"endCallMessage":{"type":"string","nullable":true,"maxLength":1000},"endCallPhrases":{"type":"array","items":{"type":"string","maxLength":140,"minLength":2}},"transferNumber":{"type":"string","nullable":true},"outsideAreaTransferNumber":{"type":"string","nullable":true},"forwardWhen":{"type":"string","enum":["ALWAYS","BUSINESS_HOURS"]},"transferMode":{"type":"string","enum":["WARM","COLD"]},"forwardingRules":{"type":"array","items":{"$ref":"#/components/schemas/ForwardingRuleDto"}},"answerSchedule":{"description":"Pause answering while the team is open — Phase 8's reply schedule, saved whole.","allOf":[{"$ref":"#/components/schemas/ReplyScheduleDto"}]},"afterHoursBehavior":{"type":"string","enum":["FOLLOW_LEAD_PROFILE","AGENT_ANSWERS","MESSAGE_ONLY","TRANSFER"]},"recordingEnabled":{"type":"boolean"},"recordingDisclosure":{"type":"string","nullable":true,"maxLength":300}},"required":["firstMessage","firstMessageMode","afterHoursBehavior","recordingEnabled"]},"ReplaceVoiceAgentNumberDto":{"type":"object","properties":{"channelIdentityId":{"type":"string","format":"uuid"},"telnyxCredentialId":{"type":"string","description":"A Telnyx identity only, and required then; refused on a Twilio one.","maxLength":80}},"required":["channelIdentityId"]},"UpdateVoiceAgentOrgSettingsDto":{"type":"object","properties":{"monthlyMinuteAlert":{"type":"number","minimum":0,"maximum":100000}},"required":["monthlyMinuteAlert"]},"QualificationQuestionDto":{"type":"object","properties":{"key":{"type":"string","maxLength":60},"question":{"type":"string","maxLength":200}},"required":["key","question"]},"UpdateLeadProfileDto":{"type":"object","properties":{"primaryTrade":{"enum":["HVAC","PLUMBING","ELECTRICAL","ROOFING","OTHER"],"type":"string"},"serviceArea":{"$ref":"#/components/schemas/ServiceAreaDto"},"afterHoursPolicy":{"enum":["AI_RESPONDS","ACK_ONLY","EMERGENCY_LINE"],"type":"string"},"emergencyPhone":{"type":"string","nullable":true,"description":"`null` clears the stored number (`@IsOptional` lets it through unvalidated).","maxLength":50},"bookingDestination":{"$ref":"#/components/schemas/BookingDestinationDto"},"responseSlaMinutes":{"type":"number","minimum":1,"maximum":1440},"aiReplyPolicy":{"enum":["DRAFT_FOR_APPROVAL","AUTO_SEND"],"type":"string"},"autoAcknowledge":{"type":"boolean"},"escalationPresets":{"type":"array","items":{"type":"string","maxLength":100}},"leadSourceChoice":{"enum":["WEBSITE_FORM","WEB_CHAT","SMS","IMPORT","SAMPLE_LEAD"],"type":"string"},"qualificationQuestions":{"type":"array","items":{"$ref":"#/components/schemas/QualificationQuestionDto"}}}},"ApplyTradePackDto":{"type":"object","properties":{"dryRun":{"type":"boolean","description":"Report the plan without writing. Omitted: a first apply writes, a re-apply only reports."}}},"GetBugReportUploadUrlDto":{"type":"object","properties":{"fileName":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","minLength":1,"maxLength":255},"sizeBytes":{"type":"number","description":"Client-declared, used only to reject an oversized upload BEFORE issuing a\npresigned URL. The persisted size is re-read from storage on confirm —\na presigned PUT carries no size condition, so this value is a courtesy,\nnever a control.","minimum":1,"maximum":26214400}},"required":["fileName","contentType","sizeBytes"]},"BugReportAttachmentInputDto":{"type":"object","properties":{"storageKey":{"type":"string","minLength":1,"maxLength":1024},"fileName":{"type":"string","minLength":1,"maxLength":255},"contentType":{"type":"string","minLength":1,"maxLength":255}},"required":["storageKey","fileName","contentType"]},"CreateBugReportDto":{"type":"object","properties":{"type":{"type":"string","description":"What the reporter is telling us. Optional so an older client keeps\nworking; the column defaults to BUG, which is what an unlabelled report\nalmost always is.","enum":["BUG","FEATURE","SUPPORT"]},"title":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","minLength":1,"maxLength":10000},"pageUrl":{"type":"string","description":"The in-app path the reporter was on, captured by the dialog.","maxLength":2048},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/BugReportAttachmentInputDto"}}},"required":["title","description"]},"CreateBugReportCommentDto":{"type":"object","properties":{"body":{"type":"string","description":"May be empty when the reply carries a file — a screenshot on its own is\na complete message. \"Empty AND no attachment\" is rejected in the service\nrather than here, because only it can see whether the claimed uploads\nactually landed.","maxLength":10000},"attachments":{"description":"Proof attached to this reply, claimed the same way a new report claims\nits own: presigned and uploaded first, then named here by storage key.\nThe service re-checks ownership and reads the real size back from\nstorage, so nothing on this list is trusted as sent.","type":"array","items":{"$ref":"#/components/schemas/BugReportAttachmentInputDto"}}},"required":["body"]},"WidgetBrandingDto":{"type":"object","properties":{"primaryColor":{"type":"string"},"position":{"type":"string","enum":["left","right"]},"launcherIcon":{"type":"string","description":"Image URL for the floating launcher button's glyph, replacing the\nbuilt-in speech-bubble SVG. Validated exactly like `avatarUrl`/`logoUrl`\n— it used to be `@IsString() @MaxLength(50)`, which read as an icon NAME\nfrom a built-in set and contradicted the settings form's own `z.url()`\nrule, rejecting any realistic image URL.","maxLength":500,"format":"uri"},"avatarUrl":{"type":"string","maxLength":500,"format":"uri"},"logoUrl":{"type":"string","maxLength":500,"format":"uri"}}},"WidgetQuickActionDto":{"type":"object","properties":{"id":{"type":"string","maxLength":40},"label":{"type":"string","maxLength":60},"message":{"type":"string","maxLength":500}},"required":["id","label","message"]},"WidgetTimeRangeDto":{"type":"object","properties":{"start":{"type":"string"},"end":{"type":"string"}},"required":["start","end"]},"WidgetWeeklyHoursDto":{"type":"object","properties":{"mon":{"type":"array","items":{"$ref":"#/components/schemas/WidgetTimeRangeDto"}},"tue":{"type":"array","items":{"$ref":"#/components/schemas/WidgetTimeRangeDto"}},"wed":{"type":"array","items":{"$ref":"#/components/schemas/WidgetTimeRangeDto"}},"thu":{"type":"array","items":{"$ref":"#/components/schemas/WidgetTimeRangeDto"}},"fri":{"type":"array","items":{"$ref":"#/components/schemas/WidgetTimeRangeDto"}},"sat":{"type":"array","items":{"$ref":"#/components/schemas/WidgetTimeRangeDto"}},"sun":{"type":"array","items":{"$ref":"#/components/schemas/WidgetTimeRangeDto"}}}},"WidgetBusinessHoursDto":{"type":"object","properties":{"mode":{"type":"string","enum":["ALWAYS","SCHEDULED"]},"timezone":{"type":"string","maxLength":64},"weekly":{"$ref":"#/components/schemas/WidgetWeeklyHoursDto"}}},"WidgetGreetingRuleConditionDto":{"type":"object","properties":{"returningVisitor":{"type":"boolean"},"utmSource":{"type":"string","maxLength":100},"landingPathPrefix":{"type":"string","maxLength":200},"presence":{"type":"string","enum":["OPEN","CLOSED"]}}},"WidgetGreetingRuleDto":{"type":"object","properties":{"id":{"type":"string","maxLength":40},"when":{"$ref":"#/components/schemas/WidgetGreetingRuleConditionDto"},"greeting":{"type":"string","maxLength":500}},"required":["id","when","greeting"]},"UpdateWidgetConfigDto":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"greeting":{"type":"string","maxLength":500},"branding":{"$ref":"#/components/schemas/WidgetBrandingDto"},"quickActions":{"type":"array","items":{"$ref":"#/components/schemas/WidgetQuickActionDto"}},"aiAgentId":{"type":"string","nullable":true,"format":"uuid"},"expectedHolderId":{"type":"string","nullable":true,"format":"uuid"},"bookingEnabled":{"type":"boolean"},"meetingTypeId":{"type":"string","nullable":true,"format":"uuid"},"allowedDomains":{"type":"array","items":{"type":"string","maxLength":255}},"status":{"type":"string","enum":["ACTIVE","DISABLED"]},"businessHours":{"$ref":"#/components/schemas/WidgetBusinessHoursDto"},"offlineMessage":{"type":"string","maxLength":500},"greetingRules":{"type":"array","items":{"$ref":"#/components/schemas/WidgetGreetingRuleDto"}},"aiAfterHours":{"type":"boolean"}}},"CreateWidgetSessionDto":{"type":"object","properties":{"pageUrl":{"type":"string","maxLength":1000,"format":"uri"},"referrerUrl":{"type":"string","maxLength":1000,"format":"uri"}}},"ResumeWidgetSessionDto":{"type":"object","properties":{"pageUrl":{"type":"string","maxLength":1000},"referrerUrl":{"type":"string","maxLength":1000}}},"PostWidgetMessageDto":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":4000},"clientMessageId":{"type":"string","format":"uuid"}},"required":["body","clientMessageId"]},"PostOfflineMessageDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"email":{"type":"string","maxLength":255,"format":"email"},"phone":{"type":"string","maxLength":32},"message":{"type":"string","minLength":1,"maxLength":4000},"consentGiven":{"type":"boolean"}},"required":["name","email","message","consentGiven"]},"SituationSelectionDto":{"type":"object","properties":{"situationKey":{"type":"string","enum":["asks_question","asks_price","wants_to_book","not_ready","asks_human","upset","no_response","emergency","something_else"]},"whenKey":{"type":"string","maxLength":60},"thenKeys":{"description":"Left out: the situation's suggested options.","maxItems":12,"type":"array","items":{"type":"string","maxLength":60}},"customWhen":{"type":"string","description":"\"Something else\" only. The 160-character limit is checked after tidying the text.","maxLength":1000}},"required":["situationKey"]},"PutSituationsDto":{"type":"object","properties":{"situations":{"maxItems":40,"type":"array","items":{"$ref":"#/components/schemas/SituationSelectionDto"}}},"required":["situations"]},"GenerateJourneyDto":{"type":"object","properties":{"text":{"type":"string","minLength":3,"maxLength":600,"description":"What the owner wants the employee to do, in their own words.","example":"If a lead doesn't respond, text them after 2 hours, email them the next day and call them after 3 days. Stop if they reply or ask for a human."}},"required":["text"]},"CreateJourneyDto":{"type":"object","properties":{"journeyKey":{"type":"string","maxLength":64,"description":"Catalog key, or omit for a journey of your own (custom-<name>).","example":"lead-follow-up"},"name":{"type":"string","minLength":1,"maxLength":120,"example":"Lead follow-up"},"spec":{"type":"object","additionalProperties":true,"description":"The journey spec, version 1."},"startOff":{"type":"boolean","description":"Save it switched off (a draft). It is turned on only by its activate route. Default: the usual rule, on when everything is in place."}},"required":["name","spec"]},"UpdateJourneyDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"example":"Lead follow-up"},"spec":{"type":"object","additionalProperties":true,"description":"The whole journey spec, version 1."}},"required":["spec"]},"SetFollowUpDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"true switches the follow-up on, false pauses it"}},"required":["enabled"]},"SetEmployeeChannelDto":{"type":"object","properties":{"assigned":{"type":"boolean"},"expectedHolderId":{"type":"string","nullable":true,"format":"uuid"}},"required":["assigned"]},"ApiSuccessResponse":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","enum":[true],"example":true},"data":{"description":"Endpoint-specific payload"},"message":{"type":"string"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}},"ApiErrorResponse":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","enum":[false],"example":false},"error":{"type":"object","required":["statusCode","errorCode","code","message","traceId","timestamp"],"properties":{"statusCode":{"type":"integer","example":400},"errorCode":{"type":"integer","example":10000},"code":{"type":"string","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"Validation failed"},"details":{"nullable":true,"example":null},"traceId":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"}}}}},"PaginationMeta":{"type":"object","required":["page","limit","total","totalPages"],"properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"additionalProperties":true}}}}