Compliance
Veil Mail enforces email compliance requirements automatically. This guide covers what's handled for you and what you need to configure.
Email Types
Veil Mail classifies emails as either transactional or marketing. Different compliance rules apply to each type.
| Feature | Transactional | Marketing |
|---|---|---|
| Unsubscribe header | Optional | Automatic |
| Unsubscribe footer | Optional | Automatic |
| Physical address | Not required | Required |
| Suppression check | Enforced | Enforced |
| Consent required | Existing relationship | Express opt-in |
// Send a marketing email (compliance features auto-applied)
const email = await client.emails.send({
from: 'news@yourdomain.com',
to: 'subscriber@example.com',
subject: 'Monthly Newsletter',
html: '<h1>Our latest updates</h1>',
type: 'marketing',
});
// Transactional email (default, no compliance overhead)
const receipt = await client.emails.send({
from: 'orders@yourdomain.com',
to: 'customer@example.com',
subject: 'Order Confirmation #1234',
html: '<h1>Your order is confirmed</h1>',
type: 'transactional', // or omit (default)
});CAN-SPAM Compliance
The CAN-SPAM Act requires commercial emails to include specific elements. Veil Mail handles most of these automatically.
What Veil Mail Handles
- List-Unsubscribe headers - Automatically added to marketing emails (RFC 2369 and RFC 8058)
- Unsubscribe footer - Added to the bottom of marketing emails with a one-click unsubscribe link
- Suppression management - Bounced, unsubscribed, and complained recipients are automatically blocked
- One-click unsubscribe - RFC 8058 compliant endpoint for email client unsubscribe buttons
- Branded unsubscribe pages - Unsubscribe and email preference pages automatically use your organization's Brand Kit (logo, colors, fonts, company name). Configure branding in Settings > Brand Kit and preview at Settings > Unsubscribe.
- Topic-based preferences - When Topics are configured, recipients see a branded preferences page to manage individual subscriptions instead of a blanket unsubscribe.
What You Need to Configure
- Physical mailing address - Required for marketing emails. Configure in Settings > General.
- Accurate sender information - Use a valid "from" address that identifies your business.
- Non-deceptive subject lines - Subject lines must accurately reflect the email content.
CASL Compliance
Canada's Anti-Spam Legislation (CASL) requires consent before sending commercial electronic messages to Canadian recipients. Veil Mail supports two consent types:
Express Consent
Recipient explicitly opted in to receive emails. Does not expire. Required for ongoing marketing communications.
Implied Consent
Based on an existing business relationship (e.g., purchase, inquiry). Expires after a set period (typically 2 years). Veil Mail automatically stops sending when consent expires.
// Add a subscriber with express consent
await client.audiences.subscribers('audience_id').add({
email: 'user@example.com',
firstName: 'John',
consentType: 'express',
consentSource: 'signup form',
consentDate: '2025-01-15T00:00:00Z',
consentProof: 'form-submission-abc123',
});
// Add a subscriber with implied consent (expires in 2 years)
await client.audiences.subscribers('audience_id').add({
email: 'customer@example.com',
firstName: 'Jane',
consentType: 'implied',
consentSource: 'product purchase',
consentDate: '2025-01-15T00:00:00Z',
consentExpiresAt: '2027-01-15T00:00:00Z',
});Google & Yahoo Bulk Sender Requirements
As of February 2024, Google and Yahoo require bulk senders (5,000+ messages/day) to meet specific authentication and compliance requirements.
Email Authentication (SPF, DKIM)
Veil Mail automatically configures SPF and DKIM when you verify your domain.
List-Unsubscribe Header
Automatically added to all marketing emails and campaigns.
One-Click Unsubscribe
RFC 8058 compliant List-Unsubscribe-Post header is included automatically.
DMARC Record (Your Responsibility)
You must set up a DMARC DNS record for your domain. See the Domains documentation for details.
Spam Rate Below 0.3%
Veil Mail tracks complaint rates and will alert you if you approach the threshold. Maintain clean lists and send relevant content to keep rates low.
Suppression Management
Veil Mail maintains a suppression list per organization. Emails to suppressed addresses are blocked before sending.
Automatic Suppression
Recipients are automatically added to your suppression list when:
- An email hard bounces (invalid address)
- A recipient marks your email as spam (complaint)
- A recipient clicks the unsubscribe link
- A recipient uses their email client's one-click unsubscribe
Pre-Send Check
The send email endpoint returns a 422 error with code recipient_suppressed if any recipient is on the suppression list. Use the suppression check endpoint to pre-filter recipients:
// Check before sending
const response = await fetch('https://api.veilmail.xyz/v1/suppressions/check', {
method: 'POST',
headers: {
'Authorization': 'Bearer veil_live_xxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
emails: ['user1@example.com', 'user2@example.com'],
}),
});Physical Address
CAN-SPAM requires a valid physical postal address in all commercial emails. Configure your address in the dashboard under Settings > General. The address appears in the footer of all marketing emails.
Required for Marketing Emails
Attempts to send marketing emails without a physical address configured will return a 422 error with code physical_address_required.
Bounce & Complaint Rate Thresholds
Maintaining low bounce and complaint rates is critical for email deliverability.
| Metric | Target | Action |
|---|---|---|
| Hard bounce rate | < 2% | Auto-suppressed on first bounce |
| Complaint rate | < 0.1% | Dashboard warnings at 0.08% |
| Soft bounce rate | < 5% | Auto-suppressed after 3 within 7 days |
SOC 2 Type II Controls
Veil Mail provides infrastructure-level controls to support SOC 2 Type II certification. These features cover audit logging, security monitoring, data retention, and API key governance.
Audit Logging
Every mutation in the Veil Mail API is recorded in an immutable audit log. Audit entries capture who performed the action, what changed, from where, and whether it succeeded or failed.
What Gets Logged
All POST, PUT, PATCH, and DELETE requests are automatically logged. Each entry includes:
| Field | Description |
|---|---|
| actorType | Who performed the action: user, api_key, system, or admin |
| action | Action in resource.verb format, e.g., email.send, api_key.create |
| status | success, failure, or denied |
| ipAddress | Source IP of the request |
| metadata | Additional context (HTTP method, path, sanitized request body) |
Auditable Actions
Authentication
- api_key.create
- api_key.revoke
- api_key.roll
- email.send
- email.cancel
- email.send_batch
Templates
- template.create
- template.update
- template.delete
Domains
- domain.create
- domain.verify
- domain.delete
Audiences
- audience.create
- audience.delete
- subscriber.import
Settings
- organization.update
- brand_kit.update
- retention.update
Querying Audit Logs
Use the SDK or REST API to query audit logs with filters for actor, action, resource, status, and date range.
// Query audit logs for the last 7 days
const { data, hasMore, total } = await client.auditLogs.list({
from: '2025-01-24T00:00:00Z',
to: '2025-01-31T23:59:59Z',
action: 'api_key.create',
limit: 50,
});
// Get a specific audit log entry
const entry = await client.auditLogs.get('cuid_xxxxx');
console.log(entry.action); // "api_key.create"
console.log(entry.actorType); // "api_key"
console.log(entry.status); // "success"Exporting Audit Logs
Export audit logs as CSV or JSON for compliance reporting. Use the GET /v1/audit-logs/export endpoint with optional date range and format parameters.
curl -H "Authorization: Bearer veil_live_xxxxx" \
"https://api.veilmail.xyz/v1/audit-logs/export?from=2025-01-01T00:00:00Z&to=2025-01-31T23:59:59Z&format=csv" \
-o audit-logs-january.csvSecurity Controls
Built-in security controls monitor for suspicious activity and generate compliance reports on demand.
Rate Limiting
All API endpoints are rate limited to prevent abuse. Limits vary by operation type:
| Operation | Limit | Window |
|---|---|---|
| Read operations | 200 requests | 1 minute |
| Email sending | 30 requests | 1 minute |
| API key operations | 10 requests | 1 hour |
| Domain verification | 10 requests | 1 hour |
| Audit log export | 10 requests | 1 hour |
Suspicious Activity Detection
The platform monitors for patterns that may indicate a security incident:
- Brute force detection - More than 10 authentication failures in 15 minutes from the same organization triggers an alert
- High-frequency key creation - Creating 5+ API keys within an hour is flagged as suspicious
- Unusual IP patterns - High-privilege actions (key management, domain deletion, org settings) from a previously unseen IP are flagged
Sensitive Data Masking
All audit log metadata is automatically sanitized before storage. API keys, tokens, passwords, and other secrets are replaced with [REDACTED]. This ensures audit logs themselves do not become a security liability.
Data Retention Policies
Configure per-organization data retention policies to comply with your data governance requirements. Retention periods are enforced automatically, and you can trigger manual enforcement at any time.
| Data Type | Default | Minimum | Maximum |
|---|---|---|---|
| Email events | 90 days | 30 days | 730 days (2 years) |
| Audit logs | 365 days | 90 days | 2,555 days (7 years) |
| API request logs | 30 days | 7 days | 365 days |
| Inbound emails | 30 days | 7 days | 365 days |
// Get the current retention policy
const policy = await client.auditLogs.getRetentionPolicy();
console.log(policy.auditLogRetentionDays); // 365
// Update retention periods
const updated = await client.auditLogs.updateRetentionPolicy({
auditLogRetentionDays: 730, // Keep audit logs for 2 years
apiLogRetentionDays: 60, // Keep API logs for 60 days
});API Key Governance
API keys are the primary authentication mechanism for the Veil Mail API. Proper key management is essential for SOC 2 compliance.
Scoped Access
API keys can be scoped to specific permissions. Follow the principle of least privilege by granting only the scopes each integration needs:
email:sendSend emails onlyemail:readRead email status and eventsdomain:readList and check domain statustemplate:writeCreate and modify templatesaudit:readRead audit logs and reportsaudit:writeManage retention policiesKey Lifecycle
- Creation audit trail - Every key creation is logged with the creator's identity and granted scopes
- Usage tracking - Last-used timestamps and total usage counts are tracked per key
- Expiration support - Set an expiration date when creating keys. Expired keys are automatically rejected
- Key rolling - Roll a key to generate a new secret while preserving the key ID and configuration. The old key remains valid for a brief overlap window
- Revocation - Immediately revoke a compromised key. Revoked keys are never deleted, maintaining a complete audit trail
Compliance Reports
Generate on-demand security reports that summarize your organization's security posture. Reports include API key inventory, recent failures, high-privilege actions, and data access patterns.
// Generate a security compliance report
const report = await client.auditLogs.getSecurityReport();
// API Key Inventory
console.log('Active keys:', report.apiKeyInventory.active);
console.log('Revoked keys:', report.apiKeyInventory.revoked);
console.log('Never-used keys:', report.apiKeyInventory.neverUsed);
// Recent Auth Failures (last 7 days)
console.log('Auth failures:', report.recentAuthFailures.count);
for (const failure of report.recentAuthFailures.entries) {
console.log(` ${failure.action} from ${failure.ipAddress}: ${failure.reason}`);
}
// High-Privilege Actions (last 30 days)
console.log('High-privilege actions:', report.highPrivilegeActions.count);
// Data Access Patterns (last 30 days)
console.log('Total API calls:', report.dataAccessPatterns.totalApiCalls);
console.log('Unique IPs:', report.dataAccessPatterns.uniqueIps);SOC 2 Readiness Checklist
The following checklist maps Veil Mail's controls to SOC 2 Trust Services Criteria. Items marked with a checkmark are handled by the platform. Items with a warning triangle require action from your team.
CC6.1 — Logical Access Controls
- Scoped API key authentication with least-privilege support
- Key expiration and revocation controls
- Rate limiting on all API endpoints
- Periodically review and rotate API keys (your responsibility)
CC7.2 — System Monitoring
- Comprehensive audit logging of all mutations
- Suspicious activity detection (brute force, unusual IPs)
- On-demand security reports
- Set up alerting for suspicious activity events (your responsibility)
CC6.5 — Data Retention and Disposal
- Configurable retention policies per organization
- Enforced minimum retention for audit logs (90 days)
- Automated data deletion based on retention policy
- Configure retention policies appropriate for your industry (your responsibility)
CC8.1 — Change Management
- All configuration changes logged (domain, webhook, template changes)
- Sensitive data masked in audit metadata
- CSV/JSON export for external audit tools
PI1.1 — PII Protection
- PII scanning via Google Cloud DLP before email delivery
- API keys and tokens redacted in all log output
- Bearer token format prevents key exposure in URL parameters