Package Exports
- @keystrokehq/sendgrid
- @keystrokehq/sendgrid/_official
- @keystrokehq/sendgrid/_runtime
- @keystrokehq/sendgrid/alerts
- @keystrokehq/sendgrid/api-keys
- @keystrokehq/sendgrid/client
- @keystrokehq/sendgrid/connection
- @keystrokehq/sendgrid/domains
- @keystrokehq/sendgrid/email-validation
- @keystrokehq/sendgrid/events
- @keystrokehq/sendgrid/mail-send
- @keystrokehq/sendgrid/marketing-contacts
- @keystrokehq/sendgrid/marketing-customfields
- @keystrokehq/sendgrid/marketing-lists
- @keystrokehq/sendgrid/marketing-segments
- @keystrokehq/sendgrid/marketing-singlesends
- @keystrokehq/sendgrid/schemas
- @keystrokehq/sendgrid/sender-identities
- @keystrokehq/sendgrid/senders
- @keystrokehq/sendgrid/stats
- @keystrokehq/sendgrid/suppressions
- @keystrokehq/sendgrid/templates
- @keystrokehq/sendgrid/user-account
- @keystrokehq/sendgrid/verification
- @keystrokehq/sendgrid/webhooks/event
- @keystrokehq/sendgrid/webhooks/parse
Readme
@keystrokehq/sendgrid
Official Keystroke integration for SendGrid (Twilio) — transactional + marketing email, templates, contacts, lists, segments, suppressions, deliverability, and webhook helpers.
This package follows the standard Keystroke official integration authoring pattern. The root entrypoint is intentionally empty; use explicit subpaths.
Install
pnpm add @keystrokehq/sendgridConnect
SendGrid authenticates with a single API key. Create one in the SendGrid console (Settings → API Keys) — we recommend a Restricted Access key with only the scopes your workflows need.
import { sendgrid, type SendGridCredentials } from '@keystrokehq/sendgrid/connection';
const credentials: SendGridCredentials = {
SENDGRID_API_KEY: 'SG.xxx...',
// Optional:
SENDGRID_SUBUSER: 'acme-eu', // adds `on-behalf-of: acme-eu` header
SENDGRID_ACCOUNT_REGION: 'eu', // default: 'global'
SENDGRID_EVENT_WEBHOOK_PUBLIC_KEY: '-----BEGIN PUBLIC KEY-----\n…\n-----END PUBLIC KEY-----',
SENDGRID_INBOUND_PARSE_TOKEN: 'token-abc',
};
void credentials;
void sendgrid;Fields
| Field | Required | Purpose |
|---|---|---|
SENDGRID_API_KEY |
yes | Full or restricted API key. Must start with SG.. |
SENDGRID_SUBUSER |
no | Username of a subuser; sent as on-behalf-of on every request. |
SENDGRID_ACCOUNT_REGION |
no | global (default) or eu. Controls the base URL (api.sendgrid.com vs api.eu.sendgrid.com). |
SENDGRID_EVENT_WEBHOOK_PUBLIC_KEY |
no | Ed25519 public key for verifying Event Webhook deliveries. Fetch with getSignedPublicKey, store when enabling signing. |
SENDGRID_INBOUND_PARSE_TOKEN |
no | Keystroke-minted shared secret embedded in the Inbound Parse receiver URL. |
Quickstart
import { sendEmail } from '@keystrokehq/sendgrid/mail-send';
void sendEmail;import { triggers } from '@keystrokehq/sendgrid/triggers';
const onBounce = triggers.bounce({
name: 'escalate-hard-bounces',
filter: (event) => event.type === 'hard',
transform: (event) => ({ email: event.email, reason: event.reason }),
});
void onBounce;Public surface
End-user authoring imports
| Import path | Exports |
|---|---|
@keystrokehq/sendgrid/mail-send |
sendEmail, createBatchId, validateBatchId, cancelOrPauseScheduledSend, updateScheduledSend, deleteScheduledSend, listScheduledSends, getScheduledSend |
@keystrokehq/sendgrid/templates |
Transactional templates + versions CRUD + activate |
@keystrokehq/sendgrid/marketing-contacts |
Marketing Contacts v3: upsert, search, batch, count, imports, exports, field definitions |
@keystrokehq/sendgrid/marketing-lists |
Marketing Lists v3 CRUD + contact count + remove-contacts |
@keystrokehq/sendgrid/marketing-segments |
Marketing Segments v2 CRUD + refresh + parent-filter |
@keystrokehq/sendgrid/marketing-singlesends |
Single Sends CRUD + schedule + stats + test sends |
@keystrokehq/sendgrid/marketing-customfields |
Marketing custom field definition CRUD |
@keystrokehq/sendgrid/senders |
Marketing senders CRUD |
@keystrokehq/sendgrid/sender-identities |
Verified sender identity CRUD + resend |
@keystrokehq/sendgrid/suppressions |
Global suppressions, groups, bounces, blocks, invalid emails, spam reports |
@keystrokehq/sendgrid/email-validation |
Single + bulk email validation (add-on gated) |
@keystrokehq/sendgrid/stats |
Global, category, automation, mailbox-provider stats + engagement-quality scores |
@keystrokehq/sendgrid/user-account |
Profile, account info, scopes, credit balance |
@keystrokehq/sendgrid/alerts |
Alert CRUD |
@keystrokehq/sendgrid/domains |
Authenticated domain read + validate |
@keystrokehq/sendgrid/api-keys |
API key CRUD |
@keystrokehq/sendgrid/webhooks/event |
Event Webhook configuration, signed-key fetch, signature toggle, test |
@keystrokehq/sendgrid/webhooks/parse |
Inbound Parse configuration + stats |
@keystrokehq/sendgrid/triggers |
12 direct-binding webhook helpers |
Support imports
| Import path | Exports |
|---|---|
@keystrokehq/sendgrid/connection |
sendgrid credential set + SendGridCredentials type |
@keystrokehq/sendgrid/client |
createSendGridClient, SendGridError, isSendGridError |
@keystrokehq/sendgrid/schemas |
All Zod v4 schemas — input/output shapes for every resource |
@keystrokehq/sendgrid/events |
Event-name constants + per-event payload schemas |
@keystrokehq/sendgrid/verification |
verifySendGridEventWebhookRequest, verifyInboundParseRequest, parseSendGridEventWebhookBody |
Hidden repo-internal imports (do not use in end-user code)
@keystrokehq/sendgrid/_official@keystrokehq/sendgrid/_runtime
Sending email
import { sendEmail } from '@keystrokehq/sendgrid/mail-send';
void sendEmail;The Mail Send operation accepts the full v3 body: multiple personalizations, dynamic template substitution, attachments, categories, customArgs, sandbox mode, and sendAt for scheduled sends. Pass a batchId to later cancel or pause messages.
Marketing: contacts, lists, segments, single sends
import { upsertContacts } from '@keystrokehq/sendgrid/marketing-contacts';
import { createList } from '@keystrokehq/sendgrid/marketing-lists';
import { createSegment } from '@keystrokehq/sendgrid/marketing-segments';
import { createSingleSend, scheduleSingleSend } from '@keystrokehq/sendgrid/marketing-singlesends';
void upsertContacts;
void createList;
void createSegment;
void createSingleSend;
void scheduleSingleSend;Suppressions
One barrel export covers global, group, bounce, block, invalid, and spam suppressions:
import {
addGlobalSuppressions,
createSuppressionGroup,
listBounces,
deleteSpamReport,
} from '@keystrokehq/sendgrid/suppressions';
void addGlobalSuppressions;
void createSuppressionGroup;
void listBounces;
void deleteSpamReport;Webhooks
Event Webhook (signed, Ed25519)
Configure via the REST helpers, then verify deliveries with the verification helpers:
import {
createEventWebhook,
getSignedPublicKey,
toggleWebhookSignature,
} from '@keystrokehq/sendgrid/webhooks/event';
import { verifySendGridEventWebhookRequest } from '@keystrokehq/sendgrid/verification';
import { triggers } from '@keystrokehq/sendgrid/triggers';
void createEventWebhook;
void getSignedPublicKey;
void toggleWebhookSignature;
void verifySendGridEventWebhookRequest;
void triggers.delivered;
void triggers.open;
void triggers.groupUnsubscribe;IMPORTANT: SendGrid signs the concatenation of the X-Twilio-Email-Event-Webhook-Timestamp header value and the raw request body bytes. Your HTTP surface must preserve the raw body — do not JSON-reparse and re-serialize before verifying.
Inbound Parse
import { createParseSetting } from '@keystrokehq/sendgrid/webhooks/parse';
import { verifyInboundParseRequest } from '@keystrokehq/sendgrid/verification';
import { triggers } from '@keystrokehq/sendgrid/triggers';
void createParseSetting;
void verifyInboundParseRequest;
void triggers.inboundParseReceived;SendGrid does not sign Inbound Parse payloads. Verification uses a Keystroke-minted token embedded in the receiver URL (plus an optional IP allowlist). Rotate the token periodically.
Caveats
No OAuth. SendGrid v3 only supports API-key auth.
Apple Mail Privacy Protection.
openevents now carrysg_machine_open: truewhen the open is an Apple MPP cache-fetch. Filter on this flag or your workflows will trigger on every Apple Mail user.One-click unsubscribe (RFC 8058). Required by major inbox providers for bulk senders. Set
List-Unsubscribe-Post: List-Unsubscribe=One-Clickin yourheadersonsendEmail.Apple MPP + bounce classification.
bounceevents includebounce_classification— use it to distinguish reputation damage from mailbox-full soft bounces.Plan-gated endpoints.
stats.getEngagementQualityScoresrequires Pro+./messages(Email Activity add-on) and reseller endpoints also 402/403 on most tenants. The client surfaces these asSendGridErrorwithkind: 'forbidden'/'auth'.Region split. An API key scoped to
globalcannot act oneudata and vice versa. SetSENDGRID_ACCOUNT_REGIONcorrectly at connect time.Legacy
/contactdb/*, Legacy Marketing Campaigns, Designs API, Reverse DNS, IP pools, Subusers, Teammates, SSO, Mail/Tracking Settings. Not wrapped in phase 1. Fall back to the typed client for these:import { createSendGridClient } from '@keystrokehq/sendgrid/client'; void createSendGridClient;
Phase 1 coverage. This package ships ~150 operations focused on Mail Send, Templates, Marketing Contacts/Lists/Segments/Single Sends/CustomFields, Suppressions, Senders, Stats, Email Validation, User Account, Alerts, API Keys, Authenticated Domains, and the Event + Inbound Parse webhook config surface.
Verification helpers
verifySendGridEventWebhookRequest and verifyInboundParseRequest are pure functions — they accept { rawBody, signature, timestamp, publicKeyPem } (Event Webhook) or { path, expectedToken, sourceIp?, allowedIps? } (Inbound Parse) and return a boolean. They have no side effects and no I/O, so they are safe to call from any Keystroke runtime surface.
License
MIT © Keystroke