{"openapi":"3.0.0","info":{"title":"JetEmail API","version":"1.0.0","description":"API documentation for JetEmail's transactional email service."},"externalDocs":{"description":"Download OpenAPI Specification","url":"/openapi.json"},"components":{"securitySchemes":{"apiKeyAuth":{"type":"http","scheme":"bearer","description":"API key for account management endpoints. Use your api_ prefixed token."},"transactionalKeyAuth":{"type":"http","scheme":"bearer","description":"Transactional key for sending emails. Use your transactional_ prefixed token."}}},"security":[{"apiKeyAuth":[]}],"servers":[{"url":"https://api.jetemail.com","description":"Production"}],"paths":{"/email":{"post":{"tags":["Email"],"summary":"Send an email","security":[{"transactionalKeyAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":256},"description":"Opaque key (1–256 chars) that makes retries safe. A repeat with the same key and body replays the original response."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["from","to","subject"],"properties":{"from":{"type":"string","description":"Sender email address in format: \"Name <email@domain.com>\"","example":"John Doe <john@example.com>"},"to":{"oneOf":[{"type":"string","format":"email","description":"Single recipient email address","example":"user@example.com"},{"type":"array","items":{"type":"string","format":"email"},"maxItems":50,"description":"List of recipient email addresses"}],"description":"Recipient email address(es)"},"subject":{"type":"string","minLength":1,"description":"Email subject line"},"html":{"type":"string","description":"HTML content of the email. At least one of html or text is required. Can be used together with text to provide a plaintext alternative"},"text":{"type":"string","description":"Plaintext content of the email. At least one of html or text is required. When used with html, serves as the plaintext alternative"},"cc":{"oneOf":[{"type":"string","format":"email"},{"type":"array","items":{"type":"string","format":"email"},"maxItems":50}],"description":"CC recipient(s). Can be plain email or \"Name <email@domain.com>\" format"},"bcc":{"oneOf":[{"type":"string","format":"email"},{"type":"array","items":{"type":"string","format":"email"},"maxItems":50}],"description":"BCC recipient(s). Can be plain email or \"Name <email@domain.com>\" format"},"reply_to":{"oneOf":[{"type":"string","format":"email"},{"type":"array","items":{"type":"string","format":"email"},"maxItems":50}],"description":"Reply-to address(es). Can be plain email or \"Name <email@domain.com>\" format"},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom email headers"},"attachments":{"type":"array","items":{"type":"object","required":["filename","data"],"properties":{"filename":{"type":"string","description":"Name of the attachment file"},"data":{"type":"string","format":"base64","description":"Base64 encoded file content"}}},"description":"Email attachments (base64 encoded, max total size: 40MB)"},"eu":{"type":"boolean","description":"If true, restricts email delivery to EU region only.","example":false},"scheduledAt":{"oneOf":[{"type":"integer","description":"Unix seconds (UTC).","example":1762435200},{"type":"string","format":"date-time","description":"ISO 8601 / RFC 3339 with offset.","example":"2026-05-15T10:00:00Z"}],"description":"Future send time, up to 30 days out. Accepts unix seconds (e.g. 1762435200) or ISO 8601 (e.g. \"2026-05-15T10:00:00Z\" or \"2026-05-15T10:00:00-04:00\"). `scheduled_at` is also accepted as an alias."}}},"examples":{"Simple Text Email":{"value":{"from":"John Doe <john@example.com>","to":"recipient@example.com","subject":"Test Email","text":"Hello! This is a test email."}},"HTML Email with Plaintext Alternative":{"value":{"from":"John Doe <john@example.com>","to":"recipient@example.com","subject":"Test Email","html":"<h1>Hello!</h1><p>This is the HTML version.</p>","text":"Hello! This is the plaintext version."}},"Scheduled Email (ISO 8601)":{"value":{"from":"John Doe <john@example.com>","to":"recipient@example.com","subject":"Reminder","text":"This will arrive at the scheduled time.","scheduledAt":"2026-05-15T10:00:00Z"}},"Scheduled Email (Unix seconds)":{"value":{"from":"John Doe <john@example.com>","to":"recipient@example.com","subject":"Reminder","text":"This will arrive at the scheduled time.","scheduledAt":1762435200}}}}}},"responses":{"201":{"description":"Email queued successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Unique message ID","example":"19424fd2acd0004210"},"response":{"type":"string","description":"Queue confirmation message","example":"Message queued as 19424fd2acd0004210"}}}}}},"202":{"description":"Email scheduled for future delivery.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Scheduling uuid","example":"0cd0f31f-1234-4abc-8def-1234567890ab"},"response":{"type":"string","example":"Scheduled as 0cd0f31f-… for 1762435200"},"scheduled_at":{"type":"integer","description":"Unix seconds at which the message will send","example":1762435200}}}}}},"400":{"description":"Bad Request - Invalid input"},"401":{"description":"Unauthorized - Missing or invalid API key"},"409":{"description":"Idempotency conflict — key in flight (IDEMPOTENCY_IN_FLIGHT) or reused with a different body (IDEMPOTENCY_BODY_MISMATCH)."}}}},"/email-batch":{"post":{"tags":["Email"],"summary":"Send multiple emails in a batch","description":"Send up to 100 emails in a single batch request","security":[{"transactionalKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["emails"],"properties":{"emails":{"type":"array","items":{"type":"object","required":["from","to","subject"],"oneOf":[{"required":["html"]},{"required":["text"]}],"properties":{"from":{"type":"string","description":"Sender email address in format: \"Name <email@domain.com>\"","example":"John Doe <john@example.com>"},"to":{"oneOf":[{"type":"string","format":"email","description":"Single recipient email address","example":"user@example.com"},{"type":"array","items":{"type":"string","format":"email"},"maxItems":50,"description":"List of recipient email addresses"}]},"subject":{"type":"string","maxLength":998,"description":"Email subject line"},"html":{"type":"string","description":"HTML content of the email. At least one of html or text is required."},"text":{"type":"string","description":"Plain text content of the email. At least one of html or text is required."},"cc":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"},"maxItems":50}],"description":"CC recipient(s)"},"bcc":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"},"maxItems":50}],"description":"BCC recipient(s)"},"reply_to":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"},"maxItems":50}],"description":"Reply-to address(es)"},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom email headers"},"attachments":{"type":"array","items":{"type":"object","required":["filename","data"],"properties":{"filename":{"type":"string","maxLength":255,"description":"Name of the attachment file"},"data":{"type":"string","format":"base64","description":"Base64 encoded file content"}}},"description":"Email attachments (base64 encoded, max total size: 40MB)"},"eu":{"type":"boolean","description":"If true, restricts email delivery to EU region only.","example":false},"idempotency_key":{"type":"string","minLength":1,"maxLength":256,"description":"Per-email idempotency key. A repeat with the same key and body replays the original result."},"scheduledAt":{"oneOf":[{"type":"integer","description":"Unix seconds (UTC).","example":1762435200},{"type":"string","format":"date-time","description":"ISO 8601 / RFC 3339 with offset.","example":"2026-05-15T10:00:00Z"}],"description":"Future send time, up to 30 days out. Accepts unix seconds (e.g. 1762435200) or ISO 8601 (e.g. \"2026-05-15T10:00:00Z\" or \"2026-05-15T10:00:00-04:00\"). `scheduled_at` is also accepted as an alias."}}},"maxItems":100,"minItems":1}}},"examples":{"Simple Batch":{"value":{"emails":[{"from":"John Doe <john@example.com>","to":"recipient1@example.com","subject":"Test Email 1","text":"Hello! This is test email 1."},{"from":"John Doe <john@example.com>","to":"recipient2@example.com","subject":"Test Email 2","text":"Hello! This is test email 2."}]}},"Mixed Immediate and Scheduled":{"value":{"emails":[{"from":"John Doe <john@example.com>","to":"recipient1@example.com","subject":"Send now","text":"Hello! This sends immediately."},{"from":"John Doe <john@example.com>","to":"recipient2@example.com","subject":"Send later","text":"Hello! This sends at the scheduled time.","scheduledAt":"2026-05-15T10:00:00Z"}]}}}}}},"responses":{"207":{"description":"Batch processing results","content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"object","properties":{"total":{"type":"integer","description":"Total number of emails in batch","example":2},"successful":{"type":"integer","description":"Number of successfully sent emails","example":1},"failed":{"type":"integer","description":"Number of failed emails","example":1}}},"results":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["success"],"example":"success"},"id":{"type":"string","description":"Message ID, or scheduling uuid for scheduled items.","example":"19424fd2acd0004210"},"response":{"type":"string","description":"Success message","example":"Message queued as 19424fd2acd0004210"},"scheduled_at":{"type":"integer","description":"Unix seconds at which the message will send. Present only when scheduled.","example":1762435200}}},{"type":"object","properties":{"status":{"type":"string","enum":["error"],"example":"error"},"error":{"type":"string","description":"Error message","example":"Invalid email format"},"email":{"type":"object","description":"The original email request that failed"}}}]}}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Maximum batch size is 100 emails"}}}}}},"401":{"description":"Unauthorized - Missing or invalid API key"},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"No healthy email endpoints available"}}}}}}}}},"/outbound/smarthost":{"get":{"tags":["Outbound"],"summary":"Get SMTP users","description":"Retrieves a list of SMTP users","responses":{"200":{"description":"Successfully retrieved SMTP users","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"smarthosts":{"type":"array","items":{"type":"object","properties":{"username":{"type":"string","description":"SMTP username","example":"smtpuser"},"uuid":{"type":"string","description":"Unique identifier for the smarthost","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"status":{"type":"string","enum":["disabled","active","suspended","quota-locked","quota-unlocked"],"description":"Current status of the SMTP user","example":"active"},"allowAnyDomain":{"type":"integer","enum":[0,1],"description":"Whether the user can send from any domain (0=false, 1=true)","example":0},"allowAllDomains":{"type":"integer","enum":[0,1],"description":"Whether the user can send from all verified domains (0=false, 1=true)","example":0},"approvedDomains":{"type":"string","description":"JSON string containing array of approved domains","example":"[\"alloweddomain.com\"]"},"usage":{"type":"integer","description":"Current usage count","example":77},"quota":{"type":"integer","description":"Maximum allowed usage","example":1001},"ipRestrictions":{"type":"string","description":"JSON string containing array of allowed IP addresses","example":"[\"1.1.1.1\"]"},"created_date":{"type":"string","description":"Creation timestamp in milliseconds or seconds (with decimal)","example":"1724113774000"},"last_modified":{"type":"integer","description":"Last modification timestamp in seconds","example":1735937552}}}}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch SMTP users"}}}}}}}},"post":{"tags":["Outbound"],"summary":"Create new SMTP user","description":"Creates a new SMTP user for outbound email sending","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username"],"properties":{"username":{"type":"string","description":"SMTP username (will be sanitized to lowercase alphanumeric with hyphens)","example":"smtp-user1","minLength":1,"maxLength":64,"pattern":"^[a-z0-9-]+$"},"password":{"type":"string","description":"Optional password (will be generated if not provided)","example":"mySecurePassword123","minLength":8,"maxLength":72},"allowAnyDomain":{"type":"boolean","description":"Whether to allow sending from any domain (requires paid subscription). Cannot be enabled together with allowAllDomains.","default":false},"allowAllDomains":{"type":"boolean","description":"Whether to allow sending from all verified domains. Cannot be enabled together with allowAnyDomain.","default":false},"approvedDomains":{"type":"array","items":{"type":"string","pattern":"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?.)+[a-zA-Z]{2,}$"},"description":"List of approved domains for sending","default":[],"example":["example.com","mydomain.com"],"maxItems":50},"quota":{"type":"number","description":"Email sending quota","default":0,"example":1000,"minimum":0},"ipRestrictions":{"type":"array","items":{"type":"string","pattern":"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"},"description":"List of allowed IP addresses","default":[],"example":["192.168.1.1","10.0.0.1"],"maxItems":50}}}}}},"responses":{"200":{"description":"SMTP user created successfully. If no password was provided in the request, a generated password will be included in the response.","content":{"application/json":{"schema":{"type":"object","required":["success","message"],"properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"SMTP user created successfully"},"password":{"type":"string","description":"Only present if no password was provided in the request","example":"generated-secure-password"}}},"examples":{"With provided password":{"value":{"success":true,"message":"SMTP user created successfully"}},"With generated password":{"value":{"success":true,"message":"SMTP user created successfully","password":"generated-secure-password"}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"SMTP username is required"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Required information not found"}}}}}},"403":{"description":"Forbidden - Feature not available","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Allow Any Domain feature requires a paid subscription"}}}}}},"409":{"description":"Conflict - Username already exists","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"This SMTP username is already in use"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create SMTP user"}}}}}}}},"patch":{"tags":["Outbound"],"summary":"Update SMTP user","description":"Updates an existing SMTP user configuration","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["currentUsername"],"properties":{"currentUsername":{"type":"string","description":"Current SMTP username to update","example":"existing-user"},"newUsername":{"type":"string","description":"New SMTP username (will be sanitized to lowercase alphanumeric with hyphens)","example":"new-user-name","minLength":1,"maxLength":64,"pattern":"^[a-z0-9-]+$"},"password":{"type":"string","description":"New password","example":"newSecurePassword123","minLength":8,"maxLength":72},"allowAnyDomain":{"type":"boolean","description":"Whether to allow sending from any domain (requires paid subscription). Cannot be enabled together with allowAllDomains.","example":false},"allowAllDomains":{"type":"boolean","description":"Whether to allow sending from all verified domains. Cannot be enabled together with allowAnyDomain.","example":false},"approvedDomains":{"type":"array","items":{"type":"string","pattern":"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?.)+[a-zA-Z]{2,}$"},"description":"List of approved domains for sending","example":["example.com","mydomain.com"],"maxItems":253},"quota":{"type":"number","description":"Email sending quota","example":1000,"minimum":0},"ipRestrictions":{"type":"array","items":{"type":"string","pattern":"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"},"description":"List of allowed IP addresses","example":["192.168.1.1","10.0.0.1"],"maxItems":50},"status":{"type":"string","enum":["inactive","active","suspended","quota-locked","quota-unlocked"],"description":"Status of the SMTP user"}}},"examples":{"Update username":{"value":{"currentUsername":"old-user","newUsername":"new-user"}},"Update multiple fields":{"value":{"currentUsername":"existing-user","allowAnyDomain":true,"approvedDomains":["newdomain.com"],"quota":2000,"ipRestrictions":["192.168.1.100"]}},"Update status":{"value":{"currentUsername":"existing-user","status":"active"}}}}}},"responses":{"200":{"description":"SMTP user updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Smarthost updated successfully"}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"No valid updates provided"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Required information not found"}}}}}},"403":{"description":"Forbidden - Feature not available","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Allow Any Domain feature requires a paid subscription"}}}}}},"404":{"description":"Not Found - Smarthost not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Smarthost not found or access denied"}}}}}},"409":{"description":"Conflict - New username already exists","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"This SMTP username is already in use"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to update smarthost"}}}}}}}},"delete":{"tags":["Outbound"],"summary":"Delete SMTP user","description":"Deletes an SMTP user","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username"],"properties":{"username":{"type":"string","description":"SMTP username to delete","example":"smtp-user1"}}}}}},"responses":{"200":{"description":"SMTP user deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Smarthost deleted successfully"}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Username is required"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Required information not found"}}}}}},"404":{"description":"Not Found - Smarthost not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Smarthost not found or access denied"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to delete smarthost"}}}}}}}}},"/outbound/transactional-keys":{"get":{"tags":["Outbound"],"summary":"Get transactional API keys","description":"Retrieves a list of transactional API keys","responses":{"200":{"description":"Successfully retrieved transactional keys","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"transactionalKeys":{"type":"array","items":{"type":"object","properties":{"api_token":{"type":"string","description":"API key","example":"transactional_1111111"},"uuid":{"type":"string","description":"Unique identifier for the transactional key","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"name":{"type":"string","description":"Name for the transactional key","example":"Production API Key"},"status":{"type":"string","enum":["disabled","active","suspended","quota-locked","quota-unlocked"],"description":"Current status of the API key","example":"active"},"allowAllDomains":{"type":"integer","enum":[0,1],"description":"Whether the key can send from all verified domains (0=false, 1=true)","example":0},"approvedDomains":{"type":"string","description":"JSON string containing array of approved domains","example":"[\"alloweddomain.com\"]"},"usage":{"type":"integer","description":"Current usage count","example":77},"quota":{"type":"integer","description":"Maximum allowed usage","example":1001},"ipRestrictions":{"type":"string","description":"JSON string containing array of allowed IP addresses","example":"[\"1.1.1.1\"]"},"created_date":{"type":"string","description":"Creation timestamp","example":"1724113774000"},"last_modified":{"type":"integer","description":"Last modification timestamp","example":1735937552}}}}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch SMTP users"}}}}}}}},"post":{"tags":["Outbound"],"summary":"Create new transactional API key","description":"Creates a new transactional API key for sending emails via the API","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Name for the transactional key","example":"Production API Key","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9-_\\s]+$"},"allowAllDomains":{"type":"boolean","description":"Whether to allow sending from all verified domains","default":false},"approvedDomains":{"type":"array","items":{"type":"string","pattern":"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?.)+[a-zA-Z]{2,}$"},"description":"List of approved domains for sending","default":[],"example":["example.com","mydomain.com"],"maxItems":253},"quota":{"type":"integer","description":"Email sending quota (0 for unlimited)","default":0,"example":1000,"minimum":0,"maximum":1000000},"ipRestrictions":{"type":"array","items":{"type":"string","pattern":"^(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:/(?:3[0-2]|[12]?[0-9]))?)|(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,7}:(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|:(?::[0-9a-fA-F]{1,4}){1,7}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|::(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?)$"},"description":"List of allowed IP addresses/CIDR ranges (IPv4 and IPv6)","default":[],"example":["192.168.1.1","10.0.0.0/24","2001:db8::1","2001:db8::/32"],"maxItems":50}}},"examples":{"Basic Key":{"value":{"name":"Development API Key"}},"Full Configuration":{"value":{"name":"Production API Key","allowAllDomains":true,"approvedDomains":["example.com"],"quota":10000,"ipRestrictions":["192.168.1.1","10.0.0.0/24"]}}}}}},"responses":{"200":{"description":"Transactional key created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Transactional key created successfully"},"api_token":{"type":"string","description":"The generated API token","example":"transactional_a1b2c3d4"}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Name is required and must be a string"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Required information not found"}}}}}},"403":{"description":"Forbidden - Limit reached","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Free accounts are limited to 50 transactional keys"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create transactional key"}}}}}}}},"patch":{"tags":["Outbound"],"summary":"Update transactional API key","description":"Updates an existing transactional API key configuration or changes the status","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["api_token"],"properties":{"api_token":{"type":"string","description":"The API token to update","example":"transactional_a1b2c3d4"},"status":{"type":"integer","enum":[0,1],"description":"Toggle key status (0 = disabled, 1 = enabled). If provided, other update fields will be ignored.","example":1},"name":{"type":"string","description":"New name for the transactional key","example":"Updated API Key","minLength":1,"maxLength":64,"pattern":"^[a-zA-Z0-9-_\\s]+$"},"allowAllDomains":{"type":"boolean","description":"Whether to allow sending from all verified domains","example":false},"approvedDomains":{"type":"array","items":{"type":"string","pattern":"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?.)+[a-zA-Z]{2,}$"},"description":"List of approved domains for sending","example":["example.com","mydomain.com"],"maxItems":253},"quota":{"type":"integer","description":"Email sending quota (0 for unlimited)","example":1000,"minimum":0,"maximum":1000000},"ipRestrictions":{"type":"array","items":{"type":"string","pattern":"^(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:/(?:3[0-2]|[12]?[0-9]))?)|(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,7}:(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|:(?::[0-9a-fA-F]{1,4}){1,7}(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?|::(?:/(?:12[0-8]|1[01][0-9]|[1-9]?[0-9]))?)$"},"description":"List of allowed IP addresses/CIDR ranges","example":["192.168.1.1","10.0.0.0/24"],"maxItems":50}}},"examples":{"Toggle Disable":{"value":{"api_token":"transactional_a1b2c3d4","status":0},"summary":"Disable a key"},"Toggle Enable":{"value":{"api_token":"transactional_a1b2c3d4","status":1},"summary":"Enable a key"},"Update Name":{"value":{"api_token":"transactional_a1b2c3d4","name":"New API Key Name"}},"Update Multiple Fields":{"value":{"api_token":"transactional_a1b2c3d4","name":"Production API","allowAllDomains":true,"approvedDomains":["newdomain.com"],"quota":5000,"ipRestrictions":["192.168.1.100","10.0.0.0/24"]}}}}}},"responses":{"200":{"description":"Transactional key updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Transactional key updated successfully"}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid name format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Required information not found"}}}}}},"404":{"description":"Not Found - Transactional key not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Transactional key not found or unauthorized"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to update transactional key"}}}}}}}},"delete":{"tags":["Outbound"],"summary":"Delete transactional API key","description":"Deletes a transactional API key","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["api_token"],"properties":{"api_token":{"type":"string","description":"The API token to delete","example":"transactional_a1b2c3d4"}}}}}},"responses":{"200":{"description":"Transactional key deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Transactional key deleted successfully"}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"API token is required"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Required information not found"}}}}}},"404":{"description":"Not Found - Transactional key not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Transactional key not found or access denied"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to delete transactional key"}}}}}}}}},"/outbound/transactional-keys/rotate":{"post":{"tags":["Outbound"],"summary":"Rotate transactional API key","description":"Generates a new API token for an existing transactional key. The old token is immediately invalidated and a new one is returned. All other configuration (name, approved domains, quota, IP restrictions) remains unchanged.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["api_token"],"properties":{"api_token":{"type":"string","description":"The current API token to rotate","example":"transactional_a1b2c3d4"}}}}}},"responses":{"200":{"description":"Transactional key rotated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Transactional key rotated successfully"},"api_token":{"type":"string","description":"The new API token","example":"transactional_e5f6a7b8"}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"api_token is required"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Required information not found"}}}}}},"403":{"description":"Forbidden - Key cannot be rotated in its current state","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Cannot rotate a disabled transactional key. Enable it first."}}}}}},"404":{"description":"Not Found - Transactional key not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Transactional key not found or access denied"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to rotate transactional key"}}}}}}}}},"/outbound/logs":{"get":{"tags":["Outbound"],"summary":"Get outbound email logs","description":"Retrieves logs of outbound email activity with comprehensive filtering options","parameters":[{"name":"limit","in":"query","description":"Number of records to return (1-100)","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"page","in":"query","description":"Page number for pagination (starts from 1)","schema":{"type":"integer","minimum":1,"default":1}},{"name":"offset","in":"query","description":"Number of records to skip (alternative to page)","schema":{"type":"integer","minimum":0,"default":0}},{"name":"sort_by","in":"query","description":"Field to sort by","schema":{"type":"string","default":"date","maxLength":50}},{"name":"sort_order","in":"query","description":"Sort order","schema":{"type":"string","enum":["ASC","DESC"],"default":"DESC"}},{"name":"id","in":"query","description":"Filter by record ID","schema":{"type":"string","maxLength":100}},{"name":"uid","in":"query","description":"Filter by unique identifier","schema":{"type":"string","pattern":"^[A-Za-z0-9-_]{1,100}$"}},{"name":"action","in":"query","description":"Filter by email action status","schema":{"type":"string","enum":["ACCEPTED","REJECTED","BOUNCED_HARD","BOUNCED_SOFT","DEFERRED","SPAM","VIRUS","QUEUED"]}},{"name":"zone","in":"query","description":"Filter by zone","schema":{"type":"string","maxLength":50}},{"name":"message_id","in":"query","description":"Filter by message ID","schema":{"type":"string","maxLength":100}},{"name":"from_address","in":"query","description":"Filter by sender email address","schema":{"type":"string","format":"email"}},{"name":"to_address","in":"query","description":"Filter by recipient email address","schema":{"type":"string","format":"email"}},{"name":"mx","in":"query","description":"Filter by MX server","schema":{"type":"string","maxLength":100}},{"name":"host","in":"query","description":"Filter by host server","schema":{"type":"string","maxLength":100}},{"name":"ip","in":"query","description":"Filter by IP address","schema":{"type":"string","pattern":"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"}},{"name":"response","in":"query","description":"Filter by server response","schema":{"type":"string","maxLength":500}},{"name":"size","in":"query","description":"Filter by message size","schema":{"type":"integer","minimum":0}},{"name":"timer","in":"query","description":"Filter by timer value","schema":{"type":"string","maxLength":20}},{"name":"start","in":"query","description":"Filter by start date (ISO format)","schema":{"type":"string","format":"date-time"}},{"name":"user","in":"query","description":"Filter by username","schema":{"type":"string","format":"email"}},{"name":"protocol","in":"query","description":"Filter by protocol","schema":{"type":"string","enum":["smtp","http","https"]}},{"name":"src","in":"query","description":"Filter by source","schema":{"type":"string","maxLength":50}},{"name":"subject","in":"query","description":"Filter by email subject","schema":{"type":"string","maxLength":500}},{"name":"body","in":"query","description":"Filter by email body content","schema":{"type":"string","maxLength":1000}},{"name":"md5","in":"query","description":"Filter by MD5 hash","schema":{"type":"string","pattern":"^[a-fA-F0-9]{32}$"}},{"name":"interface","in":"query","description":"Filter by interface","schema":{"type":"string","maxLength":50}},{"name":"originhost","in":"query","description":"Filter by origin host","schema":{"type":"string","maxLength":100}},{"name":"transhost","in":"query","description":"Filter by transport host","schema":{"type":"string","maxLength":100}},{"name":"transtype","in":"query","description":"Filter by transport type","schema":{"type":"string","enum":["smtp","http","api"]}},{"name":"headerFrom","in":"query","description":"Filter by header From field","schema":{"type":"string","format":"email"}},{"name":"from_address","in":"query","description":"Filter by from address","schema":{"type":"string","format":"email"}},{"name":"to_address","in":"query","description":"Filter by to address","schema":{"type":"string","format":"email"}},{"name":"date_from","in":"query","description":"Filter by start date (Unix timestamp)","schema":{"type":"integer","minimum":0}},{"name":"date_to","in":"query","description":"Filter by end date (Unix timestamp)","schema":{"type":"integer","minimum":0}},{"name":"from","in":"query","description":"Filter by start date (YYYY-MM-DD or ISO format)","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Filter by end date (YYYY-MM-DD or ISO format)","schema":{"type":"string","format":"date"}},{"name":"rule_id","in":"query","description":"Filter by rule ID","schema":{"type":"string","maxLength":100}},{"name":"search","in":"query","description":"General search term (searches across email fields)","schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"Successfully retrieved logs","content":{"application/json":{"schema":{"oneOf":[{"type":"array","items":{"type":"object","properties":{"uid":{"type":"string","description":"Unique identifier","example":"abc123"},"action":{"type":"string","enum":["ACCEPTED","REJECTED","BOUNCED_HARD","BOUNCED_SOFT","DEFERRED","SPAM","VIRUS","QUEUED"],"description":"Email action status"},"message_id":{"type":"string","description":"Email message ID"},"sender":{"type":"string","description":"Sender information"},"receiver":{"type":"string","description":"Receiver information"},"mx":{"type":"string","description":"MX server"},"host":{"type":"string","description":"Host server"},"ip":{"type":"string","description":"IP address"},"response":{"type":"string","description":"Server response"},"size":{"type":"integer","description":"Message size"},"timer":{"type":"string","description":"Timer value"},"start":{"type":"string","description":"Start time"},"user":{"type":"string","description":"Username"},"protocol":{"type":"string","description":"Protocol used"},"src":{"type":"string","description":"Source identifier"},"subject":{"type":"string","description":"Email subject"},"body":{"type":"string","description":"Email body content"},"originhost":{"type":"string","description":"Origin host"},"transhost":{"type":"string","description":"Transport host"},"transtype":{"type":"string","description":"Transport type"},"headerFrom":{"type":"string","description":"From header value"},"from_address":{"type":"string","description":"Sender email address"},"to_address":{"type":"string","description":"Recipient email address"},"date":{"type":"string","description":"Transaction date"},"rule_id":{"type":"string","description":"Applied rule identifier"}}}},{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"uid":{"type":"string","description":"Unique identifier","example":"abc123"},"action":{"type":"string","enum":["ACCEPTED","REJECTED","BOUNCED_HARD","BOUNCED_SOFT","DEFERRED","SPAM","VIRUS","QUEUED"],"description":"Email action status"},"message_id":{"type":"string","description":"Email message ID"},"sender":{"type":"string","description":"Sender information"},"receiver":{"type":"string","description":"Receiver information"},"mx":{"type":"string","description":"MX server"},"host":{"type":"string","description":"Host server"},"ip":{"type":"string","description":"IP address"},"response":{"type":"string","description":"Server response"},"size":{"type":"integer","description":"Message size"},"timer":{"type":"string","description":"Timer value"},"start":{"type":"string","description":"Start time"},"user":{"type":"string","description":"Username"},"protocol":{"type":"string","description":"Protocol used"},"src":{"type":"string","description":"Source identifier"},"subject":{"type":"string","description":"Email subject"},"body":{"type":"string","description":"Email body content"},"originhost":{"type":"string","description":"Origin host"},"transhost":{"type":"string","description":"Transport host"},"transtype":{"type":"string","description":"Transport type"},"headerFrom":{"type":"string","description":"From header value"},"from_address":{"type":"string","description":"Sender email address"},"to_address":{"type":"string","description":"Recipient email address"},"date":{"type":"string","description":"Transaction date"},"rule_id":{"type":"string","description":"Applied rule identifier"}}}}}}]}}}},"400":{"description":"Bad Request - Invalid parameters","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Invalid parameter format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User authentication, log location, or db_uuid not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch outbound logs"},"details":{"type":"string","description":"Additional error details"}}}}}}}}},"/outbound/logs/uid":{"get":{"tags":["Outbound"],"summary":"Get outbound email logs by UID","description":"Retrieves detailed log information for a specific message UID. This will only return data about whether the email was delivered.","parameters":[{"name":"uid","in":"query","required":true,"description":"Unique identifier of the message","schema":{"type":"string","pattern":"^[A-Za-z0-9-_]{1,50}$"}}],"responses":{"200":{"description":"Successfully retrieved log details","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"uid":{"type":"string","description":"Unique identifier","example":"abc123"},"action":{"type":"string","description":"Action taken on the message","example":"ACCEPTED"},"message_id":{"type":"string","description":"Email message ID","example":"<abc123@server.local>"},"response":{"type":"string","description":"Server response","example":"250 2.0.0 Ok: queued"},"user":{"type":"string","description":"Username","example":"smtp_user1"},"from_address":{"type":"string","description":"Sender email address","example":"sender@example.com"},"to_address":{"type":"string","description":"Recipient email address","example":"recipient@example.com"},"date":{"type":"string","description":"Transaction date","example":"2024-03-20T15:30:00Z"},"mx":{"type":"string","description":"MX server used","example":"mx.recipient.com"},"host":{"type":"string","description":"Host server name","example":"outbound1.server.local"},"outbound_ip":{"type":"string","description":"IP address used for sending","example":"192.168.1.1"}}}}}}}}},"400":{"description":"Bad Request - Invalid UID format","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Invalid or missing UID"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Required information not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Failed to fetch logs"}}}}}}}}},"/outbound/domains":{"get":{"tags":["Outbound"],"summary":"Get domains","description":"Retrieves a list of domains associated with the user or organization","responses":{"200":{"description":"Successfully retrieved domains","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"domains":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","description":"Unique identifier for the domain","example":"550e8400-e29b-41d4-a716-446655440000"},"domain":{"type":"string","description":"Domain name","example":"example.com"},"status":{"type":"string","enum":["inactive","active","disabled","unknown"],"description":"Current status of the domain","example":"active"},"created_date":{"type":"integer","description":"Creation timestamp in seconds","example":1735689600},"last_modified":{"type":"integer","description":"Last modification timestamp in seconds","example":1735689600},"dns":{"type":"object","properties":{"dkim":{"type":"object","properties":{"host":{"type":"string","description":"DKIM record hostname","example":"jetemail._domainkey.example.com"},"value":{"type":"string","description":"DKIM record value","example":"dkim.jetsmtp.net"},"verified":{"type":"boolean","description":"Whether the DKIM record is verified","example":true}}},"spf":{"type":"object","properties":{"host":{"type":"string","description":"SPF CNAME record hostname","example":"em12345.example.com"},"value":{"type":"string","description":"SPF CNAME record target","example":"return.jetsmtp.net"},"type":{"type":"string","description":"DNS record type","example":"CNAME"},"verified":{"type":"boolean","description":"Whether the SPF record is verified","example":true}}},"dmarc":{"type":"object","properties":{"host":{"type":"string","description":"DMARC record hostname","example":"_dmarc.example.com"},"value":{"type":"string","description":"DMARC record value","example":"v=DMARC1; p=none"},"verified":{"type":"boolean","description":"Whether the DMARC record is verified","example":true}}},"tracking":{"type":"object","description":"Optional tracking CNAME. Present only when tracking_domain is set on the domain.","properties":{"host":{"type":"string","example":"links.example.com"},"value":{"type":"string","example":"link-us.jete.ml"},"type":{"type":"string","example":"CNAME"},"required":{"type":"boolean","example":false},"verified":{"type":"boolean","example":true}}}}}}}}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch domains"}}}}}}}},"post":{"tags":["Outbound"],"summary":"Add new domain","description":"Adds a new domain for sending email","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string","description":"Domain name to add","example":"example.com","pattern":"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?.)+[a-zA-Z]{2,}$"}}}}}},"responses":{"200":{"description":"Domain added successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Domain added successfully"},"domain":{"type":"string","description":"The added domain name","example":"example.com"},"uuid":{"type":"string","description":"Unique identifier for the domain","example":"550e8400-e29b-41d4-a716-446655440000"},"status":{"type":"integer","description":"Domain status code","example":0},"created_date":{"type":"integer","description":"Creation timestamp","example":1735689600},"dns":{"type":"object","properties":{"dkim":{"type":"object","properties":{"host":{"type":"string","description":"DKIM record hostname","example":"jetemail._domainkey.example.com"},"value":{"type":"string","description":"DKIM record value","example":"dkim.jetsmtp.net"},"verified":{"type":"boolean","description":"Whether the DKIM record is verified","example":false}}},"spf":{"type":"object","properties":{"host":{"type":"string","description":"SPF CNAME record hostname","example":"em12345.example.com"},"value":{"type":"string","description":"SPF CNAME record target","example":"return.jetsmtp.net"},"type":{"type":"string","description":"DNS record type","example":"CNAME"},"verified":{"type":"boolean","description":"Whether the SPF record is verified","example":false}}},"dmarc":{"type":"object","properties":{"host":{"type":"string","description":"DMARC record hostname","example":"_dmarc.example.com"},"value":{"type":"string","description":"DMARC record value","example":"v=DMARC1; p=none"},"verified":{"type":"boolean","description":"Whether the DMARC record is verified","example":false}}}}}}}}}},"400":{"description":"Bad Request - Invalid domain format","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid domain format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"409":{"description":"Conflict - Domain already exists","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain already exists"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to add domain"}}}}}}}},"delete":{"tags":["Outbound"],"summary":"Delete domain","description":"Marks a domain as deleted","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["uuid"],"properties":{"uuid":{"type":"string","description":"UUID of the domain to delete","example":"b814c25d-b18c-4044-ae31-49e22ce908b5"}}}}}},"responses":{"200":{"description":"Domain deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Domain deleted successfully"}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain UUID is required"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Not Found - Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found or already deleted"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to delete domain"}}}}}}}}},"/outbound/domains/{uuid}":{"get":{"tags":["Outbound"],"summary":"Get a domain","description":"Returns a single outbound domain by UUID.","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$","example":"b814c25d-b18c-4044-ae31-49e22ce908b5"}}],"responses":{"200":{"description":"Domain found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"domain":{"type":"object","properties":{"uuid":{"type":"string","example":"b814c25d-b18c-4044-ae31-49e22ce908b5"},"domain":{"type":"string","example":"example.com"},"status":{"type":"string","enum":["inactive","active","disabled","unknown"],"example":"active"},"created_date":{"type":"string","example":"1735689600.0"},"last_modified":{"type":"string","example":"1735689600.0"},"dns":{"type":"object","properties":{"dkim":{"type":"object","properties":{"host":{"type":"string","example":"jetemail._domainkey.example.com"},"value":{"type":"string","example":"dkim.jetsmtp.net"},"verified":{"type":"boolean","example":true}}},"spf":{"type":"object","properties":{"host":{"type":"string","example":"em12345.example.com"},"value":{"type":"string","example":"return.jetsmtp.net"},"type":{"type":"string","example":"CNAME"},"verified":{"type":"boolean","example":true}}},"dmarc":{"type":"object","properties":{"host":{"type":"string","example":"_dmarc.example.com"},"value":{"type":"string","example":"v=DMARC1; p=none"},"verified":{"type":"boolean","example":true}}},"tracking":{"type":"object","description":"Optional tracking CNAME. Present only when tracking_domain is set on the domain.","properties":{"host":{"type":"string","example":"links.example.com"},"value":{"type":"string","example":"link-us.jete.ml"},"type":{"type":"string","example":"CNAME"},"required":{"type":"boolean","example":false},"verified":{"type":"boolean","example":false}}}}}}}}}}}},"400":{"description":"Invalid UUID format","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid UUID format"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch domain"}}}}}}}}},"/outbound/domains/{uuid}/check":{"post":{"tags":["Outbound"],"summary":"Check domain DNS records","description":"Verifies the DNS records for a domain","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the domain to check","schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$","example":"b814c25d-b18c-4044-ae31-49e22ce908b5"}}],"responses":{"200":{"description":"DNS check completed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"DNS check completed"}}}}}},"400":{"description":"Bad Request - Invalid UUID format","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid UUID format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Not Found - Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found or access denied"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to check domain DNS"}}}}}}}}},"/outbound/domains/{uuid}/settings":{"get":{"tags":["Outbound"],"summary":"Get domain settings","description":"Retrieves email settings for a specific domain including BCC emails, open tracking, and click tracking","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the domain to get settings for","schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$","example":"b814c25d-b18c-4044-ae31-49e22ce908b5"}}],"responses":{"200":{"description":"Domain settings retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"settings":{"type":"object","properties":{"uuid":{"type":"string","description":"Domain UUID","example":"b814c25d-b18c-4044-ae31-49e22ce908b5"},"domain":{"type":"string","description":"Domain name","example":"example.com"},"bccEmails":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"BCC email address"},"status":{"type":"integer","enum":[0,1],"description":"Verification status (0 = pending verification, 1 = verified)"}},"required":["email","status"]},"description":"Array of BCC email addresses with verification status","example":[{"email":"admin@example.com","status":1},{"email":"pending@example.com","status":0}]},"openTracking":{"type":"boolean","description":"Whether open tracking is enabled","example":true},"clickTracking":{"type":"boolean","description":"Whether click tracking is enabled","example":false},"tracking_domain":{"type":"string","nullable":true,"example":"links.example.com"},"tracking_verified":{"type":"boolean","example":false}}}}}}}},"400":{"description":"Bad Request - Invalid UUID format","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid UUID format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Not Found - Domain not found or access denied","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found or access denied"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to retrieve domain settings"}}}}}}}},"post":{"tags":["Outbound"],"summary":"Update domain settings","description":"Updates email settings for a specific domain including BCC emails, open tracking, and click tracking","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the domain to update settings for","schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$","example":"b814c25d-b18c-4044-ae31-49e22ce908b5"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"bccEmails":{"type":"array","items":{"type":"string","format":"email"},"description":"Array of BCC email addresses (maximum 5). New emails will require verification.","example":["admin@example.com","backup@example.com"],"maxItems":5,"nullable":true},"openTracking":{"type":"boolean","description":"Enable or disable open tracking for emails sent from this domain","example":true},"clickTracking":{"type":"boolean","description":"Enable or disable click tracking for emails sent from this domain","example":false},"tracking_domain":{"type":"string","nullable":true,"description":"Fully qualified hostname to CNAME to link-{logLocation}.jete.ml for click/open tracking. Pass null or an empty string to clear.","example":"links.example.com"}}}}}},"responses":{"200":{"description":"Domain settings updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Domain settings updated successfully"},"bccEmails":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"BCC email address"},"status":{"type":"integer","enum":[0,1],"description":"Verification status (0 = pending verification, 1 = verified)"}},"required":["email","status"]},"description":"Updated BCC emails with verification status (only present when bccEmails were updated)","example":[{"email":"admin@example.com","status":1},{"email":"new@example.com","status":0}]}}}}}},"400":{"description":"Bad Request - Invalid input or UUID format","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid UUID format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Not Found - Domain not found or access denied","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found or access denied"}}}}}},"429":{"description":"Too Many Requests - Too many verification attempts","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Too many verification attempts for email@example.com. Please try again later."}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to update domain settings"}}}}}}}}},"/inbound/domains":{"get":{"tags":["Inbound"],"summary":"Get inbound domains","description":"Retrieves a list of inbound domains","responses":{"200":{"description":"Successfully retrieved domains","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"result":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","description":"Unique identifier for the domain","example":"550e8400-e29b-41d4-a716-446655440000"},"domain":{"type":"string","description":"Domain name","example":"example.com"},"delivery_type":{"type":"string","enum":["smtp","webhook","forward"],"description":"How emails are delivered for this domain","example":"smtp"},"status":{"type":"integer","enum":[0,1],"description":"Domain status (0 = inactive, 1 = active)","example":1},"last_modified":{"type":"integer","description":"Last modification timestamp in seconds","example":1735937552},"created_at":{"type":"integer","description":"Creation timestamp in seconds","example":1735937552}}}}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"No domains found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"No domains found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch domains"}}}}}}}},"post":{"tags":["Inbound"],"summary":"Add new inbound domain","description":"Adds a new inbound domain with SMTP, webhook, or forward delivery. For forward delivery, use POST /inbound/domains/{uuid}/forward-rules to register routing rules after the domain is created and DNS is verified. Mode-specific fields are strictly enforced: smtp_servers is only allowed for delivery_type=smtp, the webhook_* fields are only allowed for delivery_type=webhook, and delivery_type=forward accepts neither. Sending fields from the wrong mode returns 400.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain","delivery_type"],"properties":{"domain":{"type":"string","description":"Primary domain name to add (e.g., example.com, not mail.example.com)","example":"example.com","pattern":"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?.)+[a-zA-Z]{2,}$"},"delivery_type":{"type":"string","enum":["smtp","webhook","forward"],"description":"How emails should be delivered for this domain. For \"forward\", inbound mail is forwarded to per-recipient destinations defined via POST /inbound/domains/{uuid}/forward-rules."},"smtp_servers":{"type":"array","description":"Only for delivery_type=smtp (required). Rejected with 400 if sent with webhook or forward.","items":{"oneOf":[{"type":"string","description":"Server URL","example":"mail.example.com:25"},{"type":"object","properties":{"url":{"type":"string","description":"Server URL","example":"mail.example.com:25"},"priority":{"type":"integer","description":"Server priority (lower = higher priority)","example":1},"tls_enabled":{"type":"boolean","description":"Enable TLS","default":false},"timeout":{"type":"integer","description":"Timeout in milliseconds","default":30000}},"required":["url"]}]}},"webhook_url":{"type":"string","format":"uri","description":"Only for delivery_type=webhook (required). Webhook URL to receive emails. Rejected with 400 if sent with smtp or forward.","example":"https://example.com/webhook/inbound"},"webhook_method":{"type":"string","enum":["POST","PUT"],"default":"POST","description":"Only for delivery_type=webhook. HTTP method for webhook. Rejected with 400 if sent with smtp or forward."},"webhook_headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Only for delivery_type=webhook. Custom headers to send with webhook requests. Rejected with 400 if sent with smtp or forward."},"webhook_timeout":{"type":"integer","default":30000,"description":"Only for delivery_type=webhook. Webhook timeout in milliseconds. Rejected with 400 if sent with smtp or forward."},"webhook_retry_count":{"type":"integer","default":3,"description":"Only for delivery_type=webhook. Number of retry attempts for failed webhook calls. Rejected with 400 if sent with smtp or forward."},"webhook_auth_header":{"type":"string","description":"Only for delivery_type=webhook. Authorization header value for webhook. Rejected with 400 if sent with smtp or forward."}}},"examples":{"SMTP Delivery":{"value":{"domain":"example.com","delivery_type":"smtp","smtp_servers":[{"url":"mail.example.com:25","priority":1,"tls_enabled":true}]}},"Webhook Delivery":{"value":{"domain":"example.com","delivery_type":"webhook","webhook_url":"https://example.com/webhook/inbound"}},"Forwarding Delivery":{"value":{"domain":"example.com","delivery_type":"forward"}}}}}},"responses":{"200":{"description":"Domain added successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"result":{"type":"object","properties":{"domain":{"type":"string","example":"example.com"},"delivery_type":{"type":"string","enum":["smtp","webhook","forward"],"example":"smtp"},"status":{"type":"string","example":"active"},"uuid":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"webhook_secret":{"type":"string","description":"Only present for webhook delivery_type. Secret for HMAC validation of webhook payloads.","example":"whsec_..."},"forward_mx_verified":{"type":"integer","enum":[0,1],"description":"Only present for forward delivery_type. DNS verification flag for the customer's MX record. Starts at 0; flipped to 1 by an external verifier once the customer publishes the required record. Inbound mail is rejected with 550 until all four forward_*_verified flags are 1.","example":0},"forward_dkim_verified":{"type":"integer","enum":[0,1],"description":"Only present for forward delivery_type. DNS verification flag for the customer's DKIM CNAME.","example":0},"forward_spf_verified":{"type":"integer","enum":[0,1],"description":"Only present for forward delivery_type. DNS verification flag for the customer's SPF record.","example":0},"forward_dmarc_verified":{"type":"integer","enum":[0,1],"description":"Only present for forward delivery_type. DNS verification flag for the customer's DMARC record.","example":0}}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid domain format"}}},"examples":{"Invalid domain format":{"value":{"success":false,"error":"Invalid primary domain format. Please provide a primary domain (e.g., example.com) rather than a subdomain (e.g., mail.example.com)."}},"Wrong fields for delivery_type=forward":{"summary":"smtp_servers or webhook_* sent with delivery_type=forward","value":{"success":false,"error":"Fields not allowed for delivery_type=forward: smtp_servers, webhook_url"}},"Wrong fields for delivery_type=smtp":{"summary":"webhook_* sent with delivery_type=smtp","value":{"success":false,"error":"Fields not allowed for delivery_type=smtp: webhook_url"}},"Wrong fields for delivery_type=webhook":{"summary":"smtp_servers sent with delivery_type=webhook","value":{"success":false,"error":"Fields not allowed for delivery_type=webhook: smtp_servers"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"403":{"description":"Quota exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain quota exceeded"},"quota":{"type":"number","example":1},"current":{"type":"number","example":1}}}}}},"409":{"description":"Domain already exists","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"This domain is already configured. Please use a different domain."}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create domain"}}}}}}}},"delete":{"tags":["Inbound"],"summary":"Delete inbound domain","description":"Deletes an inbound domain configuration","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["uuid"],"properties":{"uuid":{"type":"string","description":"UUID of the domain to delete","example":"550e8400-e29b-41d4-a716-446655440000","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}}}}},"responses":{"200":{"description":"Domain deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Domain deleted successfully"}}}}}},"400":{"description":"Invalid UUID format","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid UUID format"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found or already deleted"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to delete domain"}}}}}}}}},"/inbound/domains/{uuid}/check":{"post":{"tags":["Inbound"],"summary":"Run a DNS check for an inbound forwarding domain","description":"Runs a DNS check against the domain.","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the inbound forwarding domain","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}],"responses":{"200":{"description":"DNS check completed.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"DNS check completed"}}}}}},"400":{"description":"Invalid UUID, or domain is not delivery_type=forward","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"DNS check is only available for domains with delivery_type=forward"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Domain not found or access denied","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found or access denied"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to check domain DNS"}}}}}}}}},"/inbound/domains/{uuid}/forward-rules":{"get":{"tags":["Inbound"],"summary":"List forwarding rules for a domain","description":"Returns every active and inactive (but not deleted) forwarding rule for the specified domain. Only valid for domains with delivery_type=forward.","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the domain","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}],"responses":{"200":{"description":"Rules listed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"result":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","example":"7c1f7c14-1234-4abc-8def-0123456789ab"},"localpart":{"type":"string","description":"Address prefix to match. The literal \"*\" is the catch-all sentinel. Plus-addressing is handled at match time.","example":"support"},"destination":{"type":"string","format":"email","description":"Bare email address that becomes the outbound RCPT TO.","example":"team@theirinbox.com"},"active":{"type":"integer","enum":[0,1],"description":"Inactive rules are ignored at RCPT TO. Use this for soft-disable.","example":1},"verified":{"type":"integer","enum":[0,1],"description":"Set to 1 once the destination address owner has clicked the verification link. Until 1, inbound-edge will not deliver mail to this rule.","example":1},"last_modified":{"type":"integer","example":1735937552},"created_at":{"type":"integer","example":1735937552}}}}}}}}},"400":{"description":"Invalid UUID, or domain is not delivery_type=forward","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forwarding rules apply only to domains with delivery_type=forward"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to list forwarding rules"}}}}}}}},"post":{"tags":["Inbound"],"summary":"Add a forwarding rule to a domain","description":"Creates a forwarding rule.","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the domain","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["localpart","destination"],"properties":{"localpart":{"type":"string","description":"Address prefix to match. Use the literal \"*\" for catch-all. Otherwise must be a valid RFC 5321 local-part (max 64 chars). Stored lowercased; plus-addressing is handled at match time, so a rule for \"support\" also matches \"support+anything\".","example":"support"},"destination":{"type":"string","format":"email","description":"Bare email address (local@domain). No display names, no quoted local-parts.","example":"team@theirinbox.com"},"active":{"type":"boolean","default":true,"description":"Inactive rules are stored but ignored at RCPT TO. Use this for soft-disable rather than DELETE if you plan to re-enable."}}},"examples":{"Targeted alias":{"value":{"localpart":"support","destination":"team@theirinbox.com"}},"Catch-all":{"value":{"localpart":"*","destination":"inbox@theirinbox.com"}}}}}},"responses":{"201":{"description":"Rule created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"result":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid"},"localpart":{"type":"string"},"destination":{"type":"string","format":"email"},"active":{"type":"integer","enum":[0,1]},"verified":{"type":"integer","enum":[0,1],"description":"Set to 1 once the destination address owner has clicked the verification link sent on rule create. Until 1, inbound-edge will not deliver mail to this rule (the matching index filters verified = 1)."},"last_modified":{"type":"integer"},"created_at":{"type":"integer"}}}}}}}},"400":{"description":"Invalid input or domain is not delivery_type=forward","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"destination must be a bare email address (local@domain)"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found"}}}}}},"409":{"description":"A rule with this (localpart, destination) already exists for this domain","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"A forwarding rule with this localpart and destination already exists"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create forwarding rule"}}}}}}}}},"/inbound/domains/{uuid}/forward-rules/{ruleUuid}":{"get":{"tags":["Inbound"],"summary":"Get a single forwarding rule","description":"Returns one forwarding rule by UUID. Returns 404 if the rule has been deleted.","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the domain","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}},{"name":"ruleUuid","in":"path","required":true,"description":"UUID of the forwarding rule","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}],"responses":{"200":{"description":"Rule found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"result":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid"},"localpart":{"type":"string"},"destination":{"type":"string","format":"email"},"active":{"type":"integer","enum":[0,1]},"verified":{"type":"integer","enum":[0,1],"description":"Set to 1 once the destination address owner has clicked the verification link sent on rule create. Until 1, inbound-edge will not deliver mail to this rule (the matching index filters verified = 1)."},"last_modified":{"type":"integer"},"created_at":{"type":"integer"}}}}}}}},"400":{"description":"Invalid UUID","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid UUID"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Rule or domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forwarding rule not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch forwarding rule"}}}}}}}},"patch":{"tags":["Inbound"],"summary":"Update a forwarding rule","description":"Updates a forwarding rule.","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the domain","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}},{"name":"ruleUuid","in":"path","required":true,"description":"UUID of the forwarding rule","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"destination":{"type":"string","format":"email","description":"New destination email. Validated as a bare local@domain."},"active":{"type":"boolean","description":"Toggle the rule on/off without deleting it."}}},"examples":{"Re-target destination":{"value":{"destination":"newteam@theirinbox.com"}},"Pause the rule":{"value":{"active":false}}}}}},"responses":{"200":{"description":"Rule updated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"result":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid"},"localpart":{"type":"string"},"destination":{"type":"string","format":"email"},"active":{"type":"integer","enum":[0,1]},"verified":{"type":"integer","enum":[0,1],"description":"Set to 1 once the destination address owner has clicked the verification link sent on rule create. Until 1, inbound-edge will not deliver mail to this rule (the matching index filters verified = 1)."},"last_modified":{"type":"integer"},"created_at":{"type":"integer"}}}}}}}},"400":{"description":"Invalid input, or attempt to change immutable localpart","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"localpart cannot be changed; delete the rule and create a new one to rename it"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Rule or domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forwarding rule not found"}}}}}},"409":{"description":"Update would collide with another rule on (localpart, destination)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Another forwarding rule already exists with this localpart and destination"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to update forwarding rule"}}}}}}}},"delete":{"tags":["Inbound"],"summary":"Delete a forwarding rule","description":"Deletes the rule. Inbound-edge stops considering it on next sync.","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the domain","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}},{"name":"ruleUuid","in":"path","required":true,"description":"UUID of the forwarding rule","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}],"responses":{"200":{"description":"Rule deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Forwarding rule deleted"}}}}}},"400":{"description":"Invalid UUID","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid UUID"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Rule or domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forwarding rule not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to delete forwarding rule"}}}}}}}}},"/inbound/forward-destinations":{"get":{"tags":["Inbound"],"summary":"List verified (and pending) forwarding destinations","description":"Lists forwarding destinations and their verification status.","responses":{"200":{"description":"Destinations listed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"result":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","example":"7c1f7c14-1234-4abc-8def-0123456789ab"},"email":{"type":"string","format":"email","example":"team@theirinbox.com"},"verified":{"type":"integer","enum":[0,1],"description":"1 once the destination owner has clicked the verification link. Until 1, no inbound mail is delivered to rules pointing at this address.","example":1},"verified_at":{"type":"integer","nullable":true,"description":"Unix seconds when the destination was verified. Null while pending.","example":1735937552},"created_at":{"type":"integer","example":1735937552},"last_modified":{"type":"integer","example":1735937552}}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to list verified destinations"}}}}}}}}},"/inbound/forward-destinations/{uuid}/resend":{"post":{"tags":["Inbound"],"summary":"Resend the verification email for a pending destination","description":"Resends the verification email for a pending destination.","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the verified_destinations row","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}],"responses":{"200":{"description":"Verification email sent","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Verification email sent"},"result":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"}}}}}}}},"400":{"description":"Invalid UUID","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid destination UUID"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Destination not found for this owner","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Destination not found"}}}}}},"409":{"description":"Destination is already verified","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Destination is already verified"}}}}}},"429":{"description":"Per-destination resend cap hit","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Too many verification emails sent for this destination in the last 24 hours"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to resend verification email"}}}}}}}}},"/inbound/forward-destinations/verify":{"post":{"tags":["Inbound"],"summary":"Consume a forwarding-destination verification token","description":"Verifies a forwarding destination via the token from the email link. Public — no auth.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"Opaque verification token from the email link's ?token= query parameter.","example":"lkM2_oXk-OQAAAAA..."}}}}}},"responses":{"200":{"description":"Token consumed (or was already consumed for this destination)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"status":{"type":"string","enum":["verified","already_verified"],"example":"verified"},"email":{"type":"string","format":"email","example":"team@theirinbox.com"},"rules_updated":{"type":"integer","description":"Number of forwarding rules flipped to verified = 1 by this request. Only present when status = verified.","example":3}}}}}},"400":{"description":"Invalid request body or malformed token","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid token"}}}}}},"404":{"description":"Token not recognized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"status":{"type":"string","example":"invalid"},"error":{"type":"string","example":"Verification link is invalid or has been revoked."}}}}}},"410":{"description":"Token expired (TTL is 48h)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"status":{"type":"string","example":"expired"},"error":{"type":"string","example":"Verification link has expired. Ask the JetEmail account owner to resend it."}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to verify destination"}}}}}}}}},"/inbound/settings/{uuid}":{"get":{"tags":["Inbound"],"summary":"Get inbound domain settings","description":"Returns the full configuration for a specific inbound domain. Mode-specific fields (smtp_servers, webhook_url and friends, forward_*_verified) are only present when relevant to the domain's delivery_type.","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the domain","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}],"responses":{"200":{"description":"Successfully retrieved domain settings","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"result":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"domain":{"type":"string","example":"example.com"},"delivery_type":{"type":"string","enum":["smtp","webhook","forward"],"example":"smtp"},"status":{"type":"string","enum":["active","disabled"],"example":"active"},"smtp_servers":{"type":"array","nullable":true,"description":"Only populated for delivery_type=smtp; null otherwise.","items":{"type":"object","properties":{"url":{"type":"string","example":"mail.example.com:25"},"priority":{"type":"integer","example":1},"tls_enabled":{"type":"boolean","example":false},"timeout":{"type":"integer","example":30000}}}},"webhook_url":{"type":"string","format":"uri","nullable":true,"description":"Only populated for delivery_type=webhook; null otherwise.","example":"https://example.com/webhook/inbound"},"webhook_method":{"type":"string","enum":["POST","PUT"],"nullable":true,"description":"Only populated for delivery_type=webhook; null otherwise."},"webhook_headers":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Only populated for delivery_type=webhook; null otherwise."},"webhook_timeout":{"type":"integer","nullable":true,"description":"Only populated for delivery_type=webhook; null otherwise.","example":30000},"webhook_retry_count":{"type":"integer","nullable":true,"description":"Only populated for delivery_type=webhook; null otherwise.","example":3},"webhook_auth_header":{"type":"string","nullable":true,"description":"Only populated for delivery_type=webhook; null otherwise."},"webhook_secret":{"type":"string","nullable":true,"description":"Only populated for delivery_type=webhook; null otherwise. Used to validate the HMAC signature on webhook payloads."},"forward_mx_verified":{"type":"integer","enum":[0,1],"description":"Only present for delivery_type=forward. DNS verification flag for the customer's MX record. Inbound mail is rejected with 550 until all four forward_*_verified flags are 1.","example":0},"forward_dkim_verified":{"type":"integer","enum":[0,1],"description":"Only present for delivery_type=forward. DNS verification flag for the customer's DKIM CNAME.","example":0},"forward_spf_verified":{"type":"integer","enum":[0,1],"description":"Only present for delivery_type=forward. DNS verification flag for the customer's SPF record.","example":0},"forward_dmarc_verified":{"type":"integer","enum":[0,1],"description":"Only present for delivery_type=forward. DNS verification flag for the customer's DMARC record.","example":0},"last_modified":{"type":"integer","nullable":true,"description":"Unix epoch seconds.","example":1735937552},"created_at":{"type":"integer","nullable":true,"description":"Unix epoch seconds.","example":1735937552}}}}}}}},"400":{"description":"Invalid UUID format","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid UUID format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch domain settings"}}}}}}}},"patch":{"tags":["Inbound"],"summary":"Update inbound domain settings","description":"Updates the configuration of an inbound domain. Mode-specific fields are strictly enforced: smtp_servers is only allowed when the effective delivery_type is smtp, the webhook_* fields are only allowed when it is webhook, and forward accepts neither. The \"effective\" type is the new delivery_type if you are changing it in this request, otherwise the current one. Sending fields from the wrong mode returns 400. The forward_*_verified DNS flags are read-only and cannot be set via this endpoint.","parameters":[{"name":"uuid","in":"path","required":true,"description":"UUID of the inbound domain","schema":{"type":"string","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Any subset of the listed fields. At least one updatable field is required; sending an empty body returns 400.","properties":{"status":{"type":"string","enum":["active","disabled"],"description":"Domain status. \"disabled\" causes inbound-edge to stop accepting mail for the domain."},"delivery_type":{"type":"string","enum":["smtp","webhook","forward"],"description":"Switch the domain's delivery mode. The body may also include the new mode's fields in the same request."},"smtp_servers":{"type":"array","description":"Only for delivery_type=smtp. Rejected with 400 if sent on a webhook or forward domain.","items":{"oneOf":[{"type":"string","example":"mail.example.com:25"},{"type":"object","required":["url"],"properties":{"url":{"type":"string","example":"mail.example.com:25"},"priority":{"type":"integer","example":1},"tls_enabled":{"type":"boolean","default":false},"timeout":{"type":"integer","default":30000}}}]}},"webhook_url":{"type":"string","format":"uri","nullable":true,"description":"Only for delivery_type=webhook. Rejected with 400 if sent on an smtp or forward domain. Pass null to clear.","example":"https://example.com/webhook/inbound"},"webhook_method":{"type":"string","enum":["POST","PUT"],"description":"Only for delivery_type=webhook. Rejected with 400 if sent on an smtp or forward domain."},"webhook_headers":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Only for delivery_type=webhook. Rejected with 400 if sent on an smtp or forward domain. Pass null to clear."},"webhook_timeout":{"type":"integer","nullable":true,"description":"Only for delivery_type=webhook. Rejected with 400 if sent on an smtp or forward domain."},"webhook_retry_count":{"type":"integer","nullable":true,"description":"Only for delivery_type=webhook. Rejected with 400 if sent on an smtp or forward domain."},"webhook_auth_header":{"type":"string","nullable":true,"description":"Only for delivery_type=webhook. Rejected with 400 if sent on an smtp or forward domain."}}},"examples":{"Disable a domain":{"value":{"status":"disabled"}},"Update SMTP servers":{"value":{"smtp_servers":[{"url":"mail.example.com:587","priority":1,"tls_enabled":true}]}},"Switch from smtp to webhook":{"summary":"Atomic mode change with new mode's fields in the same request","value":{"delivery_type":"webhook","webhook_url":"https://example.com/webhook/inbound"}},"Switch to forwarding":{"summary":"Forward delivery accepts no further config; rules are added separately via /forward-rules","value":{"delivery_type":"forward"}}}}}},"responses":{"200":{"description":"Settings updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Domain updated successfully"}}}}}},"400":{"description":"Bad Request - Invalid input or cross-mode field bleed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid input format"}}},"examples":{"No fields to update":{"value":{"success":false,"error":"No fields to update"}},"Wrong fields for delivery_type=forward":{"summary":"smtp_servers or webhook_* sent on a forward domain","value":{"success":false,"error":"Fields not allowed for delivery_type=forward: smtp_servers, webhook_url"}},"Wrong fields for delivery_type=smtp":{"summary":"webhook_* sent on an smtp domain","value":{"success":false,"error":"Fields not allowed for delivery_type=smtp: webhook_url"}},"Wrong fields for delivery_type=webhook":{"summary":"smtp_servers sent on a webhook domain","value":{"success":false,"error":"Fields not allowed for delivery_type=webhook: smtp_servers"}},"Invalid delivery_type":{"value":{"success":false,"error":"delivery_type must be smtp, webhook, or forward"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Not Found - Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to update domain"}}}}}}}}},"/inbound/logs":{"get":{"tags":["Inbound"],"summary":"Get inbound email logs","description":"Retrieves logs of inbound email activity with filtering options. Either uuid (for domain) or subdomain_id parameter is required.","parameters":[{"name":"uuid","in":"query","description":"UUID of the inbound domain to fetch logs for. Either uuid or subdomain_id is required.","schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"}},{"name":"subdomain_id","in":"query","description":"ID of the subdomain to fetch logs for. Either uuid or subdomain_id is required.","schema":{"type":"integer","minimum":1}},{"name":"limit","in":"query","description":"Number of records to return (1-1000)","schema":{"type":"integer","minimum":1,"maximum":1000,"default":100}},{"name":"page","in":"query","description":"Page number for pagination","schema":{"type":"integer","minimum":1,"default":1}},{"name":"offset","in":"query","description":"Number of records to skip (alternative to page)","schema":{"type":"integer","minimum":0,"default":0}},{"name":"uid","in":"query","description":"Filter by unique identifier","schema":{"type":"string","pattern":"^[A-Za-z0-9-_]{1,100}$"}},{"name":"logtype","in":"query","description":"Filter by log type","schema":{"type":"string","enum":["spam","delivery","inbound","outbound"]}},{"name":"subject","in":"query","description":"Filter by email subject","schema":{"type":"string","maxLength":500}},{"name":"from","in":"query","description":"Filter by sender email","schema":{"type":"string","format":"email"}},{"name":"to","in":"query","description":"Filter by recipient email","schema":{"type":"string","format":"email"}},{"name":"spamscore_min","in":"query","description":"Filter by minimum spam score","schema":{"type":"number","minimum":0}},{"name":"spamscore_max","in":"query","description":"Filter by maximum spam score","schema":{"type":"number","minimum":0}},{"name":"host","in":"query","description":"Filter by host","schema":{"type":"string","maxLength":100}},{"name":"ip","in":"query","description":"Filter by IP address","schema":{"type":"string","pattern":"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"}},{"name":"date_from","in":"query","description":"Filter by start date (Unix timestamp)","schema":{"type":"integer","minimum":0}},{"name":"date_to","in":"query","description":"Filter by end date (Unix timestamp)","schema":{"type":"integer","minimum":0}},{"name":"sort_by","in":"query","description":"Field to sort by","schema":{"type":"string","default":"date","maxLength":50}},{"name":"sort_order","in":"query","description":"Sort order","schema":{"type":"string","enum":["ASC","DESC"],"default":"DESC"}}],"responses":{"200":{"description":"Successfully retrieved logs","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","description":"Consolidated log entries. Each entry represents a single inbound email (keyed by uid) with aggregated delivery/rejection counts and an actions array containing the individual underlying log rows.","items":{"type":"object","properties":{"uid":{"type":"string","description":"Unique identifier for the email","example":"67020a88e9ab3a023e12"},"status":{"type":"string","description":"Overall status of the email across all actions (e.g. delivered, rejected, pending)","example":"delivered"},"from":{"type":"string","description":"Sender email address","example":"sender@example.com"},"to":{"type":"string","description":"Recipient email address","example":"recipient@example.com"},"subject":{"type":"string","description":"Email subject","example":"Re: Online afspraken"},"rejected_count":{"type":"integer","description":"Number of rejected delivery attempts aggregated into this entry","example":12},"delivery_count":{"type":"integer","description":"Number of successful delivery attempts aggregated into this entry","example":1},"delivered_timestamp":{"type":"integer","format":"int64","description":"Millisecond Unix timestamp of the successful delivery. 0 or null if never delivered.","example":1776972847891},"rejected_response":{"type":"string","description":"Representative SMTP response for the most recent rejection, if any","example":"RCPT TO failed for info@example.com: 450 4.1.8 ..."},"response":{"type":"string","description":"Representative SMTP response for the successful delivery, if any","example":"250 2.0.0 Ok: queued as 638B63A5AD5"},"actions":{"type":"array","description":"Individual log actions that make up this consolidated entry, in chronological order. Each item is a single underlying log row (inbound receipt, rejection, delivery attempt, spam evaluation, etc.).","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for this action row","example":"bc1ca372-0000-0000-0000-000000000000"},"logtype":{"type":"string","description":"Type of action. Known values include: inbound, delivery, REJECTED, spam, outbound.","example":"inbound"},"response":{"type":"string","description":"SMTP or processing response for this action","example":"250 2.0.0 Ok: queued as 638B63A5AD5"},"date":{"type":"integer","format":"int64","description":"Millisecond Unix timestamp of the action","example":1776933973950},"timestamp":{"type":"string","format":"date-time","description":"ISO-8601 timestamp of the action","example":"2026-04-23T08:46:13.950Z"},"host":{"type":"string","description":"Host involved in the action","example":""},"ip":{"type":"string","description":"IP address associated with the action","example":""},"port":{"type":"integer","description":"Port number used","example":0},"mode":{"type":"string","description":"Connection mode (smtp, http, https)","example":""},"delay":{"type":"number","description":"Delay in seconds before this action","example":0},"spam_score":{"type":"number","description":"Spam score evaluated for this action","example":0},"spam_report":{"type":"string","description":"Spam report text for this action","example":""}}}}}}},"count":{"type":"integer","description":"Number of entries returned in this response","example":1}}}}}},"400":{"description":"Bad Request - Invalid parameters","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Invalid parameter format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Required information not found"}}}}}},"404":{"description":"Not Found - No results found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"No results found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Failed to fetch logs"}}}}}}}}},"/inbound/filters/blocklist":{"get":{"tags":["Inbound"],"summary":"Get domain blocklist rules","description":"Retrieves blocklist rules for a specific domain. Provide exactly one of: domain, subdomain_id, or subdomain_uuid.","parameters":[{"name":"domain","in":"query","required":false,"schema":{"type":"string"},"description":"Fully qualified domain name"},{"name":"subdomain_id","in":"query","required":false,"schema":{"type":"integer"},"description":"Numeric subdomain ID"},{"name":"subdomain_uuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Subdomain UUID"}],"responses":{"200":{"description":"Successfully retrieved blocklist rules","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rules":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"userId":{"type":"string","nullable":true},"organizationId":{"type":"string","nullable":true},"domain":{"type":"string","example":"example.com"},"action":{"type":"string","enum":["DENY"]},"name":{"type":"string","example":"Block spam senders"},"description":{"type":"string","nullable":true},"enabled":{"type":"integer","enum":[0,1],"example":1},"deleted":{"type":"integer","enum":[0,1],"example":0},"last_modified":{"type":"integer","example":1735689600},"conditions":{"type":"object","properties":{"senders":{"type":"array","items":{"type":"object","properties":{"sender_type":{"type":"string","enum":["email","domain","pattern"]},"sender_value":{"type":"string"}}}},"recipients":{"type":"array","items":{"type":"object","properties":{"recipient_type":{"type":"string","enum":["email","domain","pattern"]},"recipient_value":{"type":"string"}}}},"subjects":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex"]},"subject_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1]}}}},"body":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["contains","regex"]},"body_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1]},"max_body_size":{"type":"integer","nullable":true}}}},"headers":{"type":"array","items":{"type":"object","properties":{"header_name":{"type":"string"},"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex","exists"]},"header_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1]}}}},"ips":{"type":"array","items":{"type":"object","properties":{"ip_type":{"type":"string","enum":["single","cidr","range"]},"ip_value":{"type":"string","example":"192.168.1.0/24"}}}},"size":{"type":"object","nullable":true,"properties":{"min_size":{"type":"integer","nullable":true},"max_size":{"type":"integer","nullable":true}}},"attachments":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["filename","extension","mimetype","none","has_attachments"]},"match_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1]}}}}}}}}}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"domain, subdomain_id, or subdomain_uuid is required"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch blocklist rules"}}}}}}}},"post":{"tags":["Inbound"],"summary":"Create domain blocklist rule","description":"Creates a new blocklist rule for a domain. Provide the target via one of: domain (body or query param), subdomain_id (query), or subdomain_uuid (query).","parameters":[{"name":"domain","in":"query","required":false,"schema":{"type":"string"},"description":"Domain (alternative to body.domain)"},{"name":"subdomain_id","in":"query","required":false,"schema":{"type":"integer"},"description":"Numeric subdomain ID"},{"name":"subdomain_uuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Subdomain UUID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Rule name (alphanumeric, spaces, hyphens, underscores, periods)","example":"Block spam senders"},"description":{"type":"string","maxLength":500,"description":"Optional rule description"},"domain":{"type":"string","description":"Domain to apply the rule to (alternative to query param)","example":"example.com"},"senders":{"type":"array","items":{"type":"object","required":["sender_type","sender_value"],"properties":{"sender_type":{"type":"string","enum":["email","domain","pattern"]},"sender_value":{"type":"string","example":"spam-domain.com"}}}},"recipients":{"type":"array","items":{"type":"object","required":["recipient_type","recipient_value"],"properties":{"recipient_type":{"type":"string","enum":["email","domain","pattern"]},"recipient_value":{"type":"string"}}}},"subjects":{"type":"array","items":{"type":"object","required":["match_type","subject_value"],"properties":{"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex"]},"subject_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"body":{"type":"array","items":{"type":"object","required":["match_type","body_value"],"properties":{"match_type":{"type":"string","enum":["contains","regex"]},"body_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1],"default":0},"max_body_size":{"type":"integer","nullable":true}}}},"headers":{"type":"array","items":{"type":"object","required":["header_name","match_type"],"properties":{"header_name":{"type":"string"},"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex","exists"]},"header_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"ips":{"type":"array","items":{"type":"object","required":["ip_type","ip_value"],"properties":{"ip_type":{"type":"string","enum":["single","cidr","range"]},"ip_value":{"type":"string","example":"10.0.0.1"}}}},"size":{"type":"object","nullable":true,"properties":{"min_size":{"type":"integer","nullable":true},"max_size":{"type":"integer","nullable":true}}},"attachments":{"type":"array","items":{"type":"object","required":["match_type"],"properties":{"match_type":{"type":"string","enum":["filename","extension","mimetype","none","has_attachments"]},"match_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}}}},"examples":{"Block by sender domain":{"value":{"name":"Block spam domain","domain":"example.com","senders":[{"sender_type":"domain","sender_value":"spam-domain.com"}]}},"Block by IP":{"value":{"name":"Block suspicious IP","domain":"example.com","ips":[{"ip_type":"single","ip_value":"192.168.1.100"}]}}}}}},"responses":{"200":{"description":"Rule created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"uuid":{"type":"string","format":"uuid","description":"UUID of the created rule","example":"550e8400-e29b-41d4-a716-446655440000"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Missing rule name"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create blocklist rule"}}}}}}}}},"/inbound/quarantine-release":{"post":{"tags":["Inbound"],"summary":"Release email from quarantine","description":"Releases a quarantined email for delivery using its UID.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["uid"],"properties":{"uid":{"type":"string","pattern":"^[A-Za-z0-9-_.]{1,100}$","description":"Unique identifier of the quarantined message","example":"DE398F73-6CBC-4333-B394-6DAA6792525B.1"}}}}}},"responses":{"200":{"description":"Successfully retrieved and processed quarantined email","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"EML file successfully released from quarantine and sent to mail server"},"data":{"type":"object","properties":{"uid":{"type":"string","description":"Original UID of the message","example":"DE398F73-6CBC-4333-B394-6DAA6792525B.1"},"domain_uuid":{"type":"string","format":"uuid","description":"UUID of the domain the message belonged to","example":"12345678-1234-4321-abcd-123456789012"},"domain_name":{"type":"string","description":"Name of the domain the message belonged to","example":"example.com"}}}}}}}},"400":{"description":"Bad request - Invalid UID format or missing UID","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid UID format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User authentication, log location, or db_uuid not found"}}}}}},"404":{"description":"UID not found in logs or EML file not found in quarantine","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"UID not found in any authorized domain logs"}}}}}},"500":{"description":"Internal server error - Could be quarantine bucket access failure or mail server processing failure","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to send EML to mail server (502)"},"details":{"type":"string","description":"Additional error details when available","example":"Bad Gateway: Upstream server error"}}}}}}}}},"/inbound/filters/blocklist/{uuid}":{"get":{"tags":["Inbound"],"summary":"Get domain blocklist rule","description":"Retrieves a single domain blocklist rule with all its conditions","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the blocklist rule"}],"responses":{"200":{"description":"Successfully retrieved rule","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rule":{"type":"object","description":"Rule object with conditions (same schema as list response items)"}}}}}},"400":{"description":"Invalid UUID","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid uuid"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}}}},"patch":{"tags":["Inbound"],"summary":"Update domain blocklist rule","description":"Updates an existing domain blocklist rule. Can update name, description, enabled, and/or conditions. When updating conditions, the entire condition type is replaced.","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the blocklist rule to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":500,"nullable":true},"enabled":{"type":"boolean"},"senders":{"type":"array","items":{"type":"object"}},"recipients":{"type":"array","items":{"type":"object"}},"subjects":{"type":"array","items":{"type":"object"}},"body":{"type":"array","items":{"type":"object"}},"headers":{"type":"array","items":{"type":"object"}},"ips":{"type":"array","items":{"type":"object"}},"size":{"type":"object","nullable":true},"attachments":{"type":"array","items":{"type":"object"}}}}}}},"responses":{"200":{"description":"Rule updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"No fields to update"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to update blocklist rule"}}}}}}}},"delete":{"tags":["Inbound"],"summary":"Delete domain blocklist rule","description":"Deletes a domain blocklist rule","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the blocklist rule to delete"}],"responses":{"200":{"description":"Rule deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}},"400":{"description":"Invalid UUID","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid uuid"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to delete blocklist rule"}}}}}}}}},"/inbound/filters/allowlist":{"get":{"tags":["Inbound"],"summary":"Get domain allowlist rules","description":"Retrieves allowlist rules for a specific domain. Provide exactly one of: domain, subdomain_id, or subdomain_uuid.","parameters":[{"name":"domain","in":"query","required":false,"schema":{"type":"string"},"description":"Fully qualified domain name"},{"name":"subdomain_id","in":"query","required":false,"schema":{"type":"integer"},"description":"Numeric subdomain ID"},{"name":"subdomain_uuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Subdomain UUID"}],"responses":{"200":{"description":"Successfully retrieved allowlist rules","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rules":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"userId":{"type":"string","nullable":true},"organizationId":{"type":"string","nullable":true},"domain":{"type":"string","example":"example.com"},"action":{"type":"string","enum":["ALLOW"]},"name":{"type":"string","example":"Allow trusted senders"},"description":{"type":"string","nullable":true},"enabled":{"type":"integer","enum":[0,1],"example":1},"deleted":{"type":"integer","enum":[0,1],"example":0},"last_modified":{"type":"integer","example":1735689600},"conditions":{"type":"object","properties":{"senders":{"type":"array","items":{"type":"object","properties":{"sender_type":{"type":"string","enum":["email","domain","pattern"]},"sender_value":{"type":"string"}}}},"recipients":{"type":"array","items":{"type":"object","properties":{"recipient_type":{"type":"string","enum":["email","domain","pattern"]},"recipient_value":{"type":"string"}}}},"subjects":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex"]},"subject_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1]}}}},"body":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["contains","regex"]},"body_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1]},"max_body_size":{"type":"integer","nullable":true}}}},"headers":{"type":"array","items":{"type":"object","properties":{"header_name":{"type":"string"},"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex","exists"]},"header_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1]}}}},"ips":{"type":"array","items":{"type":"object","properties":{"ip_type":{"type":"string","enum":["single","cidr","range"]},"ip_value":{"type":"string","example":"192.168.1.0/24"}}}},"size":{"type":"object","nullable":true,"properties":{"min_size":{"type":"integer","nullable":true},"max_size":{"type":"integer","nullable":true}}},"attachments":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["filename","extension","mimetype","none","has_attachments"]},"match_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1]}}}}}}}}}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"domain, subdomain_id, or subdomain_uuid is required"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch allowlist rules"}}}}}}}},"post":{"tags":["Inbound"],"summary":"Create domain allowlist rule","description":"Creates a new allowlist rule for a domain. Provide the target via one of: domain (body or query param), subdomain_id (query), or subdomain_uuid (query).","parameters":[{"name":"domain","in":"query","required":false,"schema":{"type":"string"},"description":"Domain (alternative to body.domain)"},{"name":"subdomain_id","in":"query","required":false,"schema":{"type":"integer"},"description":"Numeric subdomain ID"},{"name":"subdomain_uuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Subdomain UUID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Rule name (alphanumeric, spaces, hyphens, underscores, periods)","example":"Allow trusted senders"},"description":{"type":"string","maxLength":500,"description":"Optional rule description"},"domain":{"type":"string","description":"Domain to apply the rule to (alternative to query param)","example":"example.com"},"senders":{"type":"array","items":{"type":"object","required":["sender_type","sender_value"],"properties":{"sender_type":{"type":"string","enum":["email","domain","pattern"]},"sender_value":{"type":"string","example":"partner.com"}}}},"recipients":{"type":"array","items":{"type":"object","required":["recipient_type","recipient_value"],"properties":{"recipient_type":{"type":"string","enum":["email","domain","pattern"]},"recipient_value":{"type":"string"}}}},"subjects":{"type":"array","items":{"type":"object","required":["match_type","subject_value"],"properties":{"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex"]},"subject_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"body":{"type":"array","items":{"type":"object","required":["match_type","body_value"],"properties":{"match_type":{"type":"string","enum":["contains","regex"]},"body_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1],"default":0},"max_body_size":{"type":"integer","nullable":true}}}},"headers":{"type":"array","items":{"type":"object","required":["header_name","match_type"],"properties":{"header_name":{"type":"string"},"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex","exists"]},"header_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"ips":{"type":"array","items":{"type":"object","required":["ip_type","ip_value"],"properties":{"ip_type":{"type":"string","enum":["single","cidr","range"]},"ip_value":{"type":"string","example":"10.0.0.1"}}}},"size":{"type":"object","nullable":true,"properties":{"min_size":{"type":"integer","nullable":true},"max_size":{"type":"integer","nullable":true}}},"attachments":{"type":"array","items":{"type":"object","required":["match_type"],"properties":{"match_type":{"type":"string","enum":["filename","extension","mimetype","none","has_attachments"]},"match_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}}}},"examples":{"Allow by sender domain":{"value":{"name":"Allow partner emails","domain":"example.com","senders":[{"sender_type":"domain","sender_value":"partner.com"}]}},"Allow by IP range":{"value":{"name":"Allow office IPs","domain":"example.com","ips":[{"ip_type":"cidr","ip_value":"10.0.0.0/8"}]}}}}}},"responses":{"200":{"description":"Rule created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"uuid":{"type":"string","format":"uuid","description":"UUID of the created rule","example":"550e8400-e29b-41d4-a716-446655440000"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Missing rule name"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Domain not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create allowlist rule"}}}}}}}}},"/inbound/filters/allowlist/{uuid}":{"get":{"tags":["Inbound"],"summary":"Get domain allowlist rule","description":"Retrieves a single domain allowlist rule with all its conditions","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the allowlist rule"}],"responses":{"200":{"description":"Successfully retrieved rule","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rule":{"type":"object","description":"Rule object with conditions (same schema as list response items)"}}}}}},"400":{"description":"Invalid UUID","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid uuid"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}}}},"patch":{"tags":["Inbound"],"summary":"Update domain allowlist rule","description":"Updates an existing domain allowlist rule. Can update name, description, enabled, and/or conditions. When updating conditions, the entire condition type is replaced.","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the allowlist rule to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":500,"nullable":true},"enabled":{"type":"boolean"},"senders":{"type":"array","items":{"type":"object"}},"recipients":{"type":"array","items":{"type":"object"}},"subjects":{"type":"array","items":{"type":"object"}},"body":{"type":"array","items":{"type":"object"}},"headers":{"type":"array","items":{"type":"object"}},"ips":{"type":"array","items":{"type":"object"}},"size":{"type":"object","nullable":true},"attachments":{"type":"array","items":{"type":"object"}}}}}}},"responses":{"200":{"description":"Rule updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"No fields to update"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to update allowlist rule"}}}}}}}},"delete":{"tags":["Inbound"],"summary":"Delete domain allowlist rule","description":"Deletes a domain allowlist rule","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the allowlist rule to delete"}],"responses":{"200":{"description":"Rule deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}},"400":{"description":"Invalid UUID","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid uuid"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to delete allowlist rule"}}}}}}}}},"/inbound/account/allowlist":{"get":{"tags":["Inbound"],"summary":"Get account-level allowlist rules","description":"Retrieves all allowlist rules that apply across all domains in the authenticated user's account. These rules are scoped by userId/organizationId and are not tied to any specific domain.","responses":{"200":{"description":"Successfully retrieved account allowlist rules","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rules":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","description":"Unique identifier for the rule","example":"550e8400-e29b-41d4-a716-446655440000"},"name":{"type":"string","description":"Rule name","example":"Allow partner emails"},"description":{"type":"string","nullable":true,"description":"Optional rule description","example":"Allow all emails from partner domain"},"action":{"type":"string","enum":["ALLOW"]},"userId":{"type":"string","nullable":true,"description":"User UUID who owns this rule"},"organizationId":{"type":"string","nullable":true,"description":"Organization UUID this rule belongs to"},"enabled":{"type":"integer","enum":[0,1],"description":"Whether the rule is enabled","example":1},"deleted":{"type":"integer","enum":[0,1],"example":0},"last_modified":{"type":"integer","description":"Unix timestamp of last modification","example":1735689600},"conditions":{"type":"object","properties":{"senders":{"type":"array","items":{"type":"object","properties":{"sender_type":{"type":"string","enum":["email","domain","pattern"]},"sender_value":{"type":"string","example":"partner.com"}}}},"recipients":{"type":"array","items":{"type":"object","properties":{"recipient_type":{"type":"string","enum":["email","domain","pattern"]},"recipient_value":{"type":"string"}}}},"subjects":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex"]},"subject_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1]}}}},"headers":{"type":"array","items":{"type":"object","properties":{"header_name":{"type":"string"},"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex","exists"]},"header_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1]}}}},"ips":{"type":"array","items":{"type":"object","properties":{"ip_type":{"type":"string","enum":["single","cidr","range"]},"ip_value":{"type":"string","example":"192.168.1.0/24"}}}},"size":{"type":"object","nullable":true,"properties":{"min_size":{"type":"integer","nullable":true,"description":"Minimum size in bytes"},"max_size":{"type":"integer","nullable":true,"description":"Maximum size in bytes"}}},"attachments":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["filename","extension","mimetype","none"]},"match_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1]}}}}}}}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch account allowlist rules"}}}}}}}},"post":{"tags":["Inbound"],"summary":"Create account-level allowlist rule","description":"Creates a new allowlist rule that applies across all domains in the authenticated user's account. Supports all condition types: senders, recipients, subjects, body, headers, IPs, size, and attachments.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Rule name (alphanumeric, spaces, hyphens, underscores, periods)","example":"Allow partner emails"},"description":{"type":"string","maxLength":500,"description":"Optional rule description","example":"Allow all emails from partner domain across all our domains"},"senders":{"type":"array","items":{"type":"object","required":["sender_type","sender_value"],"properties":{"sender_type":{"type":"string","enum":["email","domain","pattern"]},"sender_value":{"type":"string","example":"partner.com"}}}},"recipients":{"type":"array","items":{"type":"object","required":["recipient_type","recipient_value"],"properties":{"recipient_type":{"type":"string","enum":["email","domain","pattern"]},"recipient_value":{"type":"string"}}}},"subjects":{"type":"array","items":{"type":"object","required":["match_type","subject_value"],"properties":{"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex"]},"subject_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"body":{"type":"array","items":{"type":"object","required":["match_type","body_value"],"properties":{"match_type":{"type":"string","enum":["contains","regex"]},"body_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"headers":{"type":"array","items":{"type":"object","required":["header_name","match_type"],"properties":{"header_name":{"type":"string"},"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex","exists"]},"header_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"ips":{"type":"array","items":{"type":"object","required":["ip_type","ip_value"],"properties":{"ip_type":{"type":"string","enum":["single","cidr","range"]},"ip_value":{"type":"string","example":"10.0.0.1"}}}},"size":{"type":"object","nullable":true,"properties":{"min_size":{"type":"integer","nullable":true,"description":"Minimum size in bytes"},"max_size":{"type":"integer","nullable":true,"description":"Maximum size in bytes"}}},"attachments":{"type":"array","items":{"type":"object","required":["match_type"],"properties":{"match_type":{"type":"string","enum":["filename","extension","mimetype","none"]},"match_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}}}},"examples":{"Allow by sender domain":{"value":{"name":"Allow partner emails","description":"Allow all emails from partner.com across all domains","senders":[{"sender_type":"domain","sender_value":"partner.com"}]}},"Allow by IP range":{"value":{"name":"Allow office IPs","ips":[{"ip_type":"cidr","ip_value":"10.0.0.0/8"}]}}}}}},"responses":{"200":{"description":"Rule created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"uuid":{"type":"string","format":"uuid","description":"UUID of the created rule","example":"550e8400-e29b-41d4-a716-446655440000"}}}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Missing rule name"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create account allowlist rule"}}}}}}}}},"/inbound/account/allowlist/{uuid}":{"get":{"tags":["Inbound"],"summary":"Get account-level allowlist rule","description":"Retrieves a single account-level allowlist rule with all its conditions","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the account allowlist rule"}],"responses":{"200":{"description":"Successfully retrieved rule","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rule":{"type":"object","description":"Rule object with conditions (same schema as list response items)"}}}}}},"403":{"description":"Forbidden - Rule not owned by caller","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}}}},"patch":{"tags":["Inbound"],"summary":"Update account-level allowlist rule","description":"Updates an existing account-level allowlist rule. Can update metadata (name, description, enabled) and/or conditions. When updating conditions, the entire condition type is replaced.","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the account allowlist rule to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":500,"nullable":true},"enabled":{"type":"boolean"},"senders":{"type":"array","items":{"type":"object"}},"recipients":{"type":"array","items":{"type":"object"}},"subjects":{"type":"array","items":{"type":"object"}},"body":{"type":"array","items":{"type":"object"}},"headers":{"type":"array","items":{"type":"object"}},"ips":{"type":"array","items":{"type":"object"}},"size":{"type":"object","nullable":true},"attachments":{"type":"array","items":{"type":"object"}}}}}}},"responses":{"200":{"description":"Rule updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"No fields to update"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}}}},"delete":{"tags":["Inbound"],"summary":"Delete account-level allowlist rule","description":"Deletes an account-level allowlist rule","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the account allowlist rule to delete"}],"responses":{"200":{"description":"Rule deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}}}}},"/inbound/account/blocklist":{"get":{"tags":["Inbound"],"summary":"Get account-level blocklist rules","description":"Retrieves all blocklist rules that apply across all domains in the authenticated user's account.","responses":{"200":{"description":"Successfully retrieved account blocklist rules","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rules":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"name":{"type":"string","example":"Block spam domain"},"description":{"type":"string","nullable":true,"example":"Block all emails from known spam domain"},"action":{"type":"string","enum":["DENY"]},"userId":{"type":"string","nullable":true},"organizationId":{"type":"string","nullable":true},"enabled":{"type":"integer","enum":[0,1],"example":1},"deleted":{"type":"integer","enum":[0,1],"example":0},"last_modified":{"type":"integer","example":1735689600},"conditions":{"type":"object","properties":{"senders":{"type":"array","items":{"type":"object","properties":{"sender_type":{"type":"string","enum":["email","domain","pattern"]},"sender_value":{"type":"string","example":"spam-domain.com"}}}},"recipients":{"type":"array","items":{"type":"object","properties":{"recipient_type":{"type":"string","enum":["email","domain","pattern"]},"recipient_value":{"type":"string"}}}},"subjects":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex"]},"subject_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1]}}}},"headers":{"type":"array","items":{"type":"object","properties":{"header_name":{"type":"string"},"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex","exists"]},"header_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1]}}}},"ips":{"type":"array","items":{"type":"object","properties":{"ip_type":{"type":"string","enum":["single","cidr","range"]},"ip_value":{"type":"string","example":"192.168.1.100"}}}},"size":{"type":"object","nullable":true,"properties":{"min_size":{"type":"integer","nullable":true},"max_size":{"type":"integer","nullable":true}}},"attachments":{"type":"array","items":{"type":"object","properties":{"match_type":{"type":"string","enum":["filename","extension","mimetype","has_attachments"]},"match_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1]}}}}}}}}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch account blocklist rules"}}}}}}}},"post":{"tags":["Inbound"],"summary":"Create account-level blocklist rule","description":"Creates a new blocklist rule that applies across all domains in the authenticated user's account. The action is automatically set to DENY. Supports all condition types.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Rule name","example":"Block spam domain"},"description":{"type":"string","maxLength":500,"description":"Optional rule description","example":"Block all emails from known spam domain"},"senders":{"type":"array","items":{"type":"object","required":["sender_type","sender_value"],"properties":{"sender_type":{"type":"string","enum":["email","domain","pattern"]},"sender_value":{"type":"string","example":"spam-domain.com"}}}},"recipients":{"type":"array","items":{"type":"object","required":["recipient_type","recipient_value"],"properties":{"recipient_type":{"type":"string","enum":["email","domain","pattern"]},"recipient_value":{"type":"string"}}}},"subjects":{"type":"array","items":{"type":"object","required":["match_type","subject_value"],"properties":{"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex"]},"subject_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"body":{"type":"array","items":{"type":"object","required":["match_type","body_value"],"properties":{"match_type":{"type":"string","enum":["contains","regex"]},"body_value":{"type":"string"},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"headers":{"type":"array","items":{"type":"object","required":["header_name","match_type"],"properties":{"header_name":{"type":"string"},"match_type":{"type":"string","enum":["exact","contains","starts_with","ends_with","regex","exists"]},"header_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}},"ips":{"type":"array","items":{"type":"object","required":["ip_type","ip_value"],"properties":{"ip_type":{"type":"string","enum":["single","cidr","range"]},"ip_value":{"type":"string","example":"192.168.1.100"}}}},"size":{"type":"object","nullable":true,"properties":{"min_size":{"type":"integer","nullable":true},"max_size":{"type":"integer","nullable":true}}},"attachments":{"type":"array","items":{"type":"object","required":["match_type"],"properties":{"match_type":{"type":"string","enum":["filename","extension","mimetype","has_attachments"]},"match_value":{"type":"string","nullable":true},"case_sensitive":{"type":"integer","enum":[0,1],"default":0}}}}}},"examples":{"Block by sender domain":{"value":{"name":"Block spam domain","description":"Block all emails from spam-domain.com","senders":[{"sender_type":"domain","sender_value":"spam-domain.com"}]}},"Block by IP":{"value":{"name":"Block suspicious IP","ips":[{"ip_type":"single","ip_value":"192.168.1.100"}]}}}}}},"responses":{"200":{"description":"Rule created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"uuid":{"type":"string","format":"uuid","description":"UUID of the created rule","example":"550e8400-e29b-41d4-a716-446655440000"}}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Missing rule name"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create account blocklist rule"}}}}}}}}},"/inbound/account/blocklist/{uuid}":{"get":{"tags":["Inbound"],"summary":"Get account-level blocklist rule","description":"Retrieves a single account-level blocklist rule with all its conditions","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the account blocklist rule"}],"responses":{"200":{"description":"Successfully retrieved rule","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rule":{"type":"object","description":"Rule object with conditions (same schema as list response items, includes action field)"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}}}},"patch":{"tags":["Inbound"],"summary":"Update account-level blocklist rule","description":"Updates an existing account-level blocklist rule. Can update metadata and/or conditions. When updating conditions, the entire condition type is replaced.","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the account blocklist rule to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":500,"nullable":true},"enabled":{"type":"boolean"},"senders":{"type":"array","items":{"type":"object"}},"recipients":{"type":"array","items":{"type":"object"}},"subjects":{"type":"array","items":{"type":"object"}},"body":{"type":"array","items":{"type":"object"}},"headers":{"type":"array","items":{"type":"object"}},"ips":{"type":"array","items":{"type":"object"}},"size":{"type":"object","nullable":true},"attachments":{"type":"array","items":{"type":"object"}}}}}}},"responses":{"200":{"description":"Rule updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"No fields to update"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}}}},"delete":{"tags":["Inbound"],"summary":"Delete account-level blocklist rule","description":"Deletes an account-level blocklist rule","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the account blocklist rule to delete"}],"responses":{"200":{"description":"Rule deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Forbidden"}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}}}}},"/inbound/account/logs":{"get":{"tags":["Inbound"],"summary":"Get logs for all account domains","description":"Retrieves inbound logs across all domains and subdomains owned by the authenticated user/organization. Fans out requests to the logs API for each domain, merges results, and returns a unified sorted and paginated response. Supports the same filter parameters as the per-domain logs endpoint. Limited to 20 domains per request; use the domains parameter to target specific domains if you have more.","parameters":[{"name":"domains","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated list of domain names to filter to (e.g. \"example.com,mail.example.com\"). If omitted, queries all domains in the account (up to 20)."},{"name":"logtype","in":"query","required":false,"schema":{"type":"string","enum":["spam","delivery","inbound","outbound"]},"description":"Filter by log type"},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"email"},"description":"Filter by recipient email"},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"email"},"description":"Filter by sender email"},{"name":"subject","in":"query","required":false,"schema":{"type":"string","maxLength":500},"description":"Filter by subject"},{"name":"ip","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by IP address"},{"name":"date_from","in":"query","required":false,"schema":{"type":"integer"},"description":"Start of date range (Unix timestamp)"},{"name":"date_to","in":"query","required":false,"schema":{"type":"integer"},"description":"End of date range (Unix timestamp)"},{"name":"spamscore_min","in":"query","required":false,"schema":{"type":"number"},"description":"Minimum spam score filter"},{"name":"spamscore_max","in":"query","required":false,"schema":{"type":"number"},"description":"Maximum spam score filter"},{"name":"host","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by host"},{"name":"port","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":65535},"description":"Filter by port number"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","enum":["smtp","http","https"]},"description":"Filter by connection mode"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":1000,"default":100},"description":"Number of entries to return (applied after merging all domains)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0},"description":"Number of entries to skip"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1},"description":"Page number (alternative to offset, takes precedence)"},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","default":"date"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","enum":["ASC","DESC"],"default":"DESC"},"description":"Sort direction"}],"responses":{"200":{"description":"Successfully retrieved account-wide logs","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","description":"Merged and sorted consolidated log entries from all queried domains. Each entry represents a single inbound email (keyed by uid) with aggregated delivery/rejection counts and an actions array of underlying log rows. Entries are tagged with _domain, _domain_uuid, and _domain_type identifying the source domain.","items":{"type":"object","properties":{"_domain":{"type":"string","description":"Domain this log entry belongs to","example":"example.com"},"_domain_uuid":{"type":"string","description":"UUID of the domain this entry belongs to","example":"550e8400-e29b-41d4-a716-446655440000"},"_domain_type":{"type":"string","enum":["domain","subdomain"],"description":"Whether this is a domain or subdomain"},"uid":{"type":"string","description":"Unique identifier for the email","example":"67020a88e9ab3a023e12"},"status":{"type":"string","description":"Overall status of the email across all actions (e.g. delivered, rejected, pending)","example":"delivered"},"from":{"type":"string","description":"Sender email address","example":"sender@example.com"},"to":{"type":"string","description":"Recipient email address","example":"recipient@example.com"},"subject":{"type":"string","description":"Email subject","example":"Re: Online afspraken"},"rejected_count":{"type":"integer","description":"Number of rejected delivery attempts aggregated into this entry","example":12},"delivery_count":{"type":"integer","description":"Number of successful delivery attempts aggregated into this entry","example":1},"delivered_timestamp":{"type":"integer","format":"int64","description":"Millisecond Unix timestamp of the successful delivery. 0 or null if never delivered.","example":1776972847891},"rejected_response":{"type":"string","description":"Representative SMTP response for the most recent rejection, if any","example":"RCPT TO failed for info@example.com: 450 4.1.8 ..."},"response":{"type":"string","description":"Representative SMTP response for the successful delivery, if any","example":"250 2.0.0 Ok: queued as 638B63A5AD5"},"actions":{"type":"array","description":"Individual log actions that make up this consolidated entry, in chronological order. Each item is a single underlying log row (inbound receipt, rejection, delivery attempt, spam evaluation, etc.).","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for this action row","example":"bc1ca372-0000-0000-0000-000000000000"},"logtype":{"type":"string","description":"Type of action. Known values include: inbound, delivery, REJECTED, spam, outbound.","example":"inbound"},"response":{"type":"string","description":"SMTP or processing response for this action","example":"250 2.0.0 Ok: queued as 638B63A5AD5"},"date":{"type":"integer","format":"int64","description":"Millisecond Unix timestamp of the action","example":1776933973950},"timestamp":{"type":"string","format":"date-time","description":"ISO-8601 timestamp of the action","example":"2026-04-23T08:46:13.950Z"},"host":{"type":"string","description":"Host involved in the action","example":""},"ip":{"type":"string","description":"IP address associated with the action","example":""},"port":{"type":"integer","description":"Port number used","example":0},"mode":{"type":"string","description":"Connection mode (smtp, http, https)","example":""},"delay":{"type":"number","description":"Delay in seconds before this action","example":0},"spam_score":{"type":"number","description":"Spam score evaluated for this action","example":0},"spam_report":{"type":"string","description":"Spam report text for this action","example":""}}}}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer","description":"Total entries across all domains (before pagination)","example":450},"limit":{"type":"integer","example":100},"offset":{"type":"integer","example":0},"returned":{"type":"integer","description":"Number of entries in this response","example":100}}},"domains_queried":{"type":"array","description":"Status of each domain query","items":{"type":"object","properties":{"domain":{"type":"string","example":"example.com"},"domain_uuid":{"type":"string"},"domain_type":{"type":"string","enum":["domain","subdomain"]},"count":{"type":"integer","description":"Number of entries returned for this domain"},"status":{"type":"string","enum":["success","error"]}}}},"total_domains":{"type":"integer","description":"Total number of domains in the account","example":5},"domains_included":{"type":"integer","description":"Number of domains actually queried (may be capped at 20)","example":5}}}}}},"400":{"description":"Bad Request - Invalid filter parameters","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid logtype value. Must be: spam, delivery, inbound, or outbound"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User authentication not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch account inbound logs"}}}}}}}}},"/outbound/suppression":{"get":{"tags":["Outbound"],"summary":"Get suppression rules","description":"Retrieves all suppression rules for the authenticated user","responses":{"200":{"description":"Successfully retrieved suppression rules","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":1},"target_value":{"type":"string","example":"user@example.com"},"status":{"type":"integer","description":"1 = active, 0 = inactive","example":1},"created_date":{"type":"string","example":"2024-01-15 10:30:00"}}}}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch suppression rules"}}}}}}}},"post":{"tags":["Outbound"],"summary":"Create suppression rule","description":"Suppresses outbound mail to the given recipient email.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["target_value"],"properties":{"target_value":{"type":"string","format":"email","example":"user@example.com"},"reason":{"type":"string","nullable":true,"example":"Spam reports"}}}}}},"responses":{"200":{"description":"Suppression rule created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"rule":{"type":"object","properties":{"id":{"type":"integer","example":42},"target_value":{"type":"string","example":"user@example.com"},"status":{"type":"integer","example":1},"created_date":{"type":"string","example":"2026-05-11 10:30:00"}}}}}}}},"400":{"description":"Invalid body","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"target_value \"not-an-email\" is not a valid email"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"409":{"description":"Matching active rule already exists","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"A matching active suppression rule already exists"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create suppression rule"}}}}}}}}},"/outbound/suppression/{id}":{"delete":{"tags":["Outbound"],"summary":"Release suppression rule","description":"Releases a suppression rule, removing it from active suppression","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":1,"description":"ID of the suppression rule to delete"},"description":"ID of the suppression rule to release"}],"responses":{"200":{"description":"Suppression rule released successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}}}}},"400":{"description":"Bad request - Invalid ID","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid id"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"403":{"description":"Forbidden - User does not have permission to delete this rule","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"You do not have permission to delete this suppression rule"}}}}}},"404":{"description":"Not found - Suppression rule not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Not found"}}}}}},"410":{"description":"Gone - Suppression rule already deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Suppression rule is already deleted"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to delete suppression rule"}}}}}}}}},"/outbound/suppression/export":{"get":{"tags":["Outbound"],"summary":"Export suppression rules as CSV","description":"Returns active suppression rules as a CSV file.","responses":{"200":{"description":"CSV file of active suppression rules","content":{"text/csv":{"schema":{"type":"string","example":"target_value,status\r\nuser@example.com,1\r\n"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to export suppression rules"}}}}}}}}},"/outbound/suppression/import":{"post":{"tags":["Outbound"],"summary":"Import suppression rules from CSV","description":"Imports recipient emails from a CSV with a target_value column; skips rows that match an existing active rule.","requestBody":{"required":true,"content":{"text/csv":{"schema":{"type":"string","example":"target_value\r\nuser@example.com\r\nother@example.com\r\n"}}}},"responses":{"200":{"description":"Import processed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"inserted":{"type":"integer","example":12},"skipped":{"type":"integer","example":3},"failed":{"type":"array","items":{"type":"object","properties":{"row":{"type":"integer","example":5},"reason":{"type":"string","example":"target_value \"not-an-email\" is not a valid email"}}}}}}}}},"400":{"description":"Invalid CSV or missing columns","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Missing required column \"target_value\""}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Unauthorized"}}}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Body exceeds 5242880 bytes"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to load existing rules"}}}}}}}}},"/webhooks":{"get":{"tags":["Webhooks"],"summary":"List all webhooks","description":"Returns all webhook configurations for the authenticated user","responses":{"200":{"description":"List of webhooks retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"webhooks":{"type":"array","items":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","description":"Unique webhook UUID","example":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"},"name":{"type":"string","description":"Human-readable webhook name/identifier","maxLength":64,"example":"Production Webhook"},"url":{"type":"string","format":"uri","description":"Webhook endpoint URL","example":"https://example.com/webhook"},"secret":{"type":"string","description":"Webhook signing secret","example":"whsec_abc123def456..."},"events":{"type":"array","items":{"type":"string","enum":["outbound.delivered","outbound.bounced","outbound.rejected","outbound.deferred","outbound.spam","outbound.dropped","outbound.virus","outbound.opened","outbound.clicked","outbound.complaint","inbound.received","inbound.delivered","inbound.spam","inbound.blocked"]},"description":"List of event types this webhook subscribes to","example":["outbound.delivered","outbound.bounced","inbound.received"]},"status":{"type":"string","enum":["enabled","disabled"],"description":"Webhook status","example":"enabled"},"filter_users":{"type":"array","items":{"type":"string"},"nullable":true,"description":"Filter outbound events by username (null = all)","example":null},"filter_domains":{"type":"array","items":{"type":"string"},"nullable":true,"description":"Filter inbound events by domain (null = all)","example":["example.com"]},"created_at":{"type":"integer","description":"Unix timestamp of creation","example":1736524800},"last_modified":{"type":"integer","description":"Unix timestamp of last modification","example":1736524800}}}}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch webhooks"}}}}}}}},"post":{"tags":["Webhooks"],"summary":"Create a webhook","description":"Creates a new webhook configuration. A signing secret will be automatically generated.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","url","events"],"properties":{"name":{"type":"string","maxLength":64,"pattern":"^[a-zA-Z0-9-_\\s]+$","description":"Human-readable webhook name. Only letters, numbers, hyphens, underscores, and spaces allowed.","example":"Production Webhook"},"url":{"type":"string","format":"uri","description":"Webhook endpoint URL (must be http or https)","example":"https://example.com/webhook"},"events":{"type":"array","items":{"type":"string","enum":["outbound.delivered","outbound.bounced","outbound.rejected","outbound.deferred","outbound.spam","outbound.dropped","outbound.virus","outbound.opened","outbound.clicked","outbound.complaint","inbound.received","inbound.delivered","inbound.spam","inbound.blocked"]},"minItems":1,"description":"List of event types to subscribe to. Must only include allowed event types.","example":["outbound.delivered","outbound.bounced","inbound.received"]},"status":{"type":"integer","enum":[0,1],"default":1,"description":"Webhook status: 0 = disabled, 1 = enabled","example":1},"filter_users":{"type":"array","items":{"type":"string"},"nullable":true,"description":"Filter outbound events by username. Must be transactional keys or smarthosts you own. (null = all)","example":null},"filter_domains":{"type":"array","items":{"type":"string"},"nullable":true,"description":"Filter inbound events by domain. Must be inbound domains you own. (null = all)","example":["example.com"]}}},"examples":{"Basic Webhook":{"value":{"name":"My Webhook","url":"https://example.com/webhook","events":["outbound.delivered","outbound.bounced"]}},"Webhook with Filters":{"value":{"name":"Production Webhook","url":"https://example.com/webhook","events":["outbound.delivered","outbound.bounced","inbound.received"],"status":1,"filter_domains":["example.com","test.com"]}}}}}},"responses":{"200":{"description":"Webhook created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Webhook created successfully"},"webhook":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","description":"Unique webhook UUID","example":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"},"name":{"type":"string","description":"Human-readable webhook name","example":"Production Webhook"},"url":{"type":"string","example":"https://example.com/webhook"},"secret":{"type":"string","description":"The webhook signing secret. Store this securely - it will not be shown again.","example":"whsec_abc123def456..."},"events":{"type":"array","items":{"type":"string","enum":["outbound.queued","outbound.delivered","outbound.bounced","outbound.rejected","outbound.deferred","outbound.spam","outbound.dropped","outbound.virus","outbound.opened","outbound.clicked","outbound.complaint","inbound.received","inbound.delivered","inbound.spam","inbound.blocked"]},"example":["outbound.delivered","outbound.bounced"]},"status":{"type":"string","example":"enabled"},"filter_users":{"type":"array","items":{"type":"string"},"nullable":true,"example":null},"filter_domains":{"type":"array","items":{"type":"string"},"nullable":true,"example":null},"created_at":{"type":"integer","example":1736524800},"last_modified":{"type":"integer","example":1736524800}}}}}}}},"400":{"description":"Bad request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"URL is required and must be a string"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"403":{"description":"Forbidden - Invalid filter values (users/domains not owned by caller)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid filter_domains: example.com. You can only filter by domains that you own."}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to create webhook"}}}}}}}},"patch":{"tags":["Webhooks"],"summary":"Update a webhook","description":"Updates an existing webhook configuration. Only provided fields will be updated.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["uuid"],"properties":{"uuid":{"type":"string","format":"uuid","description":"UUID of the webhook to update","example":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"},"name":{"type":"string","maxLength":64,"pattern":"^[a-zA-Z0-9-_\\s]+$","description":"New webhook name. Only letters, numbers, hyphens, underscores, and spaces allowed.","example":"Updated Webhook Name"},"url":{"type":"string","format":"uri","description":"New webhook endpoint URL","example":"https://example.com/new-webhook"},"events":{"type":"array","items":{"type":"string","enum":["outbound.delivered","outbound.bounced","outbound.rejected","outbound.deferred","outbound.spam","outbound.dropped","outbound.virus","outbound.opened","outbound.clicked","outbound.complaint","inbound.received","inbound.delivered","inbound.spam","inbound.blocked"]},"minItems":1,"description":"New list of event types. Must only include allowed event types.","example":["outbound.delivered","outbound.bounced","inbound.received"]},"status":{"type":"integer","enum":[0,1],"description":"New webhook status: 0 = disabled, 1 = enabled","example":1},"filter_users":{"type":"array","items":{"type":"string"},"nullable":true,"description":"New filter for outbound events by username. Must be transactional keys or smarthosts you own.","example":null},"filter_domains":{"type":"array","items":{"type":"string"},"nullable":true,"description":"New filter for inbound events by domain. Must be inbound domains you own.","example":["example.com"]}}},"examples":{"Update URL":{"value":{"uuid":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d","url":"https://example.com/new-webhook"}},"Disable Webhook":{"value":{"uuid":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d","status":0}},"Update Events and Filters":{"value":{"uuid":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d","events":["outbound.bounced","outbound.complaint"],"filter_domains":["example.com"]}}}}}},"responses":{"200":{"description":"Webhook updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Webhook updated successfully"}}}}}},"400":{"description":"Bad request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Webhook uuid is required and must be a string"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"403":{"description":"Forbidden - Invalid filter values (users/domains not owned by caller)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid filter_users: my_key. You can only filter by users/keys that you own."}}}}}},"404":{"description":"Not found - Webhook not found or access denied","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Webhook not found or access denied"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to update webhook"}}}}}}}}},"/webhooks/{uuid}":{"get":{"tags":["Webhooks"],"summary":"Get a webhook","description":"Returns a single webhook configuration by UUID","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the webhook to retrieve"}],"responses":{"200":{"description":"Webhook retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"webhook":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","example":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"},"name":{"type":"string","description":"Human-readable webhook name","example":"Production Webhook"},"url":{"type":"string","example":"https://example.com/webhook"},"secret":{"type":"string","example":"whsec_abc123def456..."},"events":{"type":"array","items":{"type":"string","enum":["outbound.queued","outbound.delivered","outbound.bounced","outbound.rejected","outbound.deferred","outbound.spam","outbound.dropped","outbound.virus","outbound.opened","outbound.clicked","outbound.complaint","inbound.received","inbound.delivered","inbound.spam","inbound.blocked"]},"example":["outbound.delivered","outbound.bounced"]},"status":{"type":"string","example":"enabled"},"filter_users":{"type":"array","items":{"type":"string"},"nullable":true,"example":null},"filter_domains":{"type":"array","items":{"type":"string"},"nullable":true,"example":null},"created_at":{"type":"integer","example":1736524800},"last_modified":{"type":"integer","example":1736524800}}}}}}}},"400":{"description":"Bad request - Invalid UUID format","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid webhook UUID format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Not found - Webhook not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Webhook not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to fetch webhook"}}}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","description":"Deletes a webhook configuration","parameters":[{"name":"uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID of the webhook to delete"}],"responses":{"200":{"description":"Webhook deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Webhook deleted successfully"}}}}}},"400":{"description":"Bad request - Invalid UUID format","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid webhook UUID format"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User information not found"}}}}}},"404":{"description":"Not found - Webhook not found or access denied","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Webhook not found or access denied"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to delete webhook"}}}}}}}}},"/webhooks/query":{"post":{"tags":["Webhooks"],"summary":"Query webhook events","description":"Query webhook events with filtering. Returns webhook events that have been triggered for your account.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid","description":"Filter by webhook config UUID","example":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"},"event_id":{"type":"string","description":"Filter by specific event ID","example":"evt_xyz789"},"event_type":{"type":"string","enum":["outbound.queued","outbound.delivered","outbound.bounced","outbound.rejected","outbound.deferred","outbound.spam","outbound.dropped","outbound.virus","outbound.opened","outbound.clicked","outbound.complaint","inbound.received","inbound.delivered","inbound.spam","inbound.blocked"],"description":"Filter by event type","example":"outbound.delivered"},"source_uid":{"type":"string","description":"Filter by source message UID","example":"message-uid-123"},"status":{"type":"string","enum":["success","failed","retry","pending"],"description":"Filter by delivery status","example":"success"},"date_from":{"type":"integer","description":"Filter from Unix timestamp","example":1704825600},"date_to":{"type":"integer","description":"Filter to Unix timestamp","example":1704912000},"limit":{"type":"integer","minimum":1,"maximum":1000,"default":50,"description":"Maximum results to return","example":50},"offset":{"type":"integer","minimum":0,"default":0,"description":"Pagination offset","example":0}}},"examples":{"Query by webhook":{"value":{"uuid":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d","limit":50}},"Query by event type and date":{"value":{"event_type":"outbound.delivered","date_from":1704825600,"date_to":1704912000,"limit":100}},"Query failed deliveries":{"value":{"status":"failed","limit":50}}}}}},"responses":{"200":{"description":"Webhook events retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Event ID","example":"evt_xyz789"},"uuid":{"type":"string","format":"uuid","description":"Webhook config UUID","example":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"},"service":{"type":"string","enum":["outbound","inbound"],"description":"Service that triggered the event","example":"outbound"},"event_type":{"type":"string","description":"Event type","example":"outbound.delivered"},"source_uid":{"type":"string","description":"Source message UID","example":"message-uid-123"},"source_action":{"type":"string","description":"Original action or logtype","example":"ACCEPTED"},"payload":{"type":"object","description":"Event payload sent to webhook","example":{"to":"recipient@example.com","from":"sender@example.com"}},"webhook_url":{"type":"string","format":"uri","description":"Target webhook URL","example":"https://example.com/webhook"},"created_at":{"type":"integer","description":"Unix timestamp when event was created","example":1704825600},"latest_status":{"type":"string","enum":["success","failed","retry"],"description":"Latest delivery status","example":"success"},"total_attempts":{"type":"integer","description":"Total delivery attempts","example":1},"last_response_code":{"type":"integer","description":"HTTP response code from last attempt","example":200}}}},"total":{"type":"integer","description":"Total number of matching events","example":150},"limit":{"type":"integer","description":"Limit used for this query","example":50},"offset":{"type":"integer","description":"Offset used for this query","example":0}}}}}},"400":{"description":"Bad request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Invalid event_type"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User authentication not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to query webhook events"}}}}}}}}},"/webhooks/replay":{"post":{"tags":["Webhooks"],"summary":"Replay a webhook event","description":"Replay a previously sent webhook event. The event will be re-queued for delivery to the configured webhook URL.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event_id":{"type":"string","description":"Event ID to replay","example":"evt_abc123"},"source_uid":{"type":"string","description":"Source message UID to replay events for","example":"message-uid-xyz"},"uuid":{"type":"string","format":"uuid","description":"Optional: Replay to a specific webhook config","example":"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"}}},"examples":{"Replay by event ID":{"value":{"event_id":"evt_abc123"}},"Replay by source UID":{"value":{"source_uid":"message-uid-xyz"}}}}}},"responses":{"200":{"description":"Event re-queued for delivery","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"event_id":{"type":"string","description":"Event ID that was replayed","example":"evt_abc123"},"status":{"type":"string","enum":["enqueued"],"description":"Status of the replay request","example":"enqueued"},"message":{"type":"string","description":"Human-readable message","example":"Event re-queued for delivery"}}}}}},"400":{"description":"Bad request - Invalid input","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Either event_id or source_uid is required"}}}}}},"401":{"description":"Unauthorized - User not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"User authentication not found"}}}}}},"404":{"description":"Event not found","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Event not found"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Failed to replay webhook event"}}}}}}}}}}}