Newsletter signup
Capture email subscribers from your storefront. Signup is double opt-in:
your storefront submits the email, the platform emails a confirmation link, and
the subscriber becomes confirmed only after they click it. Examples reuse the
api() helper.
Subscribe (public)
POST /api/v1/public/newsletter/subscribe — tenant header, no auth (it's a
public capture, rate-limited per tenant).
await api("/public/newsletter/subscribe", {
method: "POST",
body: JSON.stringify({
email: "dana@example.com", // required, valid email — normalized to lowercase
source: "footer", // optional free-form capture-origin tag
}),
});
// → { ok: true }The response is always { ok: true } — it deliberately doesn't reveal
whether that email was new, already pending, or already confirmed (so the
endpoint can't be used to probe who's subscribed). A new email creates a
pending subscriber and triggers the confirmation email; submitting an
already-known email is an idempotent no-op (no duplicate, no second email
mid-flight).
The double opt-in flow
POST …/subscribe→ subscriber stored pending, confirmation email sent.- The email contains a confirm link —
GET …/public/newsletter/confirm?token=…. The subscriber clicks it and becomes confirmed. - Every email also carries a one-click unsubscribe link —
GET …/public/newsletter/unsubscribe?token=….
The confirm and unsubscribe links are tokenized targets the platform emails — they're not endpoints your storefront builds or calls. Your integration is just the
subscribePOST; the platform owns the confirmation + unsubscribe lifecycle (which is why those two routes aren't in the API reference).
Only confirmed subscribers are mailable, so a captured-but-unconfirmed email won't receive campaigns until the link is clicked.
Related
- Settings & onboarding — tenant profile the emails send under
- Abandoned cart recovery — the other storefront email-capture surface