Skip to content

Commit 5d59a60

Browse files
committed
feat(webhooks): add suppression webhooks
1 parent 6a2d0c7 commit 5d59a60

9 files changed

Lines changed: 28 additions & 24 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"esbuild": "0.28.1",
4747
"esbuild-wasm": "0.28.0",
4848
"picocolors": "1.1.1",
49-
"resend": "6.18.0"
49+
"resend": "6.18.1"
5050
},
5151
"pkg": {
5252
"scripts": [

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ allowBuilds:
22
esbuild: true
33
'@biomejs/biome': true
44
minimumReleaseAgeExclude:
5-
- resend@6.18.0
5+
- resend

src/commands/webhooks/create.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,13 @@ Events fire per-recipient: a batch email to 3 recipients generates 3 email.sent
3434
resend webhooks create --endpoint https://... --events email.sent,email.delivered
3535
resend webhooks create --endpoint https://... --events all
3636
37-
Available event types (17 total):
38-
Email: email.sent, email.delivered, email.delivery_delayed, email.bounced,
39-
email.complained, email.opened, email.clicked, email.failed,
40-
email.scheduled, email.suppressed, email.received
41-
Contact: contact.created, contact.updated, contact.deleted
42-
Domain: domain.created, domain.updated, domain.deleted
37+
Available event types (19 total):
38+
Email: email.sent, email.delivered, email.delivery_delayed, email.bounced,
39+
email.complained, email.opened, email.clicked, email.failed,
40+
email.scheduled, email.suppressed, email.received
41+
Contact: contact.created, contact.updated, contact.deleted
42+
Domain: domain.created, domain.updated, domain.deleted
43+
Suppression: suppression.added, suppression.removed
4344
4445
The signing_secret in the response is shown ONCE — save it immediately to verify
4546
webhook payloads using Svix signature headers (svix-id, svix-timestamp, svix-signature).

src/commands/webhooks/index.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ export const webhooksCommand = new Command('webhooks')
1515
context: `Webhooks let you receive real-time event notifications from Resend at an HTTPS endpoint.
1616
Payloads are signed with Svix headers for verification.
1717
18-
Event categories (17 total):
19-
Email: email.sent, email.delivered, email.delivery_delayed, email.bounced,
20-
email.complained, email.opened, email.clicked, email.failed,
21-
email.scheduled, email.suppressed, email.received
22-
Contact: contact.created, contact.updated, contact.deleted
23-
Domain: domain.created, domain.updated, domain.deleted
18+
Event categories (19 total):
19+
Email: email.sent, email.delivered, email.delivery_delayed, email.bounced,
20+
email.complained, email.opened, email.clicked, email.failed,
21+
email.scheduled, email.suppressed, email.received
22+
Contact: contact.created, contact.updated, contact.deleted
23+
Domain: domain.created, domain.updated, domain.deleted
24+
Suppression: suppression.added, suppression.removed
2425
2526
Signature verification (Svix):
2627
Each delivery includes headers: svix-id, svix-timestamp, svix-signature

src/commands/webhooks/listen.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ function summarizeEvent(body: Record<string, unknown>): {
4747
}
4848
} else if (type.startsWith('domain.')) {
4949
detail = safeTerminalText((data.name as string) ?? '');
50-
} else if (type.startsWith('contact.')) {
50+
} else if (type.startsWith('contact.') || type.startsWith('suppression.')) {
5151
detail = safeTerminalText((data.email as string) ?? '');
5252
}
5353

src/commands/webhooks/utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export const ALL_WEBHOOK_EVENTS: WebhookEvent[] = [
2020
'domain.created',
2121
'domain.updated',
2222
'domain.deleted',
23+
'suppression.added',
24+
'suppression.removed',
2325
];
2426

2527
export function normalizeEvents(raw: string[]): string[] {

tests/commands/webhooks/create.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ describe('webhooks create command', () => {
8383
expect(args.events).toEqual(['email.sent', 'email.bounced']);
8484
});
8585

86-
it('expands "all" shorthand to all 17 events', async () => {
86+
it('expands "all" shorthand to all 19 events', async () => {
8787
spies = setupOutputSpies();
8888

8989
const { createWebhookCommand } = await import(
@@ -95,7 +95,7 @@ describe('webhooks create command', () => {
9595
);
9696

9797
const args = mockCreate.mock.calls[0][0] as Record<string, unknown>;
98-
expect(args.events).toHaveLength(17);
98+
expect(args.events).toHaveLength(19);
9999
expect(args.events).toContain('email.sent');
100100
expect(args.events).toContain('contact.created');
101101
expect(args.events).toContain('domain.deleted');

tests/commands/webhooks/update.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ describe('webhooks update command', () => {
8383
expect(payload.events).toEqual(['email.sent', 'email.bounced']);
8484
});
8585

86-
it('expands "all" shorthand in --events to 17 events', async () => {
86+
it('expands "all" shorthand in --events to 19 events', async () => {
8787
spies = setupOutputSpies();
8888

8989
const { updateWebhookCommand } = await import(
@@ -94,7 +94,7 @@ describe('webhooks update command', () => {
9494
});
9595

9696
const payload = mockUpdate.mock.calls[0][1] as Record<string, unknown>;
97-
expect(payload.events).toHaveLength(17);
97+
expect(payload.events).toHaveLength(19);
9898
});
9999

100100
it('updates status with --status flag', async () => {

0 commit comments

Comments
 (0)