Security
How SayMaya protects account data. We list what we do, not certifications we do not hold.
What we do
Controls that are in the product today.
Tenant isolation in the database
Account data lives in Postgres tables protected by row-level security. Tenant queries made by the app run as the signed-in account and cannot read another account's rows. Server-side admin and service code bypasses these policies and is restricted by application checks instead.
Encryption in transit
Traffic is encrypted with HTTPS and the site asks browsers to always use it.
API keys stored as hashes
We keep a SHA-256 hash of each API key, not the key. A key is shown once when you create it.
Roles
Access inside an account is role based: owner, admin, member or guest.
Audit log
Security-relevant account changes are written to an audit log.
Rate limiting
Sign-in, checkout, invites, data exports, the contact form and API requests are rate limited.
Browser protections
Pages are served with a Content Security Policy and clickjacking protection.
Card data stays with the payment provider
When billing is on, card numbers are entered on the payment provider's hosted checkout. They never reach our servers or database.
Who processes data
Providers that handle account data for the core product.
Vercel
Application hosting, content delivery and scheduled jobs
Neon
Database hosting and sign-in
Upstash
Caching, rate limiting and background jobs
Stripe
Payment processing and billing, when Stripe billing is turned on
Sentry
Error monitoring, when a Sentry DSN is configured
Mail API
Transactional email through a Plunk-compatible API (configured with MAIL_API_URL)
Optional features add their own providers when they are turned on. The complete list is in the sub-processor list.
Questions and reports
Security review for procurement, or a problem you found.
Need a security questionnaire completed? Tell us what you need and we will reply by email.
To report a vulnerability, email hello@saymaya.com. Include the page or endpoint and the steps to reproduce it.