Linear
Create and sync Linear issues from Nebutra events — quota exceeded, errors, and deployment failures.
Overview
The Linear integration lets you automatically create and update Linear issues when things happen in your Nebutra organization:
- Create a bug report when a Sentry error is captured
- Create a task when a tenant exceeds their quota
- Sync deployment status to a Linear project
Step 1: Get a Linear API key
- Go to Linear → Settings → API → Create Key
- Name it "Nebutra Integration"
- Copy the API key
Step 2: Configure environment variables
LINEAR_API_KEY=lin_api_xxxxxxxxxxxxxxxxxxxx
LINEAR_TEAM_ID=your_team_id # From Linear → Settings → Teams
LINEAR_PROJECT_ID=your_project_id # Optional: default project for issuesStep 3: Register the integration
In Settings → Integrations → Linear → Connect, or via API:
await nebutra.integrations.linear.configure({
orgId: "org_123",
teamId: process.env.LINEAR_TEAM_ID!,
projectId: process.env.LINEAR_PROJECT_ID,
events: ["quota.exceeded", "deployment.failed"],
});Step 4: Create issues programmatically
import { LinearClient } from "@linear/sdk";
const linear = new LinearClient({ apiKey: process.env.LINEAR_API_KEY! });
// Create an issue when quota is exceeded
async function handleQuotaExceeded(event: QuotaExceededEvent) {
await linear.createIssue({
teamId: process.env.LINEAR_TEAM_ID!,
title: `Quota exceeded: ${event.orgName} (${event.metric})`,
description: [
`**Organization:** ${event.orgName}`,
`**Metric:** ${event.metric}`,
`**Limit:** ${event.limit}`,
`**Used:** ${event.used}`,
`**Plan:** ${event.plan}`,
"",
`This tenant has exceeded their ${event.metric} quota.`,
`Consider reaching out to offer an upgrade.`,
].join("\n"),
priority: 2, // High
labelIds: ["label_quota_exceeded"],
});
}Webhook handler
import crypto from "crypto";
export async function POST(req: Request) {
const body = await req.text();
const sig = req.headers.get("linear-signature");
// Verify Linear signature
const hash = crypto
.createHmac("sha256", process.env.LINEAR_WEBHOOK_SECRET!)
.update(body)
.digest("hex");
if (sig !== hash) {
return new Response("Invalid signature", { status: 400 });
}
const payload = JSON.parse(body);
// Handle issue status changes — update Nebutra state
if (payload.type === "Issue" && payload.action === "update") {
if (payload.data.state?.name === "Done") {
await handleIssueClosed(payload.data);
}
}
return new Response("OK", { status: 200 });
}Common automation patterns
| Trigger | Linear action |
|---|---|
quota.exceeded | Create high-priority issue → assign to success team |
error.spike | Create bug report → link to Sentry event |
member.joined (enterprise) | Create onboarding checklist issue |
invoice.payment_failed | Create issue → assign to billing team |
Related
How is this guide?
Edit on GitHub
Last updated on