Linear
Twin of the Linear GraphQL API.
Twin of the Linear GraphQL API. Everything is one endpoint, POST /graphql.
| Covers | api.linear.app |
| Auth | Personal API keys, OAuth |
| Webhooks | No |
| Operations | 29 root fields |
Coverage
Those root fields cover the viewer and organization, users, teams, and issues
with the filter grammar and create, update and archive, plus projects,
milestones, roadmaps, cycles, workflow states, labels, comments, attachments and
issue search, all over Relay pagination. The OAuth issuer sits on the same base
at /oauth/authorize and /oauth/token.
Credentials
A well-formed personal API key authenticates by default, so your existing
lin_api_… key needs no change. Set auth.mode to enforced to accept only
the keys the world knows. See Credentials.
OAuth access tokens are different: only a token this sandbox issued works. Both
kinds carry scopes, and a write without write or the matching *:create scope
gets Linear’s FORBIDDEN error naming the scope.
Vendor specific details
- The API key goes in
Authorizationraw, with noBearerprefix. Send a real key with the prefix and you get a 400 telling you to remove it, not a 401. - HTTP status is not a reliable signal. A syntax error is 500, a validation
error is 400, and a not-found or a bad argument is a 200 carrying
errorswithdata: null. Readextensions.code. - Anything that is not
Content-Type: application/jsonis refused with Apollo’s CSRF block, a 400 with codeBAD_REQUEST. That includes everyGET. searchIssuesis a case-insensitive substring match over title and description, in ordinary connection order. Real Linear ranks by relevance.issueArchiveis a soft delete. Archived issues leave every connection unless you passincludeArchived: true, and there is no hard delete here.
Whole GraphQL floats serialize as 2.0 where real Linear writes 2. Every JSON
parser reads them identically, but a byte-for-byte snapshot will differ.
Its own notes
Once a sandbox is running, this twin serves its own operating notes at
{control_url}/veris/manual: the credentials it accepts, the API versions it
serves, and the fault statuses you can arm against it. They are generated from
the same source as its behaviour, so they cannot drift.