Use Corsair’s webhookHooks to dispatch Trigger.dev tasks the moment an event fires. Trigger.dev handles retries, logging, and scheduling — Corsair handles webhook verification and integration auth.
Install
npm install @trigger.dev/sdk
Event trigger
When a PagerDuty incident is created, use before to skip low-severity alerts, and after to trigger a background task that creates a GitHub issue and pages the on-call team in Slack.
import { notifyOnCall } from '@/trigger/functions';
pagerduty({
webhookHooks: {
incident: {
incidentTriggered: {
before: async (ctx, payload) => {
// Only react to high-severity incidents
if (payload.incident.urgency !== 'high') {
throw new Error('Low severity, skipping');
}
return { ctx, payload };
},
after: async (ctx, result) => {
const incident = result.data.incident;
await notifyOnCall.trigger({
incidentId: incident.id,
title: incident.title,
htmlUrl: incident.html_url,
serviceId: incident.service.id,
tenantId: ctx.tenantId,
});
},
},
},
},
})
import { task } from '@trigger.dev/sdk/v3';
import { corsair } from '@/server/corsair';
export const notifyOnCall = task({
id: 'notify-on-call',
run: async (payload: {
incidentId: string;
title: string;
htmlUrl: string;
serviceId: string;
tenantId?: string;
}) => {
const client = payload.tenantId ? corsair.withTenant(payload.tenantId) : corsair;
// Create a GitHub issue to track the incident
const issue = await client.github.api.issues.create({
owner: process.env.GITHUB_ORG!,
repo: process.env.GITHUB_OPS_REPO!,
title: `[Incident] ${payload.title}`,
body: `PagerDuty incident: ${payload.htmlUrl}\n\nService ID: ${payload.serviceId}`,
labels: ['incident', 'high-severity'],
});
// Page the on-call channel in Slack
await client.slack.api.messages.post({
channel: 'C_ONCALL_CHANNEL',
text: `🚨 *High severity incident*: ${payload.title}\nPagerDuty: ${payload.htmlUrl}\nGitHub: ${issue.data.html_url}`,
});
},
});
Workflow
When a new HubSpot contact is created, run a multi-step task that enriches the contact, sends a personalized welcome email, and notifies the sales team in Slack.
import { onboardNewContact } from '@/trigger/functions';
hubspot({
webhookHooks: {
contacts: {
contactCreated: {
before: async (ctx, payload) => {
// Only process contacts with an email address
if (!payload.properties?.email) {
throw new Error('No email address, skipping');
}
return { ctx, payload };
},
after: async (ctx, result) => {
await onboardNewContact.trigger({
contactId: result.data.id,
email: result.data.properties.email,
firstName: result.data.properties.firstname ?? '',
company: result.data.properties.company ?? '',
tenantId: ctx.tenantId,
});
},
},
},
},
})
import { task, wait } from '@trigger.dev/sdk/v3';
import { corsair } from '@/server/corsair';
export const onboardNewContact = task({
id: 'onboard-new-contact',
run: async (payload: {
contactId: string;
email: string;
firstName: string;
company: string;
tenantId?: string;
}) => {
const client = payload.tenantId ? corsair.withTenant(payload.tenantId) : corsair;
// Step 1: Enrich the contact with company data
const companyData = await enrichCompany(payload.company); // your enrichment logic
await client.hubspot.api.contacts.update({
contactId: payload.contactId,
properties: {
industry: companyData.industry,
numberofemployees: companyData.headcount?.toString(),
},
});
// Step 2: Send a personalized welcome email
await client.resend.api.emails.send({
from: 'hello@yourapp.com',
to: payload.email,
subject: `Welcome${payload.firstName ? `, ${payload.firstName}` : ''}!`,
html: `<p>Thanks for signing up${payload.company ? ` from ${payload.company}` : ''}. Here's how to get started...</p>`,
});
// Step 3: Wait 5 minutes, then notify sales in Slack
await wait.for({ minutes: 5 });
await client.slack.api.messages.post({
channel: 'C_SALES_CHANNEL',
text: `New contact: *${payload.firstName || payload.email}*${payload.company ? ` from ${payload.company}` : ''}\nIndustry: ${companyData.industry ?? 'Unknown'}`,
});
},
});
Cron job
Every Friday at 5 PM, pull unresolved Sentry issues from Corsair’s database and post a weekly error report to Slack so the team can triage before the weekend.
import { schedules } from '@trigger.dev/sdk/v3';
import { corsair } from '@/server/corsair';
export const weeklyErrorReport = schedules.task({
id: 'weekly-error-report',
cron: '0 17 * * 5', // Every Friday at 5pm UTC
run: async () => {
// Query Corsair's synced Sentry database
const issues = await corsair.sentry.db.issues.list({
where: { status: 'unresolved' },
orderBy: { lastSeen: 'desc' },
limit: 10,
});
if (issues.length === 0) {
await corsair.slack.api.messages.post({
channel: 'C_ENG_CHANNEL',
text: '✅ No unresolved Sentry issues — great week!',
});
return;
}
const lines = [
`*Weekly Error Report — Top ${issues.length} unresolved issues*`,
'',
...issues.map(
(i, idx) =>
`${idx + 1}. *${i.title}* — ${i.count} events, last seen ${new Date(i.lastSeen).toLocaleDateString()}`,
),
'',
`_Triage before Monday_ 👆`,
];
await corsair.slack.api.messages.post({
channel: 'C_ENG_CHANNEL',
text: lines.join('\n'),
});
},
});
Register scheduled tasks in your Trigger.dev worker entry point. They’re automatically deployed and managed — no separate cron infrastructure needed.
What’s next
Inngest
Durable step functions triggered from Corsair webhooks.
Temporal
Start Temporal workflows from Corsair webhook events.
Hatchet
Event-driven workflows with Hatchet.
Workflows guide
Chain webhook events without a job queue.