{"openapi":"3.0.0","info":{"title":"X24 LABS - ADMIN API","description":"Centralized administration API for all X24 Labs applications.","version":"1.0.0","contact":{"name":"X24 Labs Team","email":"support@x24labs.com"}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT token obtained from /auth/login endpoint."},"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"API key for backend-to-backend authentication. Format: sk_appId_randomhex."}},"schemas":{}},"paths":{"/health":{"get":{"summary":"Server health check","tags":["Health"],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"timestamp":{"type":"string","format":"date-time"},"uptime":{"type":"number"},"memory":{"type":"object","properties":{"rss":{"type":"string"},"heapUsed":{"type":"string"},"heapTotal":{"type":"string"}}},"database":{"type":"object","properties":{"connected":{"type":"boolean"},"modelsCount":{"type":"integer"}}}}}}}}}}},"/auth/login":{"post":{"summary":"Back Office team login","tags":["Auth"],"description":"Authentication for internal team users using email and password","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","example":"admin@bannersallover.com"},"password":{"type":"string","format":"password","example":"password123"}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"token":{"type":"string","description":"JWT token for authentication"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","example":"admin"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/auth/refresh":{"post":{"summary":"Refresh JWT token","tags":["Auth"],"description":"Generate a new JWT token from an existing one","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"token":{"type":"string","description":"New JWT token"},"user":{"type":"object"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/auth/hash-password":{"post":{"summary":"[DEV] Generate password hash","tags":["Auth"],"description":"Development endpoint to generate bcrypt hashes for passwords","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["password"],"properties":{"password":{"type":"string","example":"mypassword123"}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"hash":{"type":"string","description":"Bcrypt hash of the password"}}}}}}}}},"/auth/me":{"get":{"summary":"Current user information","tags":["Auth"],"description":"Get authenticated user information","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string"},"role":{"type":"string"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/joinlist":{"post":{"summary":"Public newsletter signup","tags":["Joinlist"],"description":"Public capture endpoint for joinlist subscriptions. Requires `X-App-Key` (publishable pk_) and a matching `Origin` registered in the app's allowedOrigins. Routes to contacts + slack notification + welcome email. Rate-limited to 10 requests per minute per IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"appId":{"type":"string","minLength":1},"email":{"type":"string","minLength":5},"firstName":{"type":"string"},"locale":{"type":"string","enum":["en","es","fr","de","it","pt"]},"source":{"type":"string"},"referralUrl":{"type":"string"},"website":{"type":"string","description":"Honeypot. Must be empty."}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"alreadySubscribed":{"type":"boolean"},"unsubscribeUrl":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"string"}}}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"string"}}}}}}}}},"/unsubscribe/{token}":{"get":{"summary":"Public unsubscribe confirmation","tags":["Joinlist"],"description":"One-click unsubscribe via token. Always returns 200 HTML (no enumeration).","parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"token","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}}}}},"/o/{token}":{"get":{"summary":"Open tracking pixel","tags":["Email Tracking"],"description":"Returns a 1x1 transparent GIF and records an \"opened\" event. Always returns 200.","parameters":[{"schema":{"type":"string"},"in":"path","name":"token","required":true,"description":"Signed tracking token (may end with .gif)"}],"responses":{"200":{"description":"1x1 transparent GIF","content":{"application/json":{"schema":{"type":"string","description":"1x1 transparent GIF"}}}}}}},"/c/{token}":{"get":{"summary":"Click tracking redirect","tags":["Email Tracking"],"description":"Records a \"clicked\" event and 302-redirects to the original URL.","parameters":[{"schema":{"type":"string"},"in":"path","name":"token","required":true,"description":"Signed tracking token"}],"responses":{"302":{"description":"Redirect to target URL","content":{"application/json":{"schema":{"type":"string","description":"Redirect to target URL"}}}}}}},"/email-events/resend":{"post":{"summary":"Resend email webhook receiver","tags":["Webhooks"],"description":"Receives email lifecycle events from Resend (sent, delivered, bounced, etc.). Verified by HMAC signature.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"processed":{"type":"boolean"},"eventId":{"type":"string","nullable":true}}}}}}}}},"/email-events/cold-provider":{"post":{"summary":"Cold email provider webhook (stub)","tags":["Webhooks"],"description":"Placeholder endpoint for future cold-email provider integration.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}}}}},"/apps":{"get":{"summary":"List of available applications","tags":["Apps"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"app1"},"name":{"type":"string","example":"App 1"},"features":{"type":"object","properties":{"canEditTemplates":{"type":"boolean"},"canEditUsers":{"type":"boolean"},"canViewMetrics":{"type":"boolean"}}}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/users/":{"get":{"summary":"List users","tags":["Users"],"description":"Get list of admin users","parameters":[{"schema":{"type":"string","enum":["admin","user","viewer"]},"in":"query","name":"role","required":false,"description":"Filter by role"},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"isActive","required":false,"description":"Filter by active status"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"role":{"type":"string"},"isActive":{"type":"boolean"},"profile":{"type":"object","properties":{"avatar":{"type":"string"},"bio":{"type":"string"},"phone":{"type":"string"},"timezone":{"type":"string"},"language":{"type":"string"}}},"settings":{"type":"object","properties":{"notifications":{"type":"object","properties":{"email":{"type":"boolean"},"push":{"type":"boolean"}}},"theme":{"type":"string"},"defaultApp":{"type":"string"}}},"lastLoginAt":{"type":"string","format":"date-time"},"loginCount":{"type":"number"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"post":{"summary":"Create user","tags":["Users"],"description":"Create new admin user","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password","firstName","lastName"],"properties":{"email":{"type":"string","format":"email","description":"User email"},"password":{"type":"string","minLength":6,"description":"User password"},"firstName":{"type":"string","description":"First name"},"lastName":{"type":"string","description":"Last name"},"role":{"type":"string","enum":["admin","user","viewer"],"default":"user","description":"User role"},"profile":{"type":"object","properties":{"avatar":{"type":"string","description":"Avatar URL"},"bio":{"type":"string","description":"User bio","maxLength":500},"phone":{"type":"string","description":"Phone number"},"timezone":{"type":"string","description":"Timezone","default":"UTC"},"language":{"type":"string","enum":["en","es"],"default":"en","description":"Preferred language"}}},"settings":{"type":"object","properties":{"notifications":{"type":"object","properties":{"email":{"type":"boolean","default":true,"description":"Email notifications"},"push":{"type":"boolean","default":false,"description":"Push notifications"}}},"theme":{"type":"string","enum":["light","dark","auto"],"default":"auto","description":"UI theme"},"defaultApp":{"type":"string","description":"Default app ID"}}}}}}}},"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/users/{id}":{"get":{"summary":"Get user by ID","tags":["Users"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"User ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"patch":{"summary":"Update user","tags":["Users"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","description":"First name"},"lastName":{"type":"string","description":"Last name"},"role":{"type":"string","enum":["admin","user","viewer"],"description":"User role"},"isActive":{"type":"boolean","description":"Active status"},"profile":{"type":"object","properties":{"avatar":{"type":"string","description":"Avatar URL"},"bio":{"type":"string","description":"User bio","maxLength":500},"phone":{"type":"string","description":"Phone number"},"timezone":{"type":"string","description":"Timezone"},"language":{"type":"string","enum":["en","es"],"description":"Preferred language"}}},"settings":{"type":"object","properties":{"notifications":{"type":"object","properties":{"email":{"type":"boolean","description":"Email notifications"},"push":{"type":"boolean","description":"Push notifications"}}},"theme":{"type":"string","enum":["light","dark","auto"],"description":"UI theme"},"defaultApp":{"type":"string","description":"Default app ID"}}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete user","tags":["Users"],"description":"Soft delete user (sets isActive to false)","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/users/{id}/password":{"patch":{"summary":"Update user password","tags":["Users"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["password"],"properties":{"password":{"type":"string","minLength":6,"description":"New password"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/tickets/":{"get":{"summary":"List all tickets","tags":["Tickets"],"description":"Get paginated list of tickets from all apps (optionally filter by appId)","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string"},"in":"query","name":"appId","required":false,"description":"Optional: Filter by app ID"},{"schema":{"type":"string","enum":["pending","in_progress","resolved","closed"]},"in":"query","name":"status","required":false,"description":"Filter by status"},{"schema":{"type":"string","enum":["general","technical","billing","feature"]},"in":"query","name":"topic","required":false,"description":"Filter by topic"},{"schema":{"type":"string","enum":["low","normal","high","urgent"]},"in":"query","name":"priority","required":false,"description":"Filter by priority"},{"schema":{"type":"string"},"in":"query","name":"shopId","required":false,"description":"Filter by shop ID"},{"schema":{"type":"string"},"in":"query","name":"email","required":false,"description":"Filter by email"},{"schema":{"type":"string","format":"date"},"in":"query","name":"startDate","required":false,"description":"Start date filter"},{"schema":{"type":"string","format":"date"},"in":"query","name":"endDate","required":false,"description":"End date filter"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search in subject, message, and email"},{"schema":{"type":"string","default":"createdAt"},"in":"query","name":"sortBy","required":false},{"schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"in":"query","name":"sortOrder","required":false}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/tickets/{messageId}":{"get":{"summary":"Get ticket by ID","tags":["Tickets"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"messageId","required":true,"description":"Ticket ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"patch":{"summary":"Update ticket","tags":["Tickets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","in_progress","resolved","closed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"messageId","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete ticket","tags":["Tickets"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"messageId","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/tickets/{messageId}/status":{"patch":{"summary":"Update ticket status","tags":["Tickets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["pending","in_progress","resolved","closed"],"description":"Ticket status"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"messageId","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/api-keys/stats":{"get":{"summary":"API key statistics","tags":["API Keys"],"description":"Get API key statistics (total, active, inactive, by app)","parameters":[{"schema":{"type":"string"},"in":"query","name":"appId","required":false,"description":"Filter by app ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"total":{"type":"integer"},"active":{"type":"integer"},"inactive":{"type":"integer"},"expired":{"type":"integer"},"byApp":{"type":"object"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/api-keys/":{"get":{"summary":"List API keys","tags":["API Keys"],"description":"Get list of API keys with pagination and filters","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string"},"in":"query","name":"appId","required":false,"description":"Filter by app ID"},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"isActive","required":false,"description":"Filter by active status"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search in name and description"},{"schema":{"type":"string","default":"createdAt"},"in":"query","name":"sortBy","required":false,"description":"Sort by field"},{"schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"in":"query","name":"sortOrder","required":false,"description":"Sort order"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"allowedOrigins":{"type":"array","items":{"type":"string"},"description":"Allowed origins for CORS (URLs, wildcard patterns, or *)"},"isActive":{"type":"boolean"},"lastUsed":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"post":{"summary":"Create API key","tags":["API Keys"],"description":"Create new API key for an app. The full key is returned only once.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["appId","name"],"properties":{"appId":{"type":"string","description":"App ID for this key"},"name":{"type":"string","description":"Name/label for this key"},"description":{"type":"string","description":"Optional description"},"allowedOrigins":{"type":"array","items":{"type":"string"},"description":"Allowed origins (e.g., [\"https://example.com\", \"*.mydomain.com\"] or [\"*\"])","example":["https://app.example.com","*.dev.example.com"]},"expiresAt":{"type":"string","format":"date-time","description":"Optional expiration date"}}}}}},"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"key":{"type":"string","description":"Full API key (shown only once!)"},"appId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"allowedOrigins":{"type":"array","items":{"type":"string"},"description":"Allowed origins for CORS"},"isActive":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"message":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/api-keys/{keyId}":{"get":{"summary":"Get API key","tags":["API Keys"],"description":"Get API key details by ID (includes the full key value)","parameters":[{"schema":{"type":"string"},"in":"path","name":"keyId","required":true,"description":"API key ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"key":{"type":"string","description":"Full API key value"},"appId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"allowedOrigins":{"type":"array","items":{"type":"string"},"description":"Allowed origins for CORS"},"isActive":{"type":"boolean"},"lastUsed":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"patch":{"summary":"Update API key","tags":["API Keys"],"description":"Update API key details (name, description, expiration)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Name/label"},"description":{"type":"string","description":"Description"},"allowedOrigins":{"type":"array","items":{"type":"string"},"description":"Allowed origins (e.g., [\"https://example.com\", \"*.mydomain.com\"] or [\"*\"])"},"isActive":{"type":"boolean","description":"Active status"},"expiresAt":{"type":"string","format":"date-time","description":"Expiration date"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"keyId","required":true,"description":"API key ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete API key","tags":["API Keys"],"description":"Permanently delete an API key","parameters":[{"schema":{"type":"string"},"in":"path","name":"keyId","required":true,"description":"API key ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/api-keys/{keyId}/revoke":{"post":{"summary":"Revoke API key","tags":["API Keys"],"description":"Revoke (deactivate) an API key","parameters":[{"schema":{"type":"string"},"in":"path","name":"keyId","required":true,"description":"API key ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/api-keys/{keyId}/regenerate":{"post":{"summary":"Regenerate API key","tags":["API Keys"],"description":"Generate a new key value for an existing API key. The new key is returned only once.","parameters":[{"schema":{"type":"string"},"in":"path","name":"keyId","required":true,"description":"API key ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"key":{"type":"string","description":"New API key (shown only once!)"},"appId":{"type":"string"},"name":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/apps/":{"get":{"summary":"List apps (admin)","tags":["Apps"],"parameters":[{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"activeOnly","required":false,"description":"Filter to active only"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"features":{"type":"object","additionalProperties":true},"slackChannels":{"type":"object","additionalProperties":{"type":"string"}},"allowedOrigins":{"type":"array","items":{"type":"string"}},"publicKey":{"type":"string"},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"post":{"summary":"Create app","tags":["Apps"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"},"name":{"type":"string","minLength":1},"description":{"type":"string"},"features":{"type":"object","additionalProperties":true},"slackChannels":{"type":"object","additionalProperties":{"type":"string"}},"allowedOrigins":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"}}}}}},"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"features":{"type":"object","additionalProperties":true},"slackChannels":{"type":"object","additionalProperties":{"type":"string"}},"allowedOrigins":{"type":"array","items":{"type":"string"}},"publicKey":{"type":"string"},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/apps/{id}":{"get":{"summary":"Get app by id","tags":["Apps"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"features":{"type":"object","additionalProperties":true},"slackChannels":{"type":"object","additionalProperties":{"type":"string"}},"allowedOrigins":{"type":"array","items":{"type":"string"}},"publicKey":{"type":"string"},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"patch":{"summary":"Update app","tags":["Apps"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"features":{"type":"object","additionalProperties":true},"slackChannels":{"type":"object","additionalProperties":{"type":"string"}},"allowedOrigins":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"features":{"type":"object","additionalProperties":true},"slackChannels":{"type":"object","additionalProperties":{"type":"string"}},"allowedOrigins":{"type":"array","items":{"type":"string"}},"publicKey":{"type":"string"},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete app","tags":["Apps"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/apps/{id}/rotate-key":{"post":{"summary":"Rotate app publicKey","tags":["Apps"],"description":"Generates a new pk_ key. Old key is invalidated immediately.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string"},"publicKey":{"type":"string"}}}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/apps/{id}/toggle":{"post":{"summary":"Toggle app active flag","tags":["Apps"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"features":{"type":"object","additionalProperties":true},"slackChannels":{"type":"object","additionalProperties":{"type":"string"}},"allowedOrigins":{"type":"array","items":{"type":"string"}},"publicKey":{"type":"string"},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/contacts/":{"get":{"summary":"List contacts","tags":["Contacts"],"description":"Get paginated list of contacts with optional filters by email, consent category, or tag","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search by email, first name, or last name"},{"schema":{"type":"string","enum":["outreach","commercial","blog"]},"in":"query","name":"category","required":false,"description":"Filter by consent category"},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"categoryStatus","required":false,"description":"Filter by consent status (requires category)"},{"schema":{"type":"string"},"in":"query","name":"tag","required":false,"description":"Filter by tag"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/contacts/{id}":{"get":{"summary":"Get contact by ID","tags":["Contacts"],"description":"Get contact details including full consent change history","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Contact ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"GDPR delete contact","tags":["Contacts"],"description":"Soft-delete and anonymize a contact (right-to-be-forgotten). PII is removed but consent audit log is retained anonymized.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Contact ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/contacts/{id}/consent":{"patch":{"summary":"Update consent for a category","tags":["Contacts"],"description":"Update consent status for a specific category. Creates an immutable consent_event log entry.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["category","status"],"properties":{"category":{"type":"string","enum":["outreach","commercial","blog"],"description":"Consent category to update"},"status":{"type":"boolean","description":"New consent status"},"reason":{"type":"string","description":"Reason for the change"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Contact ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/contacts/{id}/opt-out":{"post":{"summary":"Global opt-out","tags":["Contacts"],"description":"Opt out contact from all email categories. No emails will be sent to this contact.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","description":"Reason for opt-out"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Contact ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/contacts/{id}/export":{"get":{"summary":"GDPR data export","tags":["Contacts"],"description":"Export all data for a contact (right-to-access). Returns contact details and full consent history.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Contact ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/slack-routing/":{"get":{"summary":"List routing rules","tags":["Slack Routing"],"description":"List all per-app Slack webhook routing rules, optionally filtered by appId","parameters":[{"schema":{"type":"string"},"in":"query","name":"appId","required":false,"description":"Filter by app ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"channel":{"type":"string"},"webhookUrl":{"type":"string"},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"post":{"summary":"Create routing rule","tags":["Slack Routing"],"description":"Create a per-app webhook override for a Slack notification channel","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["appId","channel","webhookUrl"],"properties":{"appId":{"type":"string"},"channel":{"type":"string","enum":["tickets","wants","feedback","newsletter","email","inbound","agent","digest"]},"webhookUrl":{"type":"string","format":"uri"}}}}}},"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/slack-routing/{id}":{"patch":{"summary":"Update routing rule","tags":["Slack Routing"],"description":"Update webhook URL or active status for a routing rule","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhookUrl":{"type":"string","format":"uri"},"active":{"type":"boolean"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete routing rule","tags":["Slack Routing"],"description":"Remove a per-app Slack routing rule (falls back to global env var)","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/templates/categories":{"get":{"summary":"Template languages","tags":["Templates"],"description":"Get all available template languages with counts","parameters":[{"schema":{"type":"string"},"in":"query","name":"appId","required":false,"description":"Filter by appId (omit for global)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}}},"/admin/templates/":{"get":{"summary":"List templates","tags":["Templates"],"description":"Get paginated list of email templates","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string"},"in":"query","name":"appId","required":false,"description":"Filter by appId (omit for global)"},{"schema":{"type":"string","enum":["en","es","fr","de","it","pt"]},"in":"query","name":"language","required":false,"description":"Filter by language"},{"schema":{"type":"boolean"},"in":"query","name":"isActive","required":false,"description":"Filter by active status"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search by name or subject"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}},"post":{"summary":"Create template","tags":["Templates"],"description":"Create a new email template","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","language","subject","htmlTemplate","textTemplate"],"properties":{"appId":{"type":["string","null"],"description":"App scope (null for global)"},"name":{"type":"string","description":"Template name"},"language":{"type":"string","enum":["en","es","fr","de","it","pt"],"default":"en"},"subject":{"type":"string","description":"Email subject"},"htmlTemplate":{"type":"string","description":"HTML template content"},"textTemplate":{"type":"string","description":"Plain text template content"},"variables":{"type":"array","items":{"type":"string"},"description":"Available variables"},"isActive":{"type":"boolean","default":true},"version":{"type":"number","default":1},"sender":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"}}}}}}}},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}}},"/admin/templates/{templateId}":{"get":{"summary":"Get template by ID","tags":["Templates"],"parameters":[{"schema":{"type":"string"},"in":"query","name":"appId","required":false},{"schema":{"type":"string"},"in":"path","name":"templateId","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}},"put":{"summary":"Update template (full)","tags":["Templates"],"parameters":[{"schema":{"type":"string"},"in":"path","name":"templateId","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}},"patch":{"summary":"Update template (partial)","tags":["Templates"],"description":"Partial update - only updates provided fields","parameters":[{"schema":{"type":"string"},"in":"path","name":"templateId","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}},"delete":{"summary":"Delete template","tags":["Templates"],"parameters":[{"schema":{"type":"string"},"in":"query","name":"appId","required":false},{"schema":{"type":"string"},"in":"path","name":"templateId","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}}},"/admin/templates/{templateId}/toggle":{"patch":{"summary":"Toggle template active status","tags":["Templates"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["isActive"],"properties":{"appId":{"type":["string","null"]},"isActive":{"type":"boolean"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"templateId","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}}},"/admin/templates/{templateId}/duplicate":{"post":{"summary":"Duplicate template","tags":["Templates"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"appId":{"type":["string","null"]},"name":{"type":"string","description":"Name for the duplicated template"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"templateId","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}}},"/admin/email-jobs/":{"get":{"summary":"List email jobs","tags":["Email Jobs"],"description":"List email jobs with filtering and pagination","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string","enum":["pending","processing","completed","failed","dead"]},"in":"query","name":"status","required":false,"description":"Filter by job status"},{"schema":{"type":"string","enum":["email.send","email.batch.plan"]},"in":"query","name":"type","required":false,"description":"Filter by job type"},{"schema":{"type":"string"},"in":"query","name":"campaignId","required":false,"description":"Filter by campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"type":{"type":"string","enum":["email.send","email.batch.plan"]},"status":{"type":"string","enum":["pending","processing","completed","failed","dead"]},"priority":{"type":"integer"},"payload":{"type":"object"},"result":{"type":"object"},"attempts":{"type":"integer"},"maxAttempts":{"type":"integer"},"lastError":{"type":"string"},"scheduledAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/email-jobs/stats":{"get":{"summary":"Email job statistics","tags":["Email Jobs"],"description":"Get aggregate job queue statistics, optionally filtered by campaign","parameters":[{"schema":{"type":"string"},"in":"query","name":"campaignId","required":false,"description":"Filter stats by campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"pending":{"type":"integer"},"processing":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"},"dead":{"type":"integer"},"total":{"type":"integer"},"progress":{"type":"object","properties":{"total":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"},"pending":{"type":"integer"},"processing":{"type":"integer"},"dead":{"type":"integer"},"percentage":{"type":"integer"}}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/email-jobs/{id}":{"get":{"summary":"Get email job details","tags":["Email Jobs"],"description":"Get a single email job by ID with full payload, result, and error details","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Job ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"type":{"type":"string","enum":["email.send","email.batch.plan"]},"status":{"type":"string","enum":["pending","processing","completed","failed","dead"]},"priority":{"type":"integer"},"payload":{"type":"object"},"result":{"type":"object"},"attempts":{"type":"integer"},"maxAttempts":{"type":"integer"},"lastError":{"type":"string"},"scheduledAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/email-events/":{"get":{"summary":"List email events","tags":["Email Events"],"description":"List email lifecycle events with filters and pagination.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string"},"in":"query","name":"contactId","required":false,"description":"Filter by contact ID"},{"schema":{"type":"string"},"in":"query","name":"campaignId","required":false,"description":"Filter by campaign ID"},{"schema":{"type":"string"},"in":"query","name":"messageId","required":false,"description":"Filter by message ID"},{"schema":{"type":"string","enum":["queued","sent","delivered","opened","clicked","bounced","complained","unsubscribed","replied"]},"in":"query","name":"type","required":false,"description":"Filter by event type"},{"schema":{"type":"string","enum":["resend","custom"]},"in":"query","name":"provider","required":false,"description":"Filter by provider"},{"schema":{"type":"string"},"in":"query","name":"appId","required":false,"description":"Filter by app ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"contactId":{"type":"string"},"messageId":{"type":"string"},"campaignId":{"type":"string"},"provider":{"type":"string"},"type":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/email-events/message/{messageId}":{"get":{"summary":"Get events for a message","tags":["Email Events"],"description":"Get all email lifecycle events for a specific message ID.","parameters":[{"schema":{"type":"string"},"in":"path","name":"messageId","required":true,"description":"Resend message ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"type":{"type":"string"},"provider":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/email-events/campaign/{campaignId}/stats":{"get":{"summary":"Campaign event statistics","tags":["Email Events"],"description":"Aggregated event counts and rates for a specific campaign.","parameters":[{"schema":{"type":"string"},"in":"path","name":"campaignId","required":true,"description":"Campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"bounced":{"type":"integer"},"openRate":{"type":"number"},"clickRate":{"type":"number"}}}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/email-events/analytics/campaigns/{campaignId}":{"get":{"summary":"Campaign analytics","tags":["Email Analytics"],"description":"Full campaign performance: sent, delivered, opened, clicked, bounced, unique counts, open rate (unique opens / delivered), CTR (unique clicks / unique opens), top clicked links, and event timeline.","parameters":[{"schema":{"type":"string"},"in":"path","name":"campaignId","required":true,"description":"Campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"campaignId":{"type":"string"},"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"uniqueOpens":{"type":"integer"},"clicked":{"type":"integer"},"uniqueClicks":{"type":"integer"},"bounced":{"type":"integer"},"complained":{"type":"integer"},"unsubscribed":{"type":"integer"},"openRate":{"type":"number","description":"Unique opens / delivered"},"clickThroughRate":{"type":"number","description":"Unique clicks / unique opens"},"topLinks":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"clicks":{"type":"integer"}}}},"timeline":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"type":{"type":"string"},"count":{"type":"integer"}}}}}}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/email-events/analytics/campaigns/{campaignId}/recipients":{"get":{"summary":"Campaign recipients breakdown","tags":["Email Analytics"],"description":"Per-recipient status breakdown for a campaign. Shows each contact and which event types they triggered.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string"},"in":"path","name":"campaignId","required":true,"description":"Campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"contactId":{"type":"string"},"events":{"type":"array","items":{"type":"string"},"description":"Event types triggered by this contact"},"lastEvent":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/email-events/analytics/contacts/{contactId}":{"get":{"summary":"Contact engagement history","tags":["Email Analytics"],"description":"Full engagement history for a contact across all campaigns. Includes summary counts and paginated event timeline.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string"},"in":"path","name":"contactId","required":true,"description":"Contact ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"contactId":{"type":"string"},"totalSent":{"type":"integer"},"totalOpened":{"type":"integer"},"totalClicked":{"type":"integer"},"totalBounced":{"type":"integer"},"totalComplained":{"type":"integer"},"events":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"campaignId":{"type":"string"},"messageId":{"type":"string"},"type":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/email-events/analytics/overview":{"get":{"summary":"Global email analytics overview","tags":["Email Analytics"],"description":"Dashboard KPIs for a time range. Aggregate numbers across all campaigns: totals, rates, and daily timeline.","parameters":[{"schema":{"type":"string","format":"date-time","example":"2026-01-01T00:00:00Z"},"in":"query","name":"from","required":false,"description":"Start of time range (ISO 8601, UTC)"},{"schema":{"type":"string","format":"date-time","example":"2026-12-31T23:59:59Z"},"in":"query","name":"to","required":false,"description":"End of time range (ISO 8601, UTC)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"totalSent":{"type":"integer"},"totalDelivered":{"type":"integer"},"totalOpened":{"type":"integer"},"totalUniqueOpens":{"type":"integer"},"totalClicked":{"type":"integer"},"totalUniqueClicks":{"type":"integer"},"totalBounced":{"type":"integer"},"totalComplained":{"type":"integer"},"totalUnsubscribed":{"type":"integer"},"openRate":{"type":"number"},"clickThroughRate":{"type":"number"},"bounceRate":{"type":"number"},"complaintRate":{"type":"number"},"timeline":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"}}}}}}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/tickets/stats":{"get":{"summary":"Ticket statistics","tags":["Tickets"],"description":"Get aggregated ticket statistics for an app","parameters":[{"schema":{"type":"string","format":"date"},"in":"query","name":"startDate","required":false,"description":"Start date filter"},{"schema":{"type":"string","format":"date"},"in":"query","name":"endDate","required":false,"description":"End date filter"},{"schema":{"type":"string"},"in":"query","name":"shopId","required":false,"description":"Filter by shop ID"},{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"total":{"type":"integer","description":"Total number of tickets"},"byStatus":{"type":"object","description":"Ticket count grouped by status","additionalProperties":{"type":"integer"}},"byTopic":{"type":"object","description":"Ticket count grouped by topic","additionalProperties":{"type":"integer"}},"byPriority":{"type":"object","description":"Ticket count grouped by priority","additionalProperties":{"type":"integer"}},"recentActivity":{"type":"array","description":"Last 10 tickets","items":{"type":"object","properties":{"_id":{"type":"string"},"subject":{"type":"string"},"email":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}},"volumeOverTime":{"type":"array","description":"Ticket volume per day (last 30 days)","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"count":{"type":"integer"}}}},"averageResolutionTime":{"type":"number","nullable":true,"description":"Average time to resolve tickets (in hours)"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/tickets/":{"post":{"summary":"Create ticket with attachments","tags":["Tickets"],"description":"Create new support ticket with optional file attachments.\n\n**Content Types:**\n- `application/json`: For tickets without attachments\n- `multipart/form-data`: For tickets with file attachments\n\n**File Constraints:**\n- Max file size: 50MB per file\n- Max files: 5 per ticket\n- Allowed types: images (jpeg, png, gif, webp, svg), videos (mp4, webm, quicktime), PDF\n\n**Multipart Fields:**\n- `shopId`: string (required)\n- `topic`: enum (required)\n- `email`: string (required)\n- `subject`: string (required)\n- `message`: string (required)\n- `priority`: enum (optional, default: normal)\n- `attachments`: file(s) (optional, can send multiple)","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"shopId":{"type":"string"},"topic":{"type":"string"},"email":{"type":"string"},"subject":{"type":"string"},"message":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"attachments":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","description":"Public URL of the file"},"key":{"type":"string","description":"Storage key for deletion"},"filename":{"type":"string","description":"Original filename"},"mimetype":{"type":"string","description":"File MIME type"},"size":{"type":"number","description":"File size in bytes"},"uploadedAt":{"type":"string","format":"date-time"}}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"message":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"get":{"summary":"List tickets","tags":["Tickets"],"description":"Get paginated list of tickets for an app","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string","enum":["open","pending","in_progress","resolved","closed"]},"in":"query","name":"status","required":false,"description":"Filter by status"},{"schema":{"type":"string","enum":["general","technical","billing","feature"]},"in":"query","name":"topic","required":false,"description":"Filter by topic"},{"schema":{"type":"string","enum":["low","normal","high","urgent"]},"in":"query","name":"priority","required":false,"description":"Filter by priority"},{"schema":{"type":"string"},"in":"query","name":"shopId","required":false,"description":"Filter by shop ID"},{"schema":{"type":"string"},"in":"query","name":"email","required":false,"description":"Filter by email"},{"schema":{"type":"string","format":"date"},"in":"query","name":"startDate","required":false,"description":"Start date filter"},{"schema":{"type":"string","format":"date"},"in":"query","name":"endDate","required":false,"description":"End date filter"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search in subject, message, and email"},{"schema":{"type":"string","default":"createdAt"},"in":"query","name":"sortBy","required":false},{"schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"in":"query","name":"sortOrder","required":false},{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Bulk delete tickets","tags":["Tickets"],"description":"Delete multiple tickets by IDs","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","items":{"type":"string"},"description":"Array of ticket IDs to delete"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"},"deletedCount":{"type":"integer"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/tickets/{messageId}":{"get":{"summary":"Get ticket by ID","tags":["Tickets"],"description":"Get a single ticket by its ID","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"messageId","required":true,"description":"Ticket ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"patch":{"summary":"Update ticket","tags":["Tickets"],"description":"Update ticket fields (status, priority, etc.)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["open","pending","in_progress","resolved","closed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"topic":{"type":"string","enum":["general","technical","billing","feature"]}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"messageId","required":true,"description":"Ticket ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete ticket","tags":["Tickets"],"description":"Delete a ticket by ID","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"messageId","required":true,"description":"Ticket ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/tickets/{messageId}/status":{"patch":{"summary":"Update ticket status","tags":["Tickets"],"description":"Update only the status of a ticket","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["open","pending","in_progress","resolved","closed"]}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"messageId","required":true,"description":"Ticket ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/tickets/{messageId}/messages":{"post":{"summary":"Add message to ticket","tags":["Tickets"],"description":"Add a reply/message to an existing ticket","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["content"],"properties":{"content":{"type":"string","description":"Message content"},"isCustomer":{"type":"boolean","default":false,"description":"True if message is from customer"},"authorEmail":{"type":"string","description":"Author email"},"authorName":{"type":"string","description":"Author name"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"messageId","required":true,"description":"Ticket ID"}],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true},"message":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"get":{"summary":"Get ticket messages","tags":["Tickets"],"description":"Get all messages/replies for a ticket","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"messageId","required":true,"description":"Ticket ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"content":{"type":"string"},"isCustomer":{"type":"boolean"},"authorEmail":{"type":"string"},"authorName":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/auth/magic-link/":{"post":{"summary":"Send magic link","tags":["Magic Link"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","appId"],"properties":{"email":{"type":"string","format":"email"},"appId":{"type":"string","example":"app1"}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/auth/magic-link/verify":{"post":{"summary":"Verify magic link token","tags":["Magic Link"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"token":{"type":"string","description":"End user JWT"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"appId":{"type":"string"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/wants/":{"get":{"summary":"List wants","tags":["Wants"],"description":"Get paginated list of wants for an app. If authenticated, includes hasVoted status.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"in":"query","name":"status","required":false,"description":"Filter by status"},{"schema":{"type":"string","enum":["feature","improvement","integration"]},"in":"query","name":"category","required":false,"description":"Filter by category"},{"schema":{"type":"string","enum":["newest","oldest","most_voted"],"default":"newest"},"in":"query","name":"sort","required":false,"description":"Sort order"},{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["feature","improvement","integration"]},"status":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"voteCount":{"type":"integer","description":"Total number of votes"},"hasVoted":{"type":"boolean","description":"Whether the current user has voted"},"authorEmail":{"type":"string","description":"Email of the submitter"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"post":{"summary":"Submit a want","tags":["Wants"],"description":"Submit a new want. Requires end-user authentication. Rate limited to 10 per hour.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","description","category"],"properties":{"title":{"type":"string","minLength":1,"maxLength":200,"description":"Feature request title"},"description":{"type":"string","minLength":1,"maxLength":2000,"description":"Detailed description"},"category":{"type":"string","enum":["feature","improvement","integration"],"description":"Category"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"apiKeyAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["feature","improvement","integration"]},"status":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"voteCount":{"type":"integer","description":"Total number of votes"},"hasVoted":{"type":"boolean","description":"Whether the current user has voted"},"authorEmail":{"type":"string","description":"Email of the submitter"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/wants/{id}":{"get":{"summary":"Get want by ID","tags":["Wants"],"description":"Get a single want. If authenticated, includes hasVoted status.","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feature request ID"}],"security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["feature","improvement","integration"]},"status":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"voteCount":{"type":"integer","description":"Total number of votes"},"hasVoted":{"type":"boolean","description":"Whether the current user has voted"},"authorEmail":{"type":"string","description":"Email of the submitter"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/wants/{id}/vote":{"post":{"summary":"Vote on a want","tags":["Wants"],"description":"Toggle vote on a want. Requires end-user authentication. Rate limited to 30 per hour.","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feature request ID"}],"security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"voteCount":{"type":"integer","description":"Updated vote count"},"hasVoted":{"type":"boolean","description":"Whether the user now has an active vote"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/feedback/":{"post":{"summary":"Submit feedback","tags":["Feedback"],"description":"Submit anonymous feedback for an app. Rate limited to 10 submissions per hour per IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","subject","message"],"properties":{"type":{"type":"string","enum":["bug","improvement","general"],"description":"Feedback type"},"subject":{"type":"string","description":"Feedback subject"},"message":{"type":"string","description":"Feedback message body"},"email":{"type":"string","format":"email","description":"Optional contact email"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"type":{"type":"string"},"subject":{"type":"string"},"message":{"type":"string"},"email":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/newsletter/subscribe":{"post":{"summary":"Subscribe to newsletter","tags":["Newsletter"],"description":"Subscribe an email to the newsletter for an app. Requires API Key. Rate limited.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","description":"Subscriber email"},"firstName":{"type":"string","description":"Subscriber first name (optional)"},"locale":{"type":"string","description":"Browser locale code (e.g. en, es, fr)","example":"en"},"referralUrl":{"type":"string","description":"URL where the user subscribed from"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"apiKeyAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"email":{"type":"string"},"firstName":{"type":"string"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/{appId}/newsletter/unsubscribe/{token}":{"get":{"summary":"Unsubscribe from newsletter","tags":["Newsletter"],"description":"One-click unsubscribe via token. Requires API Key. Returns an HTML confirmation page.","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"token","required":true,"description":"Unsubscribe token"}],"security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}}}},"post":{"summary":"Unsubscribe from newsletter (POST)","tags":["Newsletter"],"description":"Unsubscribe via POST request for programmatic use. Requires API Key.","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"token","required":true,"description":"Unsubscribe token"}],"security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}}}}},"/admin/{appId}/wants/stats":{"get":{"summary":"Feature request statistics","tags":["Wants"],"description":"Get aggregated want statistics for an app","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"total":{"type":"integer"},"byStatus":{"type":"object","additionalProperties":{"type":"integer"}},"byCategory":{"type":"object","additionalProperties":{"type":"integer"}},"byPriority":{"type":"object","additionalProperties":{"type":"integer"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/wants/":{"get":{"summary":"List wants (admin)","tags":["Wants"],"description":"Get paginated list of wants with full admin data","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"in":"query","name":"status","required":false,"description":"Filter by status"},{"schema":{"type":"string","enum":["feature","improvement","integration"]},"in":"query","name":"category","required":false,"description":"Filter by category"},{"schema":{"type":"string","enum":["newest","oldest","most_voted"],"default":"newest"},"in":"query","name":"sort","required":false,"description":"Sort order"},{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["feature","improvement","integration"]},"status":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"priority":{"type":"string","enum":["low","normal","high"]},"voteCount":{"type":"integer"},"authorEmail":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/wants/{id}":{"get":{"summary":"Get want by ID (admin)","tags":["Wants"],"description":"Get a single want with full admin data","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feature request ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["feature","improvement","integration"]},"status":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"priority":{"type":"string","enum":["low","normal","high"]},"voteCount":{"type":"integer"},"authorEmail":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"patch":{"summary":"Update want","tags":["Wants"],"description":"Update want fields (title, description, category)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Feature request title"},"description":{"type":"string","description":"Detailed description"},"category":{"type":"string","enum":["feature","improvement","integration"],"description":"Category"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feature request ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["feature","improvement","integration"]},"status":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"priority":{"type":"string","enum":["low","normal","high"]},"voteCount":{"type":"integer"},"authorEmail":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete want","tags":["Wants"],"description":"Permanently delete a want","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feature request ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/wants/{id}/status":{"patch":{"summary":"Update want status","tags":["Wants"],"description":"Update only the status of a want","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["under_review","planned","in_progress","completed"]}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feature request ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["feature","improvement","integration"]},"status":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"priority":{"type":"string","enum":["low","normal","high"]},"voteCount":{"type":"integer"},"authorEmail":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/wants/{id}/priority":{"patch":{"summary":"Update want priority","tags":["Wants"],"description":"Update only the priority of a want","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["priority"],"properties":{"priority":{"type":"string","enum":["low","normal","high"]}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feature request ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["feature","improvement","integration"]},"status":{"type":"string","enum":["under_review","planned","in_progress","completed"]},"priority":{"type":"string","enum":["low","normal","high"]},"voteCount":{"type":"integer"},"authorEmail":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/feedback/stats":{"get":{"summary":"Feedback statistics","tags":["Feedback"],"description":"Get aggregated feedback statistics for an app","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"total":{"type":"integer"},"byType":{"type":"object","description":"Count grouped by feedback type","additionalProperties":{"type":"integer"}},"byStatus":{"type":"object","description":"Count grouped by status","additionalProperties":{"type":"integer"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/feedback/":{"get":{"summary":"List feedback","tags":["Feedback"],"description":"Get paginated list of feedback for an app with filters","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string","enum":["bug","improvement","general"]},"in":"query","name":"type","required":false,"description":"Filter by type"},{"schema":{"type":"string","enum":["new","reviewed","addressed","closed"]},"in":"query","name":"status","required":false,"description":"Filter by status"},{"schema":{"type":"string","enum":["low","normal","high"]},"in":"query","name":"priority","required":false,"description":"Filter by priority"},{"schema":{"type":"string","default":"createdAt"},"in":"query","name":"sortBy","required":false},{"schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"in":"query","name":"sortOrder","required":false},{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/feedback/{id}":{"get":{"summary":"Get feedback by ID","tags":["Feedback"],"description":"Get a single feedback entry by its ID","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feedback ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"patch":{"summary":"Update feedback","tags":["Feedback"],"description":"Update feedback fields (type, subject, message)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["bug","improvement","general"]},"subject":{"type":"string"},"message":{"type":"string"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feedback ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete feedback","tags":["Feedback"],"description":"Delete a feedback entry by ID","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feedback ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/feedback/{id}/status":{"patch":{"summary":"Update feedback status","tags":["Feedback"],"description":"Update only the status of a feedback entry","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["new","reviewed","addressed","closed"]}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feedback ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/feedback/{id}/priority":{"patch":{"summary":"Update feedback priority","tags":["Feedback"],"description":"Update only the priority of a feedback entry","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["priority"],"properties":{"priority":{"type":"string","enum":["low","normal","high"]}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Feedback ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/subscribers/stats":{"get":{"summary":"Subscriber statistics","tags":["Newsletter"],"description":"Get aggregated subscriber statistics for an app","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"total":{"type":"integer"},"active":{"type":"integer"},"unsubscribed":{"type":"integer"},"bounced":{"type":"integer"},"bySource":{"type":"object","additionalProperties":{"type":"integer"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/subscribers":{"get":{"summary":"List subscribers","tags":["Newsletter"],"description":"Get paginated list of newsletter subscribers","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string","enum":["active","unsubscribed","bounced"]},"in":"query","name":"status","required":false,"description":"Filter by status"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search by email or name"},{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"locale":{"type":"string","description":"Subscriber locale code"},"subscriptions":{"type":"array","items":{"type":"object","properties":{"appId":{"type":"string"},"status":{"type":"string","enum":["active","unsubscribed","bounced"]},"source":{"type":"string","enum":["form","import","manual"]},"referralUrl":{"type":"string"},"subscribedAt":{"type":"string","format":"date-time"},"unsubscribedAt":{"type":"string","format":"date-time"}}}},"createdAt":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"post":{"summary":"Add subscriber manually","tags":["Newsletter"],"description":"Manually add a subscriber to the newsletter","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"},"firstName":{"type":"string"},"locale":{"type":"string"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"locale":{"type":"string","description":"Subscriber locale code"},"subscriptions":{"type":"array","items":{"type":"object","properties":{"appId":{"type":"string"},"status":{"type":"string","enum":["active","unsubscribed","bounced"]},"source":{"type":"string","enum":["form","import","manual"]},"referralUrl":{"type":"string"},"subscribedAt":{"type":"string","format":"date-time"},"unsubscribedAt":{"type":"string","format":"date-time"}}}},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/subscribers/import":{"post":{"summary":"Import subscribers","tags":["Newsletter"],"description":"Bulk import subscribers from a JSON array","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["subscribers"],"properties":{"subscribers":{"type":"array","items":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"},"firstName":{"type":"string"},"locale":{"type":"string"}}}}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"imported":{"type":"integer"},"skipped":{"type":"integer"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/subscribers/{id}":{"delete":{"summary":"Delete subscriber","tags":["Newsletter"],"description":"Permanently remove a subscriber","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Subscriber ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/campaigns":{"get":{"summary":"List campaigns","tags":["Newsletter"],"description":"Get paginated list of newsletter campaigns","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Items per page"},{"schema":{"type":"string","enum":["draft","scheduled","sending","sent","failed","cancelled"]},"in":"query","name":"status","required":false,"description":"Filter by status"},{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","sending","sent","failed","cancelled"]},"stats":{"type":"object","properties":{"total":{"type":"integer"},"sent":{"type":"integer"},"failed":{"type":"integer"}}},"sentAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"post":{"summary":"Create campaign","tags":["Newsletter"],"description":"Create a new newsletter campaign (draft)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","subject","htmlContent"],"properties":{"name":{"type":"string","description":"Campaign name"},"subject":{"type":"string","description":"Email subject line"},"htmlContent":{"type":"string","description":"HTML email content. Use {{unsubscribeUrl}} for unsubscribe link"},"textContent":{"type":"string","description":"Plain text fallback"},"templateId":{"type":"string","description":"Optional template ID to base on"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","sending","sent","failed","cancelled"]},"stats":{"type":"object","properties":{"total":{"type":"integer"},"sent":{"type":"integer"},"failed":{"type":"integer"}}},"sentAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/campaigns/{id}":{"get":{"summary":"Get campaign","tags":["Newsletter"],"description":"Get campaign details including content and stats","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","sending","sent","failed","cancelled"]},"stats":{"type":"object","properties":{"total":{"type":"integer"},"sent":{"type":"integer"},"failed":{"type":"integer"}}},"sentAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"patch":{"summary":"Update campaign","tags":["Newsletter"],"description":"Update campaign fields (only draft campaigns can be updated)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"subject":{"type":"string"},"htmlContent":{"type":"string"},"textContent":{"type":"string"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"appId":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","sending","sent","failed","cancelled"]},"stats":{"type":"object","properties":{"total":{"type":"integer"},"sent":{"type":"integer"},"failed":{"type":"integer"}}},"sentAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete campaign","tags":["Newsletter"],"description":"Delete a campaign (only draft campaigns can be deleted)","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/campaigns/{id}/send":{"post":{"summary":"Send campaign","tags":["Newsletter"],"description":"Send the campaign to all active subscribers. Enqueues a batch-plan job that fans out individual sends.","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"status":{"type":"string","example":"queued"},"jobId":{"type":"string","description":"Batch plan job ID"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/campaigns/{id}/test":{"post":{"summary":"Send test email","tags":["Newsletter"],"description":"Send a test email to a single address to preview the campaign","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","description":"Test recipient email"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Campaign ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"data":{"type":"object","properties":{"jobId":{"type":"string"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/templates":{"get":{"summary":"List newsletter templates","tags":["Newsletter"],"description":"Get all newsletter templates","parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"htmlContent":{"type":"string"},"textContent":{"type":"string"},"isActive":{"type":"boolean"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"post":{"summary":"Create newsletter template","tags":["Newsletter"],"description":"Create a reusable newsletter template","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","subject","htmlContent"],"properties":{"name":{"type":"string","description":"Template name (unique)"},"subject":{"type":"string","description":"Default subject line"},"htmlContent":{"type":"string","description":"HTML content with {{variable}} placeholders"},"textContent":{"type":"string","description":"Plain text fallback"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"}],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"htmlContent":{"type":"string"},"textContent":{"type":"string"},"isActive":{"type":"boolean"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}},"/admin/{appId}/newsletter/templates/{id}":{"patch":{"summary":"Update newsletter template","tags":["Newsletter"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"subject":{"type":"string"},"htmlContent":{"type":"string"},"textContent":{"type":"string"},"isActive":{"type":"boolean"}}}}}},"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Template ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"subject":{"type":"string"},"htmlContent":{"type":"string"},"textContent":{"type":"string"},"isActive":{"type":"boolean"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}},"delete":{"summary":"Delete newsletter template","tags":["Newsletter"],"parameters":[{"schema":{"type":"string","example":"banners-all-over"},"in":"path","name":"appId","required":true,"description":"Application ID (e.g.: banners-all-over)"},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Template ID"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}}}}}}}}},"servers":[{"url":"https://api.x24labs.io","description":"Production server"}],"tags":[{"name":"Auth","description":"Back Office authentication"},{"name":"Users","description":"Admin user management"},{"name":"Apps","description":"Application management"},{"name":"API Keys","description":"API key management for backend-to-backend authentication"},{"name":"Tickets","description":"Support tickets management"},{"name":"Health","description":"Health checks"},{"name":"Magic Link","description":"Passwordless end-user authentication"},{"name":"Wants","description":"Feature request board with voting and roadmap"},{"name":"Feedback","description":"Quick anonymous feedback submission"}]}