DEV Community

Alex Spinov
Alex Spinov

Posted on

Linear Has a Free API — Here's How to Build Custom Project Management Workflows

An engineering lead told me his team spent 2 hours every Monday manually creating sprint issues from a spreadsheet. He wrote a 50-line script with Linear's API — now it takes 0 seconds and happens automatically every Monday at 9 AM.

What Linear Offers for Free

Linear free tier:

  • Unlimited members and unlimited issues
  • GraphQL API with full access
  • Webhooks for real-time notifications
  • GitHub, GitLab, Slack integrations
  • Cycles (sprints) and projects
  • Custom views and filters
  • OAuth for third-party apps

Quick Start

# Get your API key from Linear > Settings > API
export LINEAR_API_KEY='lin_api_YOUR_KEY'

# Test the connection
curl 'https://api.linear.app/graphql' \
  -H 'Authorization: lin_api_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"query": "{ viewer { id name email } }"}'
Enter fullscreen mode Exit fullscreen mode

GraphQL Queries

const { LinearClient } = require('@linear/sdk');

const linear = new LinearClient({ apiKey: process.env.LINEAR_API_KEY });

// Get all teams
const teams = await linear.teams();
teams.nodes.forEach(t => console.log(`${t.name}: ${t.key}`));

// Get issues assigned to me
const me = await linear.viewer;
const myIssues = await me.assignedIssues({
  filter: { state: { type: { in: ['started', 'unstarted'] } } },
  orderBy: LinearDocument.PaginationOrderBy.Priority
});
myIssues.nodes.forEach(issue => {
  console.log(`[${issue.identifier}] ${issue.title}${issue.state?.name}`);
});
Enter fullscreen mode Exit fullscreen mode

Create Issues Programmatically

// Create a single issue
const issue = await linear.createIssue({
  teamId: 'TEAM_ID',
  title: 'Implement user onboarding flow',
  description: 'Build the 3-step onboarding wizard as per the Figma mockup',
  priority: 2, // 1=Urgent, 2=High, 3=Medium, 4=Low
  labelIds: ['LABEL_ID'],
  assigneeId: 'USER_ID'
});

console.log(`Created: ${issue.issue?.identifier}`);

// Bulk create from template
const sprintTasks = [
  { title: 'API endpoints for user profile', priority: 2 },
  { title: 'Unit tests for auth module', priority: 3 },
  { title: 'Update API documentation', priority: 4 },
  { title: 'Performance testing', priority: 3 }
];

for (const task of sprintTasks) {
  await linear.createIssue({ teamId: 'TEAM_ID', ...task });
}
Enter fullscreen mode Exit fullscreen mode

Automate Sprint Creation

// Create a new cycle (sprint) with issues
async function createSprint(teamId, name, issues) {
  // Create cycle
  const cycle = await linear.createCycle({
    teamId,
    name,
    startsAt: new Date(),
    endsAt: new Date(Date.now() + 14 * 86400000) // 2 weeks
  });

  // Add issues to cycle
  for (const issueData of issues) {
    const issue = await linear.createIssue({
      teamId,
      cycleId: cycle.cycle?.id,
      ...issueData
    });
  }

  return cycle;
}
Enter fullscreen mode Exit fullscreen mode

Webhooks

// Set up webhook to get notified of changes
const express = require('express');
const app = express();

app.post('/linear-webhook', express.json(), (req, res) => {
  const { action, type, data } = req.body;

  if (type === 'Issue' && action === 'update') {
    if (data.state?.name === 'Done') {
      // Issue completed — trigger deployment, notify Slack, etc.
      console.log(`Issue ${data.identifier} completed!`);
    }
  }

  res.sendStatus(200);
});
Enter fullscreen mode Exit fullscreen mode

Useful Automations

  1. Auto-create issues from GitHub PRs — when PR opened, create Linear issue
  2. Sprint reports — query cycle issues, generate Slack summary
  3. Bug triage — auto-assign based on labels and priority
  4. Standup bot — pull yesterday's completed + today's in-progress
  5. SLA tracking — alert if high-priority issues stale > 24h

Need to track scraping project tasks? Check out my web scraping actors on Apify — managed scraping with monitoring.

Need custom project automation? Email me at spinov001@gmail.com.

Top comments (0)