{"openapi":"3.1.0","info":{"title":"Email API","version":"1.0","description":"Use Email APIs to deliver secure transactional, notification, and lifecycle messages."},"servers":[{"url":"https://email.1spoc.com"}],"paths":{"/ping":{"get":{"operationId":"getping","summary":"Ping the server","description":"Ping the server","tags":["Health"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Pong response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"pong"}}}}}}}}},"/api/user/login":{"post":{"operationId":"postapiuserlogin","summary":"Login as user","description":"Login as user","tags":["User"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","example":"user@example.com"},"password":{"type":"string","format":"password","example":"UserPassword@123"}}},"example":{}}}},"responses":{"200":{"description":"Successfully logged in user. Returns access and refresh tokens.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}},"accessToken":{"type":"string","description":"JWT access token (expires in 1 hour)."},"refreshToken":{"type":"string","description":"JWT refresh token (expires in 7 days)."}}}}}},"400":{"description":"Missing email or password","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}},"accessToken":{"type":"string","description":"JWT access token (expires in 1 hour)."},"refreshToken":{"type":"string","description":"JWT refresh token (expires in 7 days)."}}}}}},"401":{"description":"Invalid email or password, or user is blocked","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}},"accessToken":{"type":"string","description":"JWT access token (expires in 1 hour)."},"refreshToken":{"type":"string","description":"JWT refresh token (expires in 7 days)."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}},"accessToken":{"type":"string","description":"JWT access token (expires in 1 hour)."},"refreshToken":{"type":"string","description":"JWT refresh token (expires in 7 days)."}}}}}}}}},"/api/user/forgot-password":{"post":{"operationId":"postapiuserforgotpassword","summary":"Request password reset","description":"Sends a password reset link to the user's email address if the user exists and is not blocked.","tags":["User"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","example":"user@example.com","description":"Email address of the user requesting password reset"}}},"example":{}}}},"responses":{"200":{"description":"Password reset link sent successfully (or user not found - same response for security)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"A link has been sent to your email to reset your password."}}}}}},"400":{"description":"Missing email","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"A link has been sent to your email to reset your password."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"A link has been sent to your email to reset your password."}}}}}}}}},"/api/user/refresh":{"post":{"operationId":"postapiuserrefresh","summary":"Refresh user access token","description":"Refresh user access token","tags":["User"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["refreshToken"],"properties":{"refreshToken":{"type":"string","description":"Existing refresh token."}}},"example":{}}}},"responses":{"200":{"description":"Successfully refreshed access token. Returns new access token and the same refresh token.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}},"accessToken":{"type":"string","description":"New JWT access token (expires in 1 hour)."},"refreshToken":{"type":"string","description":"Same JWT refresh token that was provided (expires in 7 days)."}}}}}},"400":{"description":"Missing refresh token","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}},"accessToken":{"type":"string","description":"New JWT access token (expires in 1 hour)."},"refreshToken":{"type":"string","description":"Same JWT refresh token that was provided (expires in 7 days)."}}}}}},"401":{"description":"Invalid or expired refresh token","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}},"accessToken":{"type":"string","description":"New JWT access token (expires in 1 hour)."},"refreshToken":{"type":"string","description":"Same JWT refresh token that was provided (expires in 7 days)."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}},"accessToken":{"type":"string","description":"New JWT access token (expires in 1 hour)."},"refreshToken":{"type":"string","description":"Same JWT refresh token that was provided (expires in 7 days)."}}}}}}}}},"/api/user/reset-password":{"post":{"operationId":"postapiuserresetpassword","summary":"Reset user password","description":"Resets the user's password using a valid reset token received via email.","tags":["User"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token","newPassword"],"properties":{"token":{"type":"string","example":"abc123def456...","description":"Password reset token received via email"},"newPassword":{"type":"string","format":"password","example":"NewSecurePassword@123","description":"New password for the user account"}}},"example":{}}}},"responses":{"200":{"description":"Password reset successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Password reset successfully."}}}}}},"400":{"description":"Missing token/password, invalid token, expired token, or user not found","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Password reset successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Password reset successfully."}}}}}}}}},"/api/user/self":{"get":{"operationId":"getapiuserself","summary":"Get authenticated user's own details","description":"Returns the details of the currently authenticated user.","tags":["User"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successfully retrieved user details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token, or user context missing)","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"mobile":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"admin_id":{"type":"string","format":"uuid"},"last_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"first_name":{"type":"string"},"is_blocked":{"type":"boolean"},"customer_type":{"enum":["PREPAID","POSTPAID"],"type":"string"},"email_balance":{"type":"integer"},"last_login_at":{"type":"string","format":"date-time","nullable":true},"last_login_ip":{"type":"string","nullable":true},"per_email_charge":{"type":"string"},"organization_name":{"type":"string"},"last_login_browser":{"type":"string","nullable":true}}}}}}}}},"/api/user/sending-identities":{"get":{"operationId":"getapiusersendingidentities","summary":"List sending identities for the authenticated user","description":"List sending identities for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"description":"Page number (1-based).","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","required":false,"description":"Number of items per page (max 100).","schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"search","in":"query","required":false,"description":"Search term applied to domain.","schema":{"type":"string"}},{"name":"sortBy","in":"query","required":false,"description":"Field to sort by. Defaults to created_at.","schema":{"enum":["domain","created_at"],"type":"string"}},{"name":"sortOrder","in":"query","required":false,"description":"Sort order, ascending or descending. Defaults to desc.","schema":{"enum":["asc","desc"],"type":"string"}}],"responses":{"200":{"description":"List of sending identities for the user with pagination metadata.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE"],"type":"string"},"created_at":{"type":"string","format":"date-time"}}}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE"],"type":"string"},"created_at":{"type":"string","format":"date-time"}}}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE"],"type":"string"},"created_at":{"type":"string","format":"date-time"}}}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}}}},"post":{"operationId":"postapiusersendingidentities","summary":"Create a new sending identity for the authenticated user","description":"Create a new sending identity for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string","description":"Domain of the sending identity."}}},"example":{}}}},"responses":{"201":{"description":"Sending identity created successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE"],"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Missing or invalid domain","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE"],"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE"],"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}},"409":{"description":"Sending identity for this domain already exists for the user","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE"],"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"domain":{"type":"string"},"status":{"enum":["ACTIVE","INACTIVE"],"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"/api/user/sending-identities/{id}":{"delete":{"operationId":"deleteapiusersendingidentitiesid","summary":"Delete a sending identity for the authenticated user","description":"Delete a sending identity for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sending identity deleted successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Sending identity deleted successfully."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Sending identity deleted successfully."}}}}}},"404":{"description":"Sending identity not found.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Sending identity deleted successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Sending identity deleted successfully."}}}}}}}}},"/api/user/api-key":{"get":{"operationId":"getapiuserapikey","summary":"Get the current API key for the authenticated user","description":"Get the current API key for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Returns the current API key for the authenticated user, if any.","content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string","nullable":true,"description":"The current API key for the user, or null if not generated yet."},"lastRotatedAt":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the API key was last generated or rotated."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string","nullable":true,"description":"The current API key for the user, or null if not generated yet."},"lastRotatedAt":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the API key was last generated or rotated."}}}}}},"404":{"description":"User not found.","content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string","nullable":true,"description":"The current API key for the user, or null if not generated yet."},"lastRotatedAt":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the API key was last generated or rotated."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string","nullable":true,"description":"The current API key for the user, or null if not generated yet."},"lastRotatedAt":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the API key was last generated or rotated."}}}}}}}}},"/api/user/api-key/rotate":{"post":{"operationId":"postapiuserapikeyrotate","summary":"Generate or rotate the API key for the authenticated user","description":"Generate or rotate the API key for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{}},"example":{}}}},"responses":{"200":{"description":"Successfully generated or rotated the API key. Returns the new API key.","content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string","description":"The newly generated API key."},"lastRotatedAt":{"type":"string","format":"date-time","description":"Timestamp when the API key was generated or rotated."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string","description":"The newly generated API key."},"lastRotatedAt":{"type":"string","format":"date-time","description":"Timestamp when the API key was generated or rotated."}}}}}},"404":{"description":"User not found or blocked.","content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string","description":"The newly generated API key."},"lastRotatedAt":{"type":"string","format":"date-time","description":"Timestamp when the API key was generated or rotated."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"apiKey":{"type":"string","description":"The newly generated API key."},"lastRotatedAt":{"type":"string","format":"date-time","description":"Timestamp when the API key was generated or rotated."}}}}}}}}},"/api/user/smtp-settings":{"get":{"operationId":"getapiusersmtpsettings","summary":"Get SMTP settings for the authenticated user","description":"Get SMTP settings for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Returns SMTP settings for the authenticated user.","content":{"application/json":{"schema":{"type":"object","properties":{"default_from_name":{"type":"string","nullable":true,"description":"Default sender display name for SMTP."},"default_from_email":{"type":"string","nullable":true,"description":"Default sender email address for SMTP."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"default_from_name":{"type":"string","nullable":true,"description":"Default sender display name for SMTP."},"default_from_email":{"type":"string","nullable":true,"description":"Default sender email address for SMTP."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"default_from_name":{"type":"string","nullable":true,"description":"Default sender display name for SMTP."},"default_from_email":{"type":"string","nullable":true,"description":"Default sender email address for SMTP."}}}}}}}},"put":{"operationId":"putapiusersmtpsettings","summary":"Create or update SMTP settings for the authenticated user","description":"Create or update SMTP settings for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"default_from_name":{"type":"string","nullable":true,"description":"Default sender display name for SMTP. Set to null to clear."},"default_from_email":{"type":"string","nullable":true,"description":"Default sender email address for SMTP. Set to null to clear."}}},"example":{}}}},"responses":{"200":{"description":"SMTP settings saved successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"default_from_name":{"type":"string","nullable":true},"default_from_email":{"type":"string","nullable":true}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"default_from_name":{"type":"string","nullable":true},"default_from_email":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"default_from_name":{"type":"string","nullable":true},"default_from_email":{"type":"string","nullable":true}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"default_from_name":{"type":"string","nullable":true},"default_from_email":{"type":"string","nullable":true}}}}}}}}},"/api/user/groups":{"get":{"operationId":"getapiusergroups","summary":"List groups for the authenticated user","description":"List groups for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"description":"Page number (1-based).","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","required":false,"description":"Number of items per page (max 100).","schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"search","in":"query","required":false,"description":"Search term applied to group name and description.","schema":{"type":"string"}},{"name":"sortBy","in":"query","required":false,"description":"Field to sort by. Defaults to created_at.","schema":{"enum":["name","created_at"],"type":"string"}},{"name":"sortOrder","in":"query","required":false,"description":"Sort order, ascending or descending. Defaults to desc.","schema":{"enum":["asc","desc"],"type":"string"}}],"responses":{"200":{"description":"List of groups for the user with pagination metadata.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}}}},"post":{"operationId":"postapiusergroups","summary":"Create a new group for the authenticated user","description":"Create a new group for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Name of the group."},"description":{"type":"string","nullable":true,"description":"Optional description of the group."}}},"example":{}}}},"responses":{"201":{"description":"Group created successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"400":{"description":"Missing or invalid name","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"409":{"description":"Group with this name already exists for the user","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}}}}},"/api/user/groups/{groupId}/contacts":{"post":{"operationId":"postapiusergroupsgroupidcontacts","summary":"Add a contact to a group for the authenticated user","description":"Add a contact to a group for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"groupId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email","description":"Email address of the contact to add."},"status":{"type":"string","nullable":true,"description":"Subscription status of the contact (e.g., subscribed, unsubscribed, bounced). Defaults to subscribed."},"last_name":{"type":"string","nullable":true,"description":"Last name of the contact."},"first_name":{"type":"string","nullable":true,"description":"First name of the contact."}}},"example":{}}}},"responses":{"201":{"description":"Contact added to group successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}},"400":{"description":"Missing or invalid fields (e.g., missing email or groupId).","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}},"404":{"description":"Group not found.","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}},"409":{"description":"Contact is already a member of this group.","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}}}}},"/api/user/groups/{groupId}/contacts/{contactId}":{"put":{"operationId":"putapiusergroupsgroupidcontactscontactid","summary":"Update contact details (name/status) for a contact within a group for the authenticated user","description":"Update contact details (name/status) for a contact within a group for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"groupId","in":"path","required":true,"schema":{"type":"string"}},{"name":"contactId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","nullable":true,"description":"Updated subscription status (e.g., subscribed, unsubscribed, bounced)."},"last_name":{"type":"string","nullable":true,"description":"Updated last name of the contact."},"first_name":{"type":"string","nullable":true,"description":"Updated first name of the contact."}}},"example":{}}}},"responses":{"200":{"description":"Contact within the group updated successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}},"400":{"description":"Missing group id or contact id.","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}},"404":{"description":"Contact not found in this group.","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"},"added_at":{"type":"string","format":"date-time"},"group_id":{"type":"string","format":"uuid"},"last_name":{"type":"string","nullable":true},"contact_id":{"type":"string","format":"uuid"},"first_name":{"type":"string","nullable":true}}}}}}}},"delete":{"operationId":"deleteapiusergroupsgroupidcontactscontactid","summary":"Remove a contact from a group for the authenticated user","description":"Remove a contact from a group for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"groupId","in":"path","required":true,"schema":{"type":"string"}},{"name":"contactId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Contact removed from group successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Contact removed from group successfully."}}}}}},"400":{"description":"Missing group id or contact id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Contact removed from group successfully."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Contact removed from group successfully."}}}}}},"404":{"description":"Contact not found in this group.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Contact removed from group successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Contact removed from group successfully."}}}}}}}}},"/api/user/templates":{"get":{"operationId":"getapiusertemplates","summary":"List email templates for the authenticated user","description":"List email templates for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"description":"Page number (1-based).","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","required":false,"description":"Number of items per page (max 100).","schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"search","in":"query","required":false,"description":"Search term applied to template name.","schema":{"type":"string"}},{"name":"sortBy","in":"query","required":false,"description":"Field to sort by. Defaults to updated_at.","schema":{"enum":["name","created_at","updated_at"],"type":"string"}},{"name":"sortOrder","in":"query","required":false,"description":"Sort order, ascending or descending. Defaults to desc.","schema":{"enum":["asc","desc"],"type":"string"}}],"responses":{"200":{"description":"List of email templates for the user with pagination metadata.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailTemplate"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailTemplate"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailTemplate"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}}}},"post":{"operationId":"postapiusertemplates","summary":"Create a new email template for the authenticated user","description":"Create a new email template for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Name of the template."},"engine":{"type":"string","nullable":true,"description":"Template engine used (e.g., handlebars, liquid). Defaults to handlebars."},"body_html":{"type":"string","nullable":true,"description":"HTML body for the template. Either body_html or body_text is required."},"body_text":{"type":"string","nullable":true,"description":"Plain text body for the template. Either body_html or body_text is required."},"is_active":{"type":"boolean","nullable":true,"description":"Whether this template is active. Defaults to true."},"subject_line":{"type":"string","nullable":true,"description":"Default subject line for this template (optional)."},"thumbnail_url":{"type":"string","nullable":true,"description":"Optional thumbnail URL used for previewing the template."},"required_variables":{"type":"array","items":{"type":"string"},"nullable":true,"description":"List of variables required by this template (e.g., {{firstName}})."}}},"example":{}}}},"responses":{"201":{"description":"Template created successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"400":{"description":"Missing required fields or invalid body (e.g., missing both body_html and body_text).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"409":{"description":"Template with this name already exists for the user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}}}}},"/api/user/templates/{id}":{"get":{"operationId":"getapiusertemplatesid","summary":"Get a single email template for the authenticated user","description":"Get a single email template for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"400":{"description":"Missing template id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"404":{"description":"Template not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}}}},"put":{"operationId":"putapiusertemplatesid","summary":"Update an existing email template for the authenticated user","description":"Update an existing email template for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","nullable":true,"description":"New template name (optional)."},"engine":{"type":"string","nullable":true,"description":"Updated template engine (optional)."},"body_html":{"type":"string","nullable":true,"description":"Updated HTML body (optional)."},"body_text":{"type":"string","nullable":true,"description":"Updated text body (optional)."},"is_active":{"type":"boolean","nullable":true,"description":"Whether the template is active (optional)."},"is_archived":{"type":"boolean","nullable":true,"description":"Whether the template is archived (optional)."},"subject_line":{"type":"string","nullable":true,"description":"Updated subject line (optional)."},"thumbnail_url":{"type":"string","nullable":true,"description":"Updated thumbnail URL (optional)."},"required_variables":{"type":"array","items":{"type":"string"},"nullable":true,"description":"Updated list of required variables (optional)."}}},"example":{}}}},"responses":{"200":{"description":"Template updated successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"400":{"description":"Invalid input (e.g., empty name).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"404":{"description":"Template not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"409":{"description":"Template with this name already exists for the user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplate"}}}}}},"delete":{"operationId":"deleteapiusertemplatesid","summary":"Archive (soft delete) an email template for the authenticated user","description":"Archive (soft delete) an email template for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template archived successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template deleted successfully."}}}}}},"400":{"description":"Missing template id.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template deleted successfully."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template deleted successfully."}}}}}},"404":{"description":"Template not found.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template deleted successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template deleted successfully."}}}}}}}}},"/api/user/templates/{id}/get-pre-signed-url":{"post":{"operationId":"postapiusertemplatesidgetpresignedurl","summary":"Get pre-signed URL for template file upload","description":"Generates a pre-signed URL for uploading a file attachment to a specific template. The template must belong to the authenticated user. A unique file key will be generated automatically and stored as a template attachment.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["file_name","file_type"],"properties":{"file_name":{"type":"string","example":"attachment.pdf","description":"Name of the file to be uploaded."},"file_size":{"type":"integer","example":1024000,"nullable":true,"description":"Size of the file in bytes."},"file_type":{"type":"string","example":"pdf","description":"File type/extension (without the dot)."}}},"example":{}}}},"responses":{"200":{"description":"Pre-signed URL generated successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for uploading the file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment. Initially set to DRAFT."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}},"description":"Template attachment object that was created."},"readURL":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for reading/downloading the file from S3."}}}}}},"400":{"description":"Missing template id, file name, or file type","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for uploading the file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment. Initially set to DRAFT."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}},"description":"Template attachment object that was created."},"readURL":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for reading/downloading the file from S3."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for uploading the file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment. Initially set to DRAFT."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}},"description":"Template attachment object that was created."},"readURL":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for reading/downloading the file from S3."}}}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for uploading the file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment. Initially set to DRAFT."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}},"description":"Template attachment object that was created."},"readURL":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for reading/downloading the file from S3."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for uploading the file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment. Initially set to DRAFT."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}},"description":"Template attachment object that was created."},"readURL":{"type":"string","example":"https://s3.amazonaws.com/bucket/template-files/{id}/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for reading/downloading the file from S3."}}}}}}}}},"/api/user/templates/{id}/trigger":{"post":{"operationId":"postapiusertemplatesidtrigger","summary":"Trigger template attachment upload completion","description":"Marks template attachments as uploaded after files have been successfully uploaded to S3 using the pre-signed URLs. The template must belong to the authenticated user.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["attachmentIds"],"properties":{"attachmentIds":{"type":"array","items":{"type":"string","format":"uuid"},"example":["550e8400-e29b-41d4-a716-446655440000","660e8400-e29b-41d4-a716-446655440001"],"description":"Array of attachment IDs to mark as uploaded."}}},"example":{}}}},"responses":{"200":{"description":"Template attachments marked as uploaded successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment uploaded successfully."}}}}}},"400":{"description":"Missing template id or attachment IDs","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment uploaded successfully."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment uploaded successfully."}}}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment uploaded successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment uploaded successfully."}}}}}}}}},"/api/user/templates/{id}/attachments":{"get":{"operationId":"getapiusertemplatesidattachments","summary":"List all template attachments","description":"Retrieves all attachments for a specific template. The template must belong to the authenticated user. Returns attachments ordered by creation date (newest first), each with a pre-signed read URL.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved list of template attachments.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment."},"readURL":{"type":"string","description":"Pre-signed URL for reading/downloading the file from S3."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}}}}}}}}},"400":{"description":"Missing template id","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment."},"readURL":{"type":"string","description":"Pre-signed URL for reading/downloading the file from S3."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}}}}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment."},"readURL":{"type":"string","description":"Pre-signed URL for reading/downloading the file from S3."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}}}}}}}}},"404":{"description":"Template attachments not found","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment."},"readURL":{"type":"string","description":"Pre-signed URL for reading/downloading the file from S3."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}}}}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the template attachment."},"status":{"enum":["DRAFT","UPLOADED"],"type":"string","description":"Status of the template attachment."},"readURL":{"type":"string","description":"Pre-signed URL for reading/downloading the file from S3."},"file_key":{"type":"string","description":"S3 key/path where the file is stored."},"file_name":{"type":"string","description":"Name of the uploaded file."},"file_size":{"type":"number","description":"Size of the file in bytes."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the attachment was created."},"content_type":{"type":"string","description":"MIME type/content type of the file."},"email_template_id":{"type":"string","format":"uuid","description":"ID of the email template this attachment belongs to."}}}}}}}}}}}},"/api/user/templates/{id}/attachments/{attachmentId}":{"delete":{"operationId":"deleteapiusertemplatesidattachmentsattachmentid","summary":"Delete a template attachment","description":"Deletes a template attachment by ID. The attachment must belong to the specified template, and the template must belong to the authenticated user. This will also delete the file from S3.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"attachmentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template attachment deleted successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment deleted successfully."}}}}}},"400":{"description":"Missing template id or attachment id","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment deleted successfully."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment deleted successfully."}}}}}},"404":{"description":"Template attachment not found","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment deleted successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Template attachment deleted successfully."}}}}}}}}},"/api/user/groups/{id}":{"get":{"operationId":"getapiusergroupsid","summary":"Get details of a group for the authenticated user","description":"Get details of a group for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Group details.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"404":{"description":"Group not found.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}}}},"put":{"operationId":"putapiusergroupsid","summary":"Update an existing group for the authenticated user","description":"Update an existing group for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","nullable":true,"description":"New group name (optional)."},"description":{"type":"string","nullable":true,"description":"New description (optional)."}}},"example":{}}}},"responses":{"200":{"description":"Group updated successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"400":{"description":"Invalid input (e.g., empty name)","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"404":{"description":"Group not found.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"409":{"description":"Group with this name already exists for the user","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}}}}}}},"delete":{"operationId":"deleteapiusergroupsid","summary":"Delete a group for the authenticated user","description":"Delete a group for the authenticated user","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Group deleted successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Group deleted successfully."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Group deleted successfully."}}}}}},"404":{"description":"Group not found.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Group deleted successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Group deleted successfully."}}}}}}}}},"/api/transactional-email/send":{"post":{"operationId":"postapitransactionalemailsend","summary":"Send a single transactional email","description":"Send a transactional email to a single recipient using an API key.","tags":["Transactional Email"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["from","to","subject","content"],"properties":{"to":{"type":"string","format":"email","example":"user@example.com","description":"Recipient email address."},"from":{"type":"string","format":"email","example":"no-reply@example.com","description":"Sender email address."},"content":{"type":"string","example":"<p>Hello, welcome to Pinnacle Email!</p>","description":"Email body content (HTML or text)."},"subject":{"type":"string","example":"Welcome to Pinnacle Email","description":"Email subject line."},"fromName":{"type":"string","example":"Pinnacle Support","nullable":true,"description":"Display name of the sender."},"attachments":{"type":"array","items":{"type":"object","required":["filename","content"],"properties":{"content":{"type":"string","example":"JVBERi0xLjQKJ...","description":"Base64-encoded file content."},"filename":{"type":"string","example":"invoice.pdf"}}},"nullable":true,"description":"Optional array of attachments as base64-encoded content."}}},"example":{}}}},"responses":{"200":{"description":"Transactional email request accepted and queued.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Transactional email request accepted."},"requestId":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}}}}},"400":{"description":"Validation error: missing/invalid fields, invalid email addresses, unverified sender domain, or blacklisted recipient domain.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Transactional email request accepted."},"requestId":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}}}}},"401":{"description":"Unauthorized (missing or invalid API key, or no user).","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Transactional email request accepted."},"requestId":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Transactional email request accepted."},"requestId":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"}}}}}}}}},"/api/user/imports/{groupId}":{"post":{"operationId":"postapiuserimportsgroupid","summary":"Create a new import job for the authenticated user","description":"Creates an import job for a specific group and returns a presigned URL for uploading a CSV file. The file must be a CSV file.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"groupId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["original_name","file_type"],"properties":{"file_type":{"type":"string","example":"text/csv","description":"MIME type of the file."},"original_name":{"type":"string","example":"contacts.csv","description":"Original name of the file to be imported."}}},"example":{}}}},"responses":{"201":{"description":"Import job created successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Presigned URL for uploading the CSV file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the import job."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created the import job."},"admin_id":{"type":"string","format":"uuid","nullable":true,"description":"ID of the admin associated with the user."},"file_key":{"type":"string","description":"S3 key where the file will be stored."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was created."},"original_name":{"type":"string","description":"Original name of the file."}}},"message":{"type":"string","example":"Import job created successfully."}}}}}},"400":{"description":"Bad request - missing or invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Presigned URL for uploading the CSV file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the import job."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created the import job."},"admin_id":{"type":"string","format":"uuid","nullable":true,"description":"ID of the admin associated with the user."},"file_key":{"type":"string","description":"S3 key where the file will be stored."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was created."},"original_name":{"type":"string","description":"Original name of the file."}}},"message":{"type":"string","example":"Import job created successfully."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Presigned URL for uploading the CSV file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the import job."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created the import job."},"admin_id":{"type":"string","format":"uuid","nullable":true,"description":"ID of the admin associated with the user."},"file_key":{"type":"string","description":"S3 key where the file will be stored."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was created."},"original_name":{"type":"string","description":"Original name of the file."}}},"message":{"type":"string","example":"Import job created successfully."}}}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Presigned URL for uploading the CSV file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the import job."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created the import job."},"admin_id":{"type":"string","format":"uuid","nullable":true,"description":"ID of the admin associated with the user."},"file_key":{"type":"string","description":"S3 key where the file will be stored."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was created."},"original_name":{"type":"string","description":"Original name of the file."}}},"message":{"type":"string","example":"Import job created successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Presigned URL for uploading the CSV file to S3."},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the import job."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created the import job."},"admin_id":{"type":"string","format":"uuid","nullable":true,"description":"ID of the admin associated with the user."},"file_key":{"type":"string","description":"S3 key where the file will be stored."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was created."},"original_name":{"type":"string","description":"Original name of the file."}}},"message":{"type":"string","example":"Import job created successfully."}}}}}}}}},"/api/user/imports/{groupId}/{id}/trigger":{"post":{"operationId":"postapiuserimportsgroupididtrigger","summary":"Trigger an import job for processing","description":"Triggers a pending import job to start processing. The import job must be in PENDING status. Once triggered, the job status will change to QUEUED and will be processed by the worker.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"groupId","in":"path","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["groupId","id"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier of the import job to trigger.","x-parameter-in":"path"},"groupId":{"type":"string","format":"uuid","description":"Unique identifier of the group associated with the import job.","x-parameter-in":"path"}}},"example":{}}}},"responses":{"200":{"description":"Import job triggered successfully.","content":{"application/json":{"schema":{"type":"object","example":{"message":"Import job triggered successfully."},"properties":{"message":{"type":"string","example":"Import job triggered successfully."}}}}}},"400":{"description":"Bad request - import job is not pending or missing id","content":{"application/json":{"schema":{"type":"object","example":{"message":"Import job triggered successfully."},"properties":{"message":{"type":"string","example":"Import job triggered successfully."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","example":{"message":"Import job triggered successfully."},"properties":{"message":{"type":"string","example":"Import job triggered successfully."}}}}}},"404":{"description":"User or import job not found","content":{"application/json":{"schema":{"type":"object","example":{"message":"Import job triggered successfully."},"properties":{"message":{"type":"string","example":"Import job triggered successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","example":{"message":"Import job triggered successfully."},"properties":{"message":{"type":"string","example":"Import job triggered successfully."}}}}}}}}},"/api/user/imports/{groupId}/all":{"get":{"operationId":"getapiuserimportsgroupidall","summary":"List all import jobs for a specific group","description":"Retrieves a paginated list of all import jobs for a specific group created by the authenticated user. Supports search, sorting, and pagination. Search is performed on the original_name field (case-insensitive).","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"groupId","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number for pagination (default: 1).","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","required":false,"description":"Number of items per page (default: 10).","schema":{"type":"integer","default":10,"minimum":1}},{"name":"search","in":"query","required":false,"description":"Search term to filter import jobs by original file name (case-insensitive).","schema":{"type":"string"}},{"name":"sortBy","in":"query","required":false,"description":"Field to sort by (default: created_at).","schema":{"type":"string","default":"created_at"}},{"name":"sortOrder","in":"query","required":false,"description":"Sort order: 'asc' or 'desc' (default: desc).","schema":{"enum":["asc","desc"],"type":"string","default":"desc"}}],"responses":{"200":{"description":"Successfully retrieved list of import jobs.","content":{"application/json":{"schema":{"type":"object","example":{"data":[{"id":"123e4567-e89b-12d3-a456-426614174000","status":"COMPLETED","user_id":"123e4567-e89b-12d3-a456-426614174001","admin_id":"123e4567-e89b-12d3-a456-426614174002","file_key":"imports/123e4567-e89b-12d3-a456-426614174001/abc123.csv","created_at":"2024-01-15T10:30:00Z","updated_at":"2024-01-15T10:35:00Z","original_name":"contacts.csv","failure_reason":null,"total_contacts":100,"failed_contacts":2,"processed_contacts":98},{"id":"123e4567-e89b-12d3-a456-426614174003","status":"PROCESSING","user_id":"123e4567-e89b-12d3-a456-426614174001","admin_id":"123e4567-e89b-12d3-a456-426614174002","file_key":"imports/123e4567-e89b-12d3-a456-426614174001/def456.csv","created_at":"2024-01-16T14:20:00Z","updated_at":"2024-01-16T14:22:00Z","original_name":"new_contacts.csv","failure_reason":null,"total_contacts":50,"failed_contacts":0,"processed_contacts":25}],"page":1,"limit":10,"total":2},"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the import job."},"status":{"enum":["PENDING","QUEUED","PROCESSING","COMPLETED","FAILED"],"type":"string","description":"Current status of the import job."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created the import job."},"admin_id":{"type":"string","format":"uuid","description":"ID of the admin associated with the user."},"file_key":{"type":"string","description":"S3 key where the file is stored."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was created."},"updated_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was last updated."},"original_name":{"type":"string","description":"Original name of the imported file."},"failure_reason":{"type":"string","nullable":true,"description":"Reason for failure if the import job failed."},"total_contacts":{"type":"integer","default":0,"description":"Total number of contacts in the import file."},"failed_contacts":{"type":"integer","default":0,"description":"Number of contacts that failed to import."},"processed_contacts":{"type":"integer","default":0,"description":"Number of contacts successfully processed."}}}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of import jobs returned in this response."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","example":{"data":[{"id":"123e4567-e89b-12d3-a456-426614174000","status":"COMPLETED","user_id":"123e4567-e89b-12d3-a456-426614174001","admin_id":"123e4567-e89b-12d3-a456-426614174002","file_key":"imports/123e4567-e89b-12d3-a456-426614174001/abc123.csv","created_at":"2024-01-15T10:30:00Z","updated_at":"2024-01-15T10:35:00Z","original_name":"contacts.csv","failure_reason":null,"total_contacts":100,"failed_contacts":2,"processed_contacts":98},{"id":"123e4567-e89b-12d3-a456-426614174003","status":"PROCESSING","user_id":"123e4567-e89b-12d3-a456-426614174001","admin_id":"123e4567-e89b-12d3-a456-426614174002","file_key":"imports/123e4567-e89b-12d3-a456-426614174001/def456.csv","created_at":"2024-01-16T14:20:00Z","updated_at":"2024-01-16T14:22:00Z","original_name":"new_contacts.csv","failure_reason":null,"total_contacts":50,"failed_contacts":0,"processed_contacts":25}],"page":1,"limit":10,"total":2},"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the import job."},"status":{"enum":["PENDING","QUEUED","PROCESSING","COMPLETED","FAILED"],"type":"string","description":"Current status of the import job."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created the import job."},"admin_id":{"type":"string","format":"uuid","description":"ID of the admin associated with the user."},"file_key":{"type":"string","description":"S3 key where the file is stored."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was created."},"updated_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was last updated."},"original_name":{"type":"string","description":"Original name of the imported file."},"failure_reason":{"type":"string","nullable":true,"description":"Reason for failure if the import job failed."},"total_contacts":{"type":"integer","default":0,"description":"Total number of contacts in the import file."},"failed_contacts":{"type":"integer","default":0,"description":"Number of contacts that failed to import."},"processed_contacts":{"type":"integer","default":0,"description":"Number of contacts successfully processed."}}}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of import jobs returned in this response."}}}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object","example":{"data":[{"id":"123e4567-e89b-12d3-a456-426614174000","status":"COMPLETED","user_id":"123e4567-e89b-12d3-a456-426614174001","admin_id":"123e4567-e89b-12d3-a456-426614174002","file_key":"imports/123e4567-e89b-12d3-a456-426614174001/abc123.csv","created_at":"2024-01-15T10:30:00Z","updated_at":"2024-01-15T10:35:00Z","original_name":"contacts.csv","failure_reason":null,"total_contacts":100,"failed_contacts":2,"processed_contacts":98},{"id":"123e4567-e89b-12d3-a456-426614174003","status":"PROCESSING","user_id":"123e4567-e89b-12d3-a456-426614174001","admin_id":"123e4567-e89b-12d3-a456-426614174002","file_key":"imports/123e4567-e89b-12d3-a456-426614174001/def456.csv","created_at":"2024-01-16T14:20:00Z","updated_at":"2024-01-16T14:22:00Z","original_name":"new_contacts.csv","failure_reason":null,"total_contacts":50,"failed_contacts":0,"processed_contacts":25}],"page":1,"limit":10,"total":2},"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the import job."},"status":{"enum":["PENDING","QUEUED","PROCESSING","COMPLETED","FAILED"],"type":"string","description":"Current status of the import job."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created the import job."},"admin_id":{"type":"string","format":"uuid","description":"ID of the admin associated with the user."},"file_key":{"type":"string","description":"S3 key where the file is stored."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was created."},"updated_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was last updated."},"original_name":{"type":"string","description":"Original name of the imported file."},"failure_reason":{"type":"string","nullable":true,"description":"Reason for failure if the import job failed."},"total_contacts":{"type":"integer","default":0,"description":"Total number of contacts in the import file."},"failed_contacts":{"type":"integer","default":0,"description":"Number of contacts that failed to import."},"processed_contacts":{"type":"integer","default":0,"description":"Number of contacts successfully processed."}}}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of import jobs returned in this response."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","example":{"data":[{"id":"123e4567-e89b-12d3-a456-426614174000","status":"COMPLETED","user_id":"123e4567-e89b-12d3-a456-426614174001","admin_id":"123e4567-e89b-12d3-a456-426614174002","file_key":"imports/123e4567-e89b-12d3-a456-426614174001/abc123.csv","created_at":"2024-01-15T10:30:00Z","updated_at":"2024-01-15T10:35:00Z","original_name":"contacts.csv","failure_reason":null,"total_contacts":100,"failed_contacts":2,"processed_contacts":98},{"id":"123e4567-e89b-12d3-a456-426614174003","status":"PROCESSING","user_id":"123e4567-e89b-12d3-a456-426614174001","admin_id":"123e4567-e89b-12d3-a456-426614174002","file_key":"imports/123e4567-e89b-12d3-a456-426614174001/def456.csv","created_at":"2024-01-16T14:20:00Z","updated_at":"2024-01-16T14:22:00Z","original_name":"new_contacts.csv","failure_reason":null,"total_contacts":50,"failed_contacts":0,"processed_contacts":25}],"page":1,"limit":10,"total":2},"properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for the import job."},"status":{"enum":["PENDING","QUEUED","PROCESSING","COMPLETED","FAILED"],"type":"string","description":"Current status of the import job."},"user_id":{"type":"string","format":"uuid","description":"ID of the user who created the import job."},"admin_id":{"type":"string","format":"uuid","description":"ID of the admin associated with the user."},"file_key":{"type":"string","description":"S3 key where the file is stored."},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was created."},"updated_at":{"type":"string","format":"date-time","description":"Timestamp when the import job was last updated."},"original_name":{"type":"string","description":"Original name of the imported file."},"failure_reason":{"type":"string","nullable":true,"description":"Reason for failure if the import job failed."},"total_contacts":{"type":"integer","default":0,"description":"Total number of contacts in the import file."},"failed_contacts":{"type":"integer","default":0,"description":"Number of contacts that failed to import."},"processed_contacts":{"type":"integer","default":0,"description":"Number of contacts successfully processed."}}}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of import jobs returned in this response."}}}}}}}}},"/api/user/campaigns":{"get":{"operationId":"getapiusercampaigns","summary":"List email campaigns for the authenticated user","description":"Retrieves a paginated list of campaigns for the authenticated user. Supports search and sorting.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"description":"Page number (starts at 1).","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","required":false,"description":"Number of items per page (max 100).","schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"search","in":"query","required":false,"description":"Search term applied to campaign name, subject line, or from email.","schema":{"type":"string"}},{"name":"sortBy","in":"query","required":false,"description":"Field to sort by. Defaults to created_at.","schema":{"enum":["name","status","created_at","updated_at","scheduled_at"],"type":"string"}},{"name":"sortOrder","in":"query","required":false,"description":"Sort order (asc or desc). Defaults to desc.","schema":{"enum":["asc","desc"],"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved list of campaigns.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of campaigns matching the filters."},"totalPages":{"type":"integer","description":"Total number of pages."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of campaigns matching the filters."},"totalPages":{"type":"integer","description":"Total number of pages."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of campaigns matching the filters."},"totalPages":{"type":"integer","description":"Total number of pages."}}}}}}}},"post":{"operationId":"postapiusercampaigns","summary":"Create a new email campaign for the authenticated user","description":"Creates a new email campaign in DRAFT status. The from_email domain must match a verified (ACTIVE) sending identity for the user. Target groups must belong to the user.","tags":["User"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Summer Sale 2024","description":"Name of the campaign (required)."},"content":{"type":"string","nullable":true,"description":"HTML content for the campaign email."},"settings":{"type":"object","example":{},"nullable":true,"description":"Additional campaign settings as a JSON object."},"from_name":{"type":"string","nullable":true,"description":"Display name for the sender."},"from_email":{"type":"string","format":"email","nullable":true,"description":"From email address. Domain must match a verified (ACTIVE) sending identity for the user."},"template_id":{"type":"string","format":"uuid","nullable":true,"description":"ID of the email template to use for this campaign (optional)."},"preview_text":{"type":"string","nullable":true,"maxLength":255,"description":"Preview text shown in email clients (max 255 characters)."},"scheduled_at":{"type":"string","format":"date-time","nullable":true,"description":"ISO date string for when to schedule the campaign (must be a future date)."},"subject_line":{"type":"string","nullable":true,"maxLength":998,"description":"Subject line for the campaign email (max 998 characters)."},"target_groups":{"type":"array","items":{"type":"string","format":"uuid"},"nullable":true,"description":"Array of group IDs to target with this campaign. All groups must belong to the user."},"reply_to_email":{"type":"string","format":"email","nullable":true,"description":"Reply-to email address."}}},"example":{}}}},"responses":{"201":{"description":"Campaign created successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Bad request - validation errors (missing required fields, invalid email format, invalid domain, etc.).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"404":{"description":"Template or target groups not found or don't belong to the user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"409":{"description":"A campaign with this name already exists for this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}}}}},"/api/user/campaigns/{id}":{"get":{"operationId":"getapiusercampaignsid","summary":"Get a single email campaign for the authenticated user","description":"Retrieves detailed information about a specific campaign by ID. The campaign must belong to the authenticated user and not be deleted.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Campaign details retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Missing campaign ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"404":{"description":"Campaign not found or deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}}}},"put":{"operationId":"putapiusercampaignsid","summary":"Update an existing email campaign for the authenticated user","description":"Updates an existing campaign. All fields are optional - only provided fields will be updated. The campaign must be in DRAFT or SCHEDULED status to be edited. The from_email domain must match a verified (ACTIVE) sending identity for the user. Target groups must belong to the user.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","nullable":true,"description":"Updated campaign name (optional)."},"content":{"type":"string","nullable":true,"description":"Updated HTML content for the campaign email (optional)."},"settings":{"type":"object","nullable":true,"description":"Updated campaign settings as a JSON object (optional)."},"from_name":{"type":"string","nullable":true,"description":"Updated display name for the sender (optional)."},"from_email":{"type":"string","format":"email","nullable":true,"description":"Updated from email address. Domain must match a verified (ACTIVE) sending identity (optional)."},"template_id":{"type":"string","format":"uuid","nullable":true,"description":"Updated template ID (optional). Set to null to remove template association."},"preview_text":{"type":"string","nullable":true,"maxLength":255,"description":"Updated preview text (optional, max 255 characters)."},"scheduled_at":{"type":"string","format":"date-time","nullable":true,"description":"Updated scheduled date and time (optional, must be a future date). Set to null to remove schedule. Campaign status will automatically be set to SCHEDULED if scheduled_at is provided, or DRAFT if removed."},"subject_line":{"type":"string","nullable":true,"maxLength":998,"description":"Updated subject line (optional, max 998 characters)."},"target_groups":{"type":"array","items":{"type":"string","format":"uuid"},"nullable":true,"description":"Updated array of group IDs to target. Pass empty array to remove all groups (optional)."},"reply_to_email":{"type":"string","format":"email","nullable":true,"description":"Updated reply-to email address (optional)."}}},"example":{}}}},"responses":{"200":{"description":"Campaign updated successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"Bad request - validation errors (invalid email format, invalid domain, campaign not in editable status, etc.).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"404":{"description":"Campaign, template, or target groups not found or don't belong to the user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}}}},"delete":{"operationId":"deleteapiusercampaignsid","summary":"Delete (soft delete) an email campaign for the authenticated user","description":"Soft deletes a campaign by setting is_deleted to true. The campaign will no longer appear in list queries but data is preserved.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Campaign deleted successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign deleted successfully."}}}}}},"400":{"description":"Missing campaign ID.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign deleted successfully."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign deleted successfully."}}}}}},"404":{"description":"Campaign not found or already deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign deleted successfully."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Campaign deleted successfully."}}}}}}}}},"/api/user/campaigns/{id}/analytics":{"get":{"operationId":"getapiusercampaignsidanalytics","summary":"Get campaign analytics for the authenticated user","description":"Returns delivery status counts and calculated rates for a specific campaign. Queued emails are excluded.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Campaign analytics retrieved successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"rates":{"type":"object","properties":{"openRate":{"type":"number","example":69.57},"clickRate":{"type":"number","example":47.83},"bounceRate":{"type":"number","example":1.67},"failureRate":{"type":"number","example":2.5},"deliveryRate":{"type":"number","example":95.83},"complaintRate":{"type":"number","example":0.87}}},"replyTo":{"type":"string","format":"email","example":"support@pinnacle.in","nullable":true},"subject":{"type":"string","example":"Big Spring Savings Inside","nullable":true},"summary":{"type":"object","properties":{"totalOpens":{"type":"integer","example":200},"totalClicks":{"type":"integer","example":140},"totalFailed":{"type":"integer","example":3},"uniqueOpens":{"type":"integer","example":80},"totalBounced":{"type":"integer","example":2},"uniqueClicks":{"type":"integer","example":55},"totalDelivered":{"type":"integer","example":115},"totalComplaints":{"type":"integer","example":1},"totalEmailsSent":{"type":"integer","example":120}}},"fromName":{"type":"string","example":"Pinnacle Email","nullable":true},"fromEmail":{"type":"string","format":"email","example":"no-reply@pinnacle.in","nullable":true},"campaignId":{"type":"string","format":"uuid"},"completedAt":{"type":"string","format":"date-time","example":"2024-06-01T12:30:00.000Z","nullable":true},"campaignName":{"type":"string","example":"Spring Sale Campaign","nullable":true}}}}}},"400":{"description":"Missing campaign ID.","content":{"application/json":{"schema":{"type":"object","properties":{"rates":{"type":"object","properties":{"openRate":{"type":"number","example":69.57},"clickRate":{"type":"number","example":47.83},"bounceRate":{"type":"number","example":1.67},"failureRate":{"type":"number","example":2.5},"deliveryRate":{"type":"number","example":95.83},"complaintRate":{"type":"number","example":0.87}}},"replyTo":{"type":"string","format":"email","example":"support@pinnacle.in","nullable":true},"subject":{"type":"string","example":"Big Spring Savings Inside","nullable":true},"summary":{"type":"object","properties":{"totalOpens":{"type":"integer","example":200},"totalClicks":{"type":"integer","example":140},"totalFailed":{"type":"integer","example":3},"uniqueOpens":{"type":"integer","example":80},"totalBounced":{"type":"integer","example":2},"uniqueClicks":{"type":"integer","example":55},"totalDelivered":{"type":"integer","example":115},"totalComplaints":{"type":"integer","example":1},"totalEmailsSent":{"type":"integer","example":120}}},"fromName":{"type":"string","example":"Pinnacle Email","nullable":true},"fromEmail":{"type":"string","format":"email","example":"no-reply@pinnacle.in","nullable":true},"campaignId":{"type":"string","format":"uuid"},"completedAt":{"type":"string","format":"date-time","example":"2024-06-01T12:30:00.000Z","nullable":true},"campaignName":{"type":"string","example":"Spring Sale Campaign","nullable":true}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"rates":{"type":"object","properties":{"openRate":{"type":"number","example":69.57},"clickRate":{"type":"number","example":47.83},"bounceRate":{"type":"number","example":1.67},"failureRate":{"type":"number","example":2.5},"deliveryRate":{"type":"number","example":95.83},"complaintRate":{"type":"number","example":0.87}}},"replyTo":{"type":"string","format":"email","example":"support@pinnacle.in","nullable":true},"subject":{"type":"string","example":"Big Spring Savings Inside","nullable":true},"summary":{"type":"object","properties":{"totalOpens":{"type":"integer","example":200},"totalClicks":{"type":"integer","example":140},"totalFailed":{"type":"integer","example":3},"uniqueOpens":{"type":"integer","example":80},"totalBounced":{"type":"integer","example":2},"uniqueClicks":{"type":"integer","example":55},"totalDelivered":{"type":"integer","example":115},"totalComplaints":{"type":"integer","example":1},"totalEmailsSent":{"type":"integer","example":120}}},"fromName":{"type":"string","example":"Pinnacle Email","nullable":true},"fromEmail":{"type":"string","format":"email","example":"no-reply@pinnacle.in","nullable":true},"campaignId":{"type":"string","format":"uuid"},"completedAt":{"type":"string","format":"date-time","example":"2024-06-01T12:30:00.000Z","nullable":true},"campaignName":{"type":"string","example":"Spring Sale Campaign","nullable":true}}}}}},"404":{"description":"Campaign not found or deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"rates":{"type":"object","properties":{"openRate":{"type":"number","example":69.57},"clickRate":{"type":"number","example":47.83},"bounceRate":{"type":"number","example":1.67},"failureRate":{"type":"number","example":2.5},"deliveryRate":{"type":"number","example":95.83},"complaintRate":{"type":"number","example":0.87}}},"replyTo":{"type":"string","format":"email","example":"support@pinnacle.in","nullable":true},"subject":{"type":"string","example":"Big Spring Savings Inside","nullable":true},"summary":{"type":"object","properties":{"totalOpens":{"type":"integer","example":200},"totalClicks":{"type":"integer","example":140},"totalFailed":{"type":"integer","example":3},"uniqueOpens":{"type":"integer","example":80},"totalBounced":{"type":"integer","example":2},"uniqueClicks":{"type":"integer","example":55},"totalDelivered":{"type":"integer","example":115},"totalComplaints":{"type":"integer","example":1},"totalEmailsSent":{"type":"integer","example":120}}},"fromName":{"type":"string","example":"Pinnacle Email","nullable":true},"fromEmail":{"type":"string","format":"email","example":"no-reply@pinnacle.in","nullable":true},"campaignId":{"type":"string","format":"uuid"},"completedAt":{"type":"string","format":"date-time","example":"2024-06-01T12:30:00.000Z","nullable":true},"campaignName":{"type":"string","example":"Spring Sale Campaign","nullable":true}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"rates":{"type":"object","properties":{"openRate":{"type":"number","example":69.57},"clickRate":{"type":"number","example":47.83},"bounceRate":{"type":"number","example":1.67},"failureRate":{"type":"number","example":2.5},"deliveryRate":{"type":"number","example":95.83},"complaintRate":{"type":"number","example":0.87}}},"replyTo":{"type":"string","format":"email","example":"support@pinnacle.in","nullable":true},"subject":{"type":"string","example":"Big Spring Savings Inside","nullable":true},"summary":{"type":"object","properties":{"totalOpens":{"type":"integer","example":200},"totalClicks":{"type":"integer","example":140},"totalFailed":{"type":"integer","example":3},"uniqueOpens":{"type":"integer","example":80},"totalBounced":{"type":"integer","example":2},"uniqueClicks":{"type":"integer","example":55},"totalDelivered":{"type":"integer","example":115},"totalComplaints":{"type":"integer","example":1},"totalEmailsSent":{"type":"integer","example":120}}},"fromName":{"type":"string","example":"Pinnacle Email","nullable":true},"fromEmail":{"type":"string","format":"email","example":"no-reply@pinnacle.in","nullable":true},"campaignId":{"type":"string","format":"uuid"},"completedAt":{"type":"string","format":"date-time","example":"2024-06-01T12:30:00.000Z","nullable":true},"campaignName":{"type":"string","example":"Spring Sale Campaign","nullable":true}}}}}}}}},"/api/user/campaigns/{id}/link-analytics":{"get":{"operationId":"getapiusercampaignsidlinkanalytics","summary":"Get campaign link analytics for the authenticated user","description":"Returns a paginated list of tracked links for a campaign with click counts. Supports search by URL or token.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number (1-indexed).","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","required":false,"description":"Number of rows per page (max 100).","schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"search","in":"query","required":false,"description":"Search term applied to original URL or token.","schema":{"type":"string"}}],"responses":{"200":{"description":"Campaign link analytics retrieved successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"token":{"type":"string","example":"abc123"},"ipAddress":{"type":"string","example":"192.0.2.1","nullable":true},"clickCount":{"type":"integer","example":42},"originalUrl":{"type":"string","example":"https://example.com/sale"}}}},"filters":{"type":"object","properties":{"search":{"type":"string","example":"example.com","nullable":true}}},"campaignId":{"type":"string","format":"uuid"},"pagination":{"type":"object","properties":{"page":{"type":"integer","example":1},"limit":{"type":"integer","example":10},"totalPages":{"type":"integer","example":3},"totalRecords":{"type":"integer","example":25}}}}}}}},"400":{"description":"Invalid request parameters.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"token":{"type":"string","example":"abc123"},"ipAddress":{"type":"string","example":"192.0.2.1","nullable":true},"clickCount":{"type":"integer","example":42},"originalUrl":{"type":"string","example":"https://example.com/sale"}}}},"filters":{"type":"object","properties":{"search":{"type":"string","example":"example.com","nullable":true}}},"campaignId":{"type":"string","format":"uuid"},"pagination":{"type":"object","properties":{"page":{"type":"integer","example":1},"limit":{"type":"integer","example":10},"totalPages":{"type":"integer","example":3},"totalRecords":{"type":"integer","example":25}}}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"token":{"type":"string","example":"abc123"},"ipAddress":{"type":"string","example":"192.0.2.1","nullable":true},"clickCount":{"type":"integer","example":42},"originalUrl":{"type":"string","example":"https://example.com/sale"}}}},"filters":{"type":"object","properties":{"search":{"type":"string","example":"example.com","nullable":true}}},"campaignId":{"type":"string","format":"uuid"},"pagination":{"type":"object","properties":{"page":{"type":"integer","example":1},"limit":{"type":"integer","example":10},"totalPages":{"type":"integer","example":3},"totalRecords":{"type":"integer","example":25}}}}}}}},"404":{"description":"Campaign not found or deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"token":{"type":"string","example":"abc123"},"ipAddress":{"type":"string","example":"192.0.2.1","nullable":true},"clickCount":{"type":"integer","example":42},"originalUrl":{"type":"string","example":"https://example.com/sale"}}}},"filters":{"type":"object","properties":{"search":{"type":"string","example":"example.com","nullable":true}}},"campaignId":{"type":"string","format":"uuid"},"pagination":{"type":"object","properties":{"page":{"type":"integer","example":1},"limit":{"type":"integer","example":10},"totalPages":{"type":"integer","example":3},"totalRecords":{"type":"integer","example":25}}}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"token":{"type":"string","example":"abc123"},"ipAddress":{"type":"string","example":"192.0.2.1","nullable":true},"clickCount":{"type":"integer","example":42},"originalUrl":{"type":"string","example":"https://example.com/sale"}}}},"filters":{"type":"object","properties":{"search":{"type":"string","example":"example.com","nullable":true}}},"campaignId":{"type":"string","format":"uuid"},"pagination":{"type":"object","properties":{"page":{"type":"integer","example":1},"limit":{"type":"integer","example":10},"totalPages":{"type":"integer","example":3},"totalRecords":{"type":"integer","example":25}}}}}}}}}}},"/api/user/files/get-pre-signed-url":{"post":{"operationId":"postapiuserfilesgetpresignedurl","summary":"Get pre-signed URL for user file upload","description":"Generates a pre-signed URL for uploading a file to S3. The file name and type are required. A unique file key will be generated automatically.","tags":["User"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["file_name","file_type"],"properties":{"file_name":{"type":"string","example":"document.pdf","description":"Name of the file to be uploaded."},"file_size":{"type":"integer","example":1024000,"nullable":true,"description":"Size of the file in bytes."},"file_type":{"type":"string","example":"pdf","description":"File type/extension (without the dot)."}}},"example":{}}}},"responses":{"200":{"description":"Pre-signed URL generated successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://s3.amazonaws.com/bucket/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for uploading the file to S3."},"readURL":{"type":"string","example":"https://s3.amazonaws.com/bucket/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for reading/downloading the file from S3."}}}}}},"400":{"description":"Missing file name or file type","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://s3.amazonaws.com/bucket/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for uploading the file to S3."},"readURL":{"type":"string","example":"https://s3.amazonaws.com/bucket/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for reading/downloading the file from S3."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://s3.amazonaws.com/bucket/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for uploading the file to S3."},"readURL":{"type":"string","example":"https://s3.amazonaws.com/bucket/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for reading/downloading the file from S3."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://s3.amazonaws.com/bucket/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for uploading the file to S3."},"readURL":{"type":"string","example":"https://s3.amazonaws.com/bucket/file-key?X-Amz-Algorithm=...","description":"Pre-signed URL for reading/downloading the file from S3."}}}}}}}}},"/api/user/mis-report":{"get":{"operationId":"getapiusermisreport","summary":"Get MIS report for the authenticated user","description":"Retrieves a paginated MIS report with email metrics aggregated by date. Automatically filters by the authenticated user's ID. Users can only see their own data.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"description":"Page number (1-indexed). Defaults to 1.","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","required":false,"description":"Number of rows per page (max 100). Defaults to 10.","schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"endDate","in":"query","required":false,"description":"End date in ISO 8601 format (YYYY-MM-DD). Defaults to end of day (23:59:59).","schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"startDate","in":"query","required":false,"description":"Start date in ISO 8601 format (YYYY-MM-DD). Defaults to start of day (00:00:00).","schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"campaignId","in":"query","required":false,"description":"Filter by campaign ID (only valid with emailSource 'campaign' or 'all').","schema":{"type":"string","format":"uuid"}},{"name":"emailSource","in":"query","required":false,"description":"Filter by email source: 'campaign' (campaign-based emails), 'smtp' (SMTP emails), 'api' (transactional/API emails), or 'all' (default).","schema":{"enum":["campaign","smtp","api","all"],"type":"string","default":"all"}}],"responses":{"200":{"description":"MIS report retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MISReportResponse"}}}},"400":{"description":"Bad request - invalid date format, invalid filter value, or invalid date range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MISReportResponse"}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MISReportResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MISReportResponse"}}}}}}},"/api/user/delivery-log-report":{"get":{"operationId":"getapiuserdeliverylogreport","summary":"Get delivery log report for the authenticated user","description":"Retrieves a paginated delivery log report for the authenticated user. Includes email, status, delivery time, and submission time.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"description":"Page number (1-indexed). Defaults to 1.","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","required":false,"description":"Number of rows per page (max 100). Defaults to 10.","schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"emailSource","in":"query","required":false,"description":"Filter by email source: 'campaign' (campaign-based emails), 'smtp' (SMTP emails), 'api' (transactional/API emails), or 'all' (default).","schema":{"enum":["campaign","smtp","api","all"],"type":"string","default":"all"}}],"responses":{"200":{"description":"Delivery log report retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryLogReportResponse"}}}},"400":{"description":"Bad request - invalid filter value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryLogReportResponse"}}}},"401":{"description":"Unauthorized (missing or invalid user access token, or user context missing)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryLogReportResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryLogReportResponse"}}}}}}},"/api/user/recharge-logs":{"get":{"operationId":"getapiuserrechargelogs","summary":"Get user recharge logs (paginated)","description":"Retrieves a paginated list of recharge logs for the authenticated user. Supports search and sort by created_at or credit_amount.","tags":["User"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"description":"Page number (1-based).","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","required":false,"description":"Number of items per page (max 100).","schema":{"type":"integer","default":10,"maximum":100,"minimum":1}},{"name":"search","in":"query","required":false,"description":"Search term (included for consistency with other APIs, but not very useful for self logs).","schema":{"type":"string"}},{"name":"sortBy","in":"query","required":false,"description":"Field to sort by. Defaults to created_at.","schema":{"enum":["created_at","credit_amount"],"type":"string"}},{"name":"sortOrder","in":"query","required":false,"description":"Sort order, ascending or descending. Defaults to desc.","schema":{"enum":["asc","desc"],"type":"string"}}],"responses":{"200":{"description":"User recharge logs retrieved successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"admin_id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time"},"credit_amount":{"type":"string","description":"Decimal string (e.g. '100.0000')"},"per_email_charge":{"type":"string","nullable":true,"description":"Decimal string (e.g. '0.0100')"}}}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of recharge logs."},"totalPages":{"type":"integer","description":"Total number of pages."}}}}}},"401":{"description":"Unauthorized (missing or invalid user access token)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"admin_id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time"},"credit_amount":{"type":"string","description":"Decimal string (e.g. '100.0000')"},"per_email_charge":{"type":"string","nullable":true,"description":"Decimal string (e.g. '0.0100')"}}}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of recharge logs."},"totalPages":{"type":"integer","description":"Total number of pages."}}}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"admin_id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time"},"credit_amount":{"type":"string","description":"Decimal string (e.g. '100.0000')"},"per_email_charge":{"type":"string","nullable":true,"description":"Decimal string (e.g. '0.0100')"}}}},"page":{"type":"integer","description":"Current page number."},"limit":{"type":"integer","description":"Number of items per page."},"total":{"type":"integer","description":"Total number of recharge logs."},"totalPages":{"type":"integer","description":"Total number of pages."}}}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"access token"}}}}