Encryption in transit
All connections to the API, dashboard, and mail engine are encrypted with TLS 1.3. Unencrypted HTTP is permanently redirected. HSTS with a one-year max-age is enforced on all domains.
Encryption at rest
Postgres databases are encrypted at rest using AES-256. Channel credentials — Twilio tokens, FCM service accounts, Slack secrets, and similar — are additionally encrypted at the application layer using per-organisation key wrapping before storage. The raw credential JSON never exists in cleartext in the database.
Password security
Passwords are hashed with argon2id (memoryCost 19 MiB, timeCost 2, parallelism 1) — the strongest mainstream password hashing algorithm. Plaintext passwords are never logged or stored. New passwords are checked against the Have I Been Pwned k-anonymity API before acceptance.
API key design
API keys are generated with 32 bytes of cryptographic randomness (CSPRNG). Only a SHA-256 hash is stored — the plaintext key is shown exactly once at creation and is unrecoverable. Keys support fine-grained scopes, channel restrictions, IP allowlists, and expiry dates.
Session management
Sessions use iron-session v8 with a 256-bit encryption key. Session cookies are httpOnly, Secure, and SameSite=Lax. Sessions slide on activity with a 30-day maximum lifetime. Password reset invalidates all active sessions for that user immediately.
Multi-tenant isolation
Every database query on user-facing data is scoped to an Organisation ID resolved from the session or API key — never from request body parameters. Organisation boundaries are enforced at the middleware layer on every route.
Rate limiting
All authentication endpoints are rate-limited per IP using a Redis-backed sliding-window counter, independent of API rate limits. The API itself enforces per-organisation daily send limits with Redis counters that reset at midnight UTC — not rolling 24-hour windows that can be gamed.
Infrastructure
The API and mail engine run on dedicated EU servers. No shared cloud infrastructure with other customers. Your messages never pass through a third-party SMTP relay. Dedicated sending IPs per organisation on higher-tier plans.
Suppression list
Hard bounces and global unsubscribes are added to a permanent suppression list. Suppressed addresses can never be messaged through Senddio infrastructure regardless of what is in your list. This protects sender reputation and prevents accidental messaging of opted-out contacts.
Audit logging
Every organisation-level mutation — API key creation, domain changes, member additions, plan changes, webhook configuration — is written to an immutable audit log. Audit events include the acting user ID, IP address, user agent, and timestamp. Logs are retained per your plan window (30 days STARTER, 90 days PRO).
Webhook signatures
Every outbound webhook payload is signed with HMAC-SHA256 using a per-endpoint secret. The signature is sent in the Senddio-Signature header so your server can verify the payload has not been tampered with in transit.
Dependency management
Production dependencies are pinned to exact versions. The dependency tree is audited on every CI run with pnpm audit. Dependabot pull requests for security patches are reviewed and merged within 48 hours of publication.
Found a vulnerability?
We take security reports seriously and respond within 48 hours. If you discover a potential vulnerability we ask that you give us a reasonable time to fix it before public disclosure.
- A clear description of the vulnerability and its potential impact
- Steps to reproduce, including any relevant URLs or request payloads
- Your contact details so we can keep you updated
- We will acknowledge your report within 48 hours
- We will keep you informed of our progress
- We will not take legal action against researchers acting in good faith
- We will credit you in our changelog if you wish
Please do not use public issue trackers or social media to report security vulnerabilities.