Skip to content

Data inventory — ZevSend

Categories of data ZevSend holds. Field-by-field detail lives in the schema folder under zevsend-backend/src/common/database/schema/. This page is the DPO's overview — the schema is the source of truth for exact columns and types.

What we don't store

ZevSend does not store the customer's email, password, MFA secrets, or KYC data. Those live in ZevID. We address customers by their accountId (a UUID issued by ZevID) and read identity fields on demand via the ZevID internal API.

Identity references (not the identity itself)

Category What we hold Schema
Account pointer accountId (UUID issued by ZevID) on every team-membership / billing / audit row every owning table
ZevID enrollment sync Whether this account is enrolled in ZevSend + their tier — written into ZevID, not stored locally n/a (ZevID-owned)

Team + collaboration data

Category What we hold Schema
Team Team name, owner account id, billing currency, sandboxState (sandbox / live), suspension state, created / updated timestamps teams.ts
Team membership Per-account team membership + role team-members.ts
Team invitations Pending invites with expiry, invited-by account id, revocation state team-invites.ts
API keys SHA-256 hashes of plaintext, env (test / live), type (secret / publishable), optional scoped domain_id, prefix + last-four for display, revocation state api-keys.ts (hash only — plaintext shown once at creation)

Domain + sender-identity data

Category What we hold Schema
Domain Customer-owned domain name (name, nameNormalised), verification status, admin-review status, source (manual / zevcloud), carrier id (SES identity), carrier metadata, health-check counters (consecutiveFailures, firstFailedAt) domains.ts
Brand identity Brand name, legal entity, support email, support URL, submission + review timestamps; locked at admin approval columns on domains
DNS records the customer should publish JSONB mirror of carrier-emitted records (DKIM, custom MAIL FROM, SPF, DMARC) column on domains
Display-name applications Customer-registered alternate brand strings per domain — submitted display string, normalised form, justification, status, review note, public id (dn_…) domain-display-names.ts
Sender-ID applications (SMS) Customer-submitted SMS sender id requests — value, justification, country codes, status, review note, result sender-id pointer on approval sms-sender-id-applications.ts
Sender IDs (SMS) Approved + carrier-registered SMS sender values sms-sender-ids.ts
SMS carriers Admin-managed carrier registry + routing config sms-carriers.ts
WhatsApp carriers Admin-managed WhatsApp provider registry (Meta Cloud today) whatsapp-carriers.ts

Template data

Category What we hold Schema
Message templates Per-channel template (email / SMS / WhatsApp) — slug, name, description, subject (email), body, plaintext, declared customer.* + brand.* variables, locale, status, price message-templates.ts
Template price overrides Per-country price overrides on a template template-price-overrides.ts

Send / dispatch data (customer-controller, ZevSend-processor for body + recipient)

Category What we hold Schema
Email messages Per-send row — from, to, subject, html, plain-text, template id, api-key id, domain id, status, carrier message id, error message, sandbox flag, sent / created timestamps email-messages.ts
SMS messages Per-send row — from, to (phone, E.164), body, template id, api-key id, status, carrier id, carrier message id, error message, sandbox flag, sent / created timestamps sms-messages.ts
WhatsApp messages Per-send row — from (display + WABA template id), to (phone, E.164), template variables (positional), api-key id, status, carrier message id, error message, sandbox flag, sent / created timestamps whatsapp-messages.ts
Verifications OTP record — channel, recipient address / phone, hashed code only (plaintext never persisted), expiry, status, attempt count verifications.ts
Suppressions Per-team list of recipient addresses to refuse sends to — recipient, reason (hard_bounce / complaint / manual), source (carrier / manual), detail, carrier event id suppressions.ts
Verified recipients (sandbox only) Per-team allowlist of recipients sandbox teams may dispatch to before going live — recipient, verification token, verified-at timestamp verified-recipients.ts

Webhook + integration data

Category What we hold Schema
Webhook subscriptions Per-team webhook target — URL, subscribed events, HMAC signing secret, active flag, failure-streak counter webhooks.ts
Webhook deliveries BullMQ-backed delivery records (in Redis for active jobs; failure rows retained in queue for ops triage with a cap) n/a — Redis-resident

Billing data

Category What we hold Schema
Plan Sellable plans + their per-channel feature flags, price matrix, quotas (monthlyEmailQuota, dailyEmailQuota, domainsAllowed, teamMembersMax), monthlyCreditAllowanceMinor plans.ts
Subscription Recurring billing schedule, plan id, next-renewal date, scheduled-plan-change + effective-at subscriptions.ts + team-plan-schedule.ts
Invoice Header + line items + amount + status; total billed / paid invoices.ts + subscription-invoices.ts
Payment method Tokenised reference (ZevPay's token; no card numbers, BVN, or bank-account credentials stored by ZevSend) reference only — owned by ZevPay
Credits ledger ref Pointer into ZevID's Zev Credit balance (ZevID is the canonical ledger) n/a — read via ZevID API

Audit + admin

Category What we hold Schema
Admin audit log Every admin action against a customer resource (domain approve / reject, display-name approve / reject, sender-id approve / reject, plan change, suspend / reinstate, mark-paid) — actor admin id, target resource, before / after where relevant, metadata admin-actions.ts
ZPIP token + delivery audit Inbound consent + outbound webhook deliveries (token id, scopes, requester product, decision) shared ZPIP middleware

Platform-management data

Category What we hold Schema
Platform settings Admin-tunable runtime config — open-flag toggles (e.g. sms.custom_sender_id_applications_open), per-currency verify pricing maps (verify.sms.price_by_currency, etc.) platform-settings.ts

Special categories (NDPA Sensitive Personal Data)

Not applicable. ZevSend does not collect biometric, health, racial / ethnic, political, religious, sexual-orientation, or genetic data. KYC outcome (the one place biometric-derived data could land) is held by ZevID — see ZevID's data inventory.