Skip to content

Subscription unsubscribe flows (single + all) #1785

Description

@davidgamez

Description

Users need to unsubscribe from notifications both from the logged-in account
screen and from a link in an email, with no end-user login required for the
email case. This issue covers the API work to support those flows, including
unsubscribing from a single subscription and from all of a user's subscriptions.

Design constraints:

  • The unsubscribe capability is keyed on the subscription ID
    (notification_subscription.id, a UUID) — the value embedded in email
    unsubscribe links. It is distinct from the user ID and the notification-type ID.
  • The email-link flow requires no end-user authentication: the subscription
    ID is the capability. The call is still made server-side by an authorized IAP
    principal (the API has no open-internet endpoints).
  • api.announcements is delivered via Brevo, so its opt-in state lives in three
    places that must stay in sync — the notification_subscription row, Brevo list
    membership, and app_user.is_registered_to_receive_api_announcements.
    Unsubscribing this type disables the row (never deletes it) and removes the
    Brevo contact.

Implementation

API spec

  • Add a scope query parameter (one default / all) to
    DELETE /v1/subscriptions/{id}.
  • Clarify the {id} path parameter across the subscription endpoints as the
    subscription ID (notification_subscription.id).

API implementation

api/src/user_service/impl/subscriptions_api_impl.py

  • Honor scope=all: resolve user_id from the given subscription, then
    unsubscribe the user from every type they hold — hard-delete normal types,
    route api.announcements through set_announcements_optin(subscribe=False).
  • scope=one (default) keeps the current single-subscription behavior.
  • Return 204 on success; 404 for an unknown subscription ID; 502 if Brevo
    is unreachable during an announcements update.

Email templates

  • api.announcements campaign: build the unsubscribe link from the contact's
    MDB_SUBSCRIPTION_ID attribute.
  • Transactional templates (api/src/shared/notifications/templates/*.j2): embed
    the subscription ID in the unsubscribe link.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions