Technical reference
The SendGrid plugin wraps SendGrid's Marketing Campaigns and Mail Send APIs behind a Brightspot-friendly extension point, SendGridTemplateProvider. Any asset that implements it can use the plugin's existing CMS tool pages, widget, caches, and permission model to create, update, schedule, send, test, and disconnect a SendGrid Single Send campaign, with no additional UI work. The plugin is split into an api module (the SendGridClient contract and its request/response data classes) and an api-impl module (a Retrofit-based implementation of that contract), so the SendGrid HTTP wiring can be swapped or mocked independently of the CMS integration.
Dependencies
com.psddev:cms-db,dari-db,dari-html,dari-util,dari-web—Brightspot CMS and Dari core libraries.com.brightspot.api-client:api-clientandcom.brightspot.api-client:retrofit—the shared internal frameworkSendGridApiConfigurationandSendGridClientbuild on for typed, cacheable API clients.com.squareup.retrofit2:retrofitandcom.squareup.okhttp3:okhttp—the HTTP client stack used by theapi-implmodule's implementation.com.fasterxml.jackson.core:jackson-annotations/jackson-databind—request/response serialization.com.github.ben-manes.caffeine:caffeine—backs the plugin's in-memory caches.
Installation
- Maven
- Gradle
- Gradle (Kotlin DSL)
<!-- Requires Brightspot 4.8 or later. -->
<dependency>
<groupId>com.brightspot.sendgrid</groupId>
<artifactId>sendgrid</artifactId>
<version>1.0.1</version>
</dependency>
// Requires Brightspot 4.8 or later.
implementation 'com.brightspot.sendgrid:sendgrid:1.0.1'
// Requires Brightspot 4.8 or later.
implementation("com.brightspot.sendgrid:sendgrid:1.0.1")
- Maven
- Gradle
- Gradle (Kotlin DSL)
<!-- Requires Brightspot 4.8 or later. -->
<dependency>
<groupId>com.brightspot.sendgrid</groupId>
<artifactId>api-impl</artifactId>
<version>1.0.1</version>
</dependency>
// Requires Brightspot 4.8 or later.
implementation 'com.brightspot.sendgrid:api-impl:1.0.1'
// Requires Brightspot 4.8 or later.
implementation("com.brightspot.sendgrid:api-impl:1.0.1")
The sendgrid artifact is the core CMS integration and pulls in the api module transitively. Add api-impl as well to get a working SendGridClient—it's the only implementation the plugin ships. Provide your own implementation of SendGridClient/SendGridApiConfiguration instead if you need different HTTP client behavior.
API reference
Extending an asset: SendGridTemplateProvider
An asset opts into SendGrid campaigns by implementing SendGridTemplateProvider.
| Method | Returns | Description |
|---|---|---|
getSendGridClient() | SendGridClient | The client to use for this content's campaigns. Defaults to null—override it to supply a client, typically built from the content's Site. |
getSendGridSubject() | String | The email subject line this content supplies. |
getSendGridPreheader() | String | The preheader text this content supplies. |
getSendGridHtmlContent() | String | The HTML content for the campaign. |
getSendGridPlainContent() | String | The plain text content for the campaign. |
getTemplateData() | SendGridTemplateData | The stored campaign association for this content. Looks one up by provider and returns a new, unsaved instance if none exists yet. |
SendGridTemplateData is the record that links a SendGridTemplateProvider to a SendGrid Single Send: singleSendId, singleSendName, status (draft, scheduled, or triggered), lastSyncDate, and lastActionDate.
1public SendGridClient getSendGridClient() {2Site site = as(Site.ObjectModification.class).getOwner();3SendGridSiteSettings settings = SiteSettings.get(site, s -> s.as(SendGridSiteSettings.class));4String apiKey = settings != null && settings.getSettings() != null5? settings.getSettings().getApiKey()6: null;78if (apiKey == null) {9return null;10}1112return new StandardSendGridClientConfiguration(site.getId(), apiKey, settings.getLastChanged().toInstant()).build();13}
SendGridClient
SendGridClient (package brightspot.sendgrid.api) is the contract every SendGrid API call goes through. All methods throw SendGridApiException on failure.
| Method | Parameters | Returns | Purpose |
|---|---|---|---|
getSenders(GetSendersRequest) | request | GetSendersResponse | List verified sender identities. |
getLists(GetListsRequest) | request (pageSize, pageToken) | GetListsResponse | List contact lists, cursor-paginated. |
getSegments() | — | GetSegmentsResponse | List all contact segments. |
createSingleSend(CreateSingleSendRequest) | request | CreateSingleSendResponse | Create a new Single Send campaign. |
getSingleSend(GetSingleSendRequest) | request (singleSendId) | GetSingleSendResponse | Get a Single Send campaign by ID. |
updateSingleSend(UpdateSingleSendRequest) | request | UpdateSingleSendResponse | Update an existing Single Send campaign. |
scheduleSingleSend(ScheduleSingleSendRequest) | request (singleSendId, sendAt) | ScheduleSingleSendResponse | Schedule a Single Send, or send it immediately with sendAt = "now". |
cancelScheduledSingleSend(CancelScheduledSingleSendRequest) | request (singleSendId) | void | Cancel a scheduled send and return the campaign to draft. |
sendMail(MailSendRequest) | request | void | Send a transactional email via POST /v3/mail/send. Used for test emails. |
getSuppressionGroups() | — | GetSuppressionGroupsResponse | List suppression (unsubscribe) groups. |
getSingleSendStats(GetSingleSendStatsRequest) | request (singleSendId) | GetSingleSendStatsResponse | Get delivery and engagement stats for a Single Send. |
isConfigured() (inherited from RetrofitApiClient) reports whether the client has a usable API key.
Data classes
Request and response types live in brightspot.sendgrid.api.data, grouped by the SendGridClient method they belong to:
| Method | Request | Response | Notable fields |
|---|---|---|---|
getSenders | GetSendersRequest | GetSendersResponse{results} | SenderData{id, nickname, from, replyTo, verified} |
getLists | GetListsRequest{pageSize, pageToken} | GetListsResponse{result, metadata} | ListData{id, name, contactCount} |
getSegments | — | GetSegmentsResponse{results} | SegmentData{id, name, contactsCount} |
createSingleSend | CreateSingleSendRequest{name, categories, sendTo, emailConfig} | CreateSingleSendResponse | Extends SingleSendData |
getSingleSend | GetSingleSendRequest{singleSendId} | GetSingleSendResponse | Extends SingleSendData |
updateSingleSend | UpdateSingleSendRequest{singleSendId, name, categories, sendTo, emailConfig} | UpdateSingleSendResponse | Extends SingleSendData |
scheduleSingleSend | ScheduleSingleSendRequest{singleSendId, sendAt} | ScheduleSingleSendResponse | sendAt is an ISO 8601 instant, or "now" |
cancelScheduledSingleSend | CancelScheduledSingleSendRequest{singleSendId} | void | — |
sendMail | MailSendRequest{personalizations, from, subject, content} | void | MailSendPersonalization{to}, MailSendContent{type, value} |
getSuppressionGroups | — | GetSuppressionGroupsResponse{groups} | SuppressionGroupData{id, name, description, isDefault} |
getSingleSendStats | GetSingleSendStatsRequest{singleSendId} | GetSingleSendStatsResponse{results} | SingleSendStatsResultData{id, stats}, where stats is a SingleSendStatsData{requests, delivered, opens, uniqueOpens, clicks, uniqueClicks, bounces} |
Shared embedded types: SingleSendData{id, name, status, sendAt, categories, emailConfig, sendTo}, SingleSendEmailConfig{subject, htmlContent, plainContent, senderId, suppressionGroupId}, SingleSendSendTo{listIds, segmentIds, all}.
On failure, StandardSendGridClient parses SendGrid's error body into ErrorResponse{errors: List<ErrorData>}, where each ErrorData has message, field, and help, and wraps it in a SendGridApiException with a message in the form SendGrid API Error [<status>]: <errors>.
Caches
The plugin caches read-heavy SendGrid data per SendGridClient to avoid exceeding SendGrid's rate limits.
| Cache | Caches | TTL |
|---|---|---|
SendGridListsCache | Contact lists | 10 minutes |
SendGridSegmentsCache | Contact segments | 10 minutes |
SendGridSendersCache | Sender identities | 10 minutes |
SendGridSuppressionGroupsCache | Suppression groups | 10 minutes |
SendGridSingleSendCache | A single campaign's live data and stats | 60 seconds |
SendGridListsCache, SendGridSegmentsCache, SendGridSendersCache, and SendGridSuppressionGroupsCache each expose an invalidate()/invalidate(client) method. SendGridSingleSendCache instead exposes invalidate(client, singleSendId), which tool pages that change a campaign's state (schedule, send, unschedule, update) call afterward so the widget reflects the change immediately instead of waiting out the 60-second TTL.
Tool pages and permissions
Every editorial action is a ToolPage subclass of AbstractSendGridToolPage, gated by its own @Permission:
| Permission ID | Tool page |
|---|---|
sendgrid/create-single-send | SendGridCreateSingleSendToolPage |
sendgrid/update-campaign | SendGridUpdateCampaignToolPage |
sendgrid/schedule-campaign | SendGridScheduleCampaignToolPage |
sendgrid/send-campaign | SendGridSendCampaignToolPage |
sendgrid/send-test-email | SendGridSendTestEmailToolPage |
sendgrid/unschedule-campaign | SendGridUnscheduleCampaignToolPage |
sendgrid/disconnect-campaign | SendGridDisconnectToolPage |
sendgrid/view-activity-log | SendGridViewActivityLogToolPage |
sendgrid/view-campaign-info | SendGridViewCampaignDetailsToolPage |
SendGridPermissions is the AdditionalPermission a role is configured with; its permissions field holds one of AllSendGridPermission, OnlySendGridPermission, or AllExceptSendGridPermission (all SendGridPermissionOption subtypes), each implementing hasPermission(String permissionId) against the sendgrid/ prefix.
Configuration
SendGridSiteSettings is a Modification<SiteSettings>, so it applies at both the Global level and the per-Site level, with null on a Site meaning "inherit from Global."
| Field | Type | Default | Effect |
|---|---|---|---|
enabled | Boolean | null | Whether the SendGrid widget and tool pages are active for the site. null on a Site inherits the Global value. |
settings | SendGridApiSettings | null | Embedded API settings; settings.apiKey is the account's SendGrid API key. |
defaultSubject | String | null | Fallback subject line used when a SendGridTemplateProvider doesn't supply its own. |
defaultPreheader | String | null | Fallback preheader text used when a SendGridTemplateProvider doesn't supply its own. |
categories | List<String> | empty | The pool of categories offered when creating a campaign. |
lastChanged | Date | — | Read-only; bumped in beforeCommit() whenever any tracked settings field changes. Used as the timestamp component of StandardSendGridClientConfiguration, so a settings change produces a distinct, cache-busting SendGridClient. |
onValidate() requires a non-blank API key—either local or, for a Site, inherited from Global—whenever enabled is true, and rejects duplicate categories.
StandardSendGridClientConfiguration(UUID ownerId, String apiKey, Instant timestamp) targets https://api.sendgrid.com and is keyed by ownerId and timestamp for equality—typically the Site ID and SendGridSiteSettings.getLastChanged(), respectively—so a SendGridClient built for a given site and settings version is stable and cacheable until those settings next change.