Email notifications
How portfolIQ sends emails — provider, templates, opt-out, and disclaimer policy.
Email notifications
portfolIQ sends transactional and notification emails for authentication, API key lifecycle, quota warnings, incident alerts, and billing events.
Provider
- Resend (resend.com) — EU region (Frankfurt), GDPR-compliant.
- From address:
noreply@portfoliq.io - Reply-to:
support@portfoliq.io - DKIM, SPF, and DMARC configured on
portfoliq.io.
Templates
Templates are React Email components rendered server-side in the Next.js BFF, then dispatched via Resend SDK.
| Template | Type | Trigger | Locales |
|---|---|---|---|
MagicLink | Transactional | Magic link auth | EN, FR |
ApiKeyCreated | Transactional | New API key created | EN, FR |
PasswordReset | Transactional | Password reset request | EN, FR |
QuotaWarning | Notification | API usage at 80%, 95%, 100% of monthly quota | EN, FR |
IncidentAlert | Notification | Incident posted on status page | EN, FR |
InvoicePaid | Billing | Stripe invoice.payment_succeeded | EN, FR |
InvoiceFailed | Billing | Stripe invoice.payment_failed | EN, FR |
Locale is detected at signup via the Accept-Language header and stored in your account settings. Override it anytime at /account/email-preferences.
Preferences and opt-out
Manage your email preferences at /account/email-preferences.
Four categories can be toggled independently:
- Product updates — feature releases and changelogs
- Newsletter — market context and data insights
- Promotions — plan offers and discounts
- Recommendations — signal digests (M9+)
Transactional emails cannot be opted out. Password reset, invoice receipts, and API key notifications are required for service delivery and are always sent regardless of preferences.
GDPR: opt-out requests are processed immediately and logged to api.email_unsubscribe_log for audit. One-click unsubscribe via HMAC-signed token (no login required) is included in every marketing and notification email.
Consent management
portfolIQ applies explicit opt-in for all marketing email categories (GDPR art. 7 / ePrivacy Directive).
Default state at signup
| Category | Default | Legal basis |
|---|---|---|
| Newsletter | Off | Explicit opt-in required |
| Promotions | Off | Explicit opt-in required |
| Product updates | On | Contract execution (art. 6.1.b) |
| Recommendations | On | Contract execution (art. 6.1.b) |
Marketing categories (newsletter, promotions) are never enabled by default — no pre-ticked boxes. A user who does not actively check the opt-in box at signup will have newsletter=FALSE and promotions=FALSE in their preferences row, with consent_marketing_at = NULL.
Consent record
When a user opts in at signup, the following is recorded in api.user_email_preferences:
| Column | Value |
|---|---|
newsletter | TRUE |
consent_marketing_at | timestamp of consent (UTC) |
consent_marketing_source | signup-form |
Accepted values for consent_marketing_source: signup-form, preference-page, support, import.
Revoking consent
The user can revoke marketing consent at any time via /account/email-preferences. Revocation is immediate, logged to api.email_unsubscribe_log, and irreversible from the platform side (the user must actively re-opt-in).
B2B note
For B2B API consumers (M12+ tiers), the legal basis for product_updates and recommendations may shift to legitimate interest (art. 6.1.f) once personalisation features are active. This will be re-evaluated at M9 with expert-legal.
Financial disclaimer policy
Per AMF methodology disclosure requirements, emails that may reference market data carry a footer:
Not financial advice. Methodology disclosed. See /docs/core-concepts/methodology for sources and limitations.
| Template | Disclaimer |
|---|---|
MagicLink | Yes |
ApiKeyCreated | Yes |
QuotaWarning | Yes |
IncidentAlert | Yes |
PasswordReset | No |
InvoicePaid | No |
InvoiceFailed | No |
Deliverability
- Transactional emails: typical delivery under 5 seconds.
- Hard bounce or spam complaint:
users.email_statusis updated automatically — no further sends to that address. - Deliverability issues: contact
support@portfoliq.io.
Architecture
Python service (api/services/email.py)
│
│ POST /api/internal/email/send (X-Internal-Token, Docker network only)
▼
Next.js BFF (web/app/api/internal/email/send/route.ts)
│ ① Renders React Email template (HTML + plain text)
│ ② Calls Resend SDK with idempotency key
│ ③ Logs to api.email_log
▼
Resend → recipient
│
│ Webhook on bounce / complaint / delivered
▼
Next.js POST /api/webhooks/resend (Svix signature verification)
│ Updates email_log.status + users.email_status + email_unsubscribe_log
See also
- Authentication — magic link flow
- Rate limits — quota thresholds that trigger
QuotaWarning - Methodology — data sourcing and disclaimer context
Not financial advice. Methodology disclosed.