Extra and Special Lists
Purpose of this integration
This integration introduces server-side logic and APIs that:
- discover SendGrid suppression groups and classify them as extra or special;
- normalize and map those groups into a consistent representation including
name,locale,idand, when available for special,list_id; - expose endpoints to read available lists and segments and to read/update a contact's subscription state;
- apply deterministic subscribe/unsubscribe semantics using the existing SendGrid suppression groups API.
High-level API behaviour
OpenAPI defines the exact shapes and parameters; here we describe the runtime behaviour and selection rules implemented by the service. The APIs provide operations to:
- list suppression groups filtered and mapped as extra or special;
- read and update subscription state for extra and special by
emailandlocale.
tip
Full api is described in the OpenAPI spec
Selection and normalization rules
Suppression groups retrieved from SendGrid are filtered and normalized according to naming conventions:
- Extra groups: names that start with the prefix
EXTRA-<LOCALE>-(prefix match is case-sensitive). - Special groups: names that start with the prefix
SPECIAL-<LOCALE>-. - The two-letter
LOCALEtoken immediately after the prefix is extracted and normalized (for exampleen,fr) and assigned to thelocalefield. - The remainder of the group name, after trimming, is returned as the human-facing
name. - Any suppression group that does not match these patterns is ignored and not exposed by the APIs.
This approach makes it explicit which SendGrid groups are managed by the application and reduces noise from non-conforming groups.
Mapping special groups to SendGrid lists
For special groups the service attempts a best-effort mapping to SendGrid mailing lists:
- Both suppression groups and lists are fetched from the SendGrid API.
- For each
SPECIAL-<LOCALE>-...group the service looks for a list with a matching normalized name. - When a match is found, the list's identifier is attached as
list_id(SendGrid list IDs are strings). - If no matching list is found the suppression group is still returned without
list_idand a warning is logged with context (locale,group_id,group_name).
This enables campaign UIs to use list_id when available and to degrade gracefully when mapping is missing.
Subscribe / unsubscribe semantics
Subscription updates are reconciled deterministically:
- The client provides a collection of items with
group_idand a booleansubscribed. - For each item:
subscribed: true- the service invokesSendgrid::API.suppress!(email, group_id).subscribed: false- the service invokesSendgrid::API.unsuppress!(email, group_id).
- The service returns the post-sync state for each input item so the caller can present the effective result.
- The choice to use
suppress!forsubscribed: truefollows established conventions in the codebase and is covered by service and integration tests.
Visibility rules
- Requests for extra lists return all known extra lists for the requested locale together with the contact's current subscription state.
- Requests for special lists return only those special lists to which the contact is currently subscribed or was previously subscribed (including historical unsubscriptions). This avoids users that never subscribed to a special list seeing it.
Logging, resilience and error handling
- When a special group cannot be mapped to any SendGrid list, the service logs a warning with
locale,group_idandgroup_nameto help operators detect configuration drift. - Interactions with SendGrid are encapsulated in a service layer; retries, error handling and logging follow the project's existing policies and are covered by VCR-backed integration tests.
Operational notes
- Ensure SendGrid suppression group names follow the
EXTRA-<LOCALE>-...orSPECIAL-<LOCALE>-...pattern for discovery by the service. - Renaming groups on SendGrid can break mappings; expect warnings and missing
list_idvalues if names diverge. - The API provides a stable representation to let frontends list options and apply bulk updates safely.