Menu QaldyDocs

Linear

Preview

Create and update Linear issues and read what your team shipped.

  • Status: Preview
  • Shelf: Developer
  • How you connect: API key
  • Regions: global (not available to Kazakhstan-only workspaces)
  • The service’s own API reference: https://linear.app/developers/graphql

Apps create and update Linear issues and read what a team finished, with a personal API key. Linear is reached through the HTTP API connector with a preset: the gate calls only api.linear.app/graphql, with POST. The key is sealed to the gate and apps never see it.

Connect it

  1. In Linear: Settings → Account → Security & access → Personal API keys → New API key (linear.app/settings/account/security).
  2. Give it only the permissions the apps need: Read, and Create issues if apps open issues. Leave out Admin.
  3. Copy the key (it starts with lin_api_; Linear shows it once).
  4. Qaldy → Connectors → Linear → Connect Linear → paste the key → Seal and connect.

A personal key acts as you, with your access to teams. Create it from a shared or machine account if the apps should not be tied to one person.

Test connection only checks that the sealed key opens. Linear has no GET to test with and the preset allows only POST, so the gate sends nothing; the first real call proves the key.

What the gate allows

Hostapi.linear.app (pinned, every resolved address public)
MethodPOST only
Path/graphql
KeyAuthorization: <key>, added by the gate (Linear takes a personal key without Bearer)

GraphQL means one path carries every operation, so the fence is the host, the method and the key's own permissions; the typed helper below sends only the documented operations.

Use it from an app

json
{ "id": "http", "actions": ["request"], "scope": "conn_k3v9…" }
ts
import { linear } from '@qaldy/sdk'

const ln = linear(ctx.connectors.http('conn_k3v9…'))
const { teams } = await ln.listTeams()
const { issues } = await ln.listIssues({ teamId: teams[0]?.id, completedSince: '2026-10-12T00:00:00Z' })
await ln.createIssue({ teamId: teams[0]?.id ?? '', title: 'Checkout shows the wrong total', priority: 2 })
await ln.updateIssue({ id: issues[0]?.id ?? '', description: 'Seen on mobile only.' })

The helper checks the input before anything is sent and decodes the reply; a GraphQL errors array becomes an error with Linear's own words.

When it breaks

You seeWhyDo
401 / "Authentication required"The key was revoked or mistypedReplace the key
RATELIMITEDLinear's request or complexity limitRead fewer issues per call, run less often
"Entity not found" for a team or stateThe id is from another workspace, or deletedList teams again and pick one
"Forbidden" on createIssueThe key lacks Create issuesMake a new key with it

Gaps

  • Not run against a live workspace (hence Preview).
  • No webhooks from Linear, no comments, projects or cycles; only issues and teams.
  • Test connection sends nothing (see above).

Type to search. Up and down to choose, Enter to open, Esc to close.