Skip to main content

Linear

This connector captures issues, projects, initiatives, and labels from Linear into Estuary collections. It authenticates with a Linear personal API key and reads data through the Linear GraphQL API.

Supported data resources​

StreamDescriptionReplication
issuesIssues across every team the authenticating user can access.Incremental + backfill
projectsProjects, including their status, dates, and progress.Incremental + backfill
initiativesInitiatives and their owning relationships. Requires a paid Linear plan.Incremental + backfill
labelsIssue labels, both workspace-level and team-level.Snapshot

issues, projects, and initiatives are keyed on /id and cursored on updatedAt. After the initial backfill, each sync captures only records changed since the previous sync.

labels is re-read in full every interval, because applying a label to an issue does not advance the label's updatedAt. Every label is captured regardless of the start date, and each row carries a /_meta/row_id key instead of /id.

Related records are referenced by id. Each issue carries labelIds, so issues join to the labels collection, along with { id } references to its team, state, project, cycle, parent and assignee. Two relationships are not captured: the teams a project belongs to, and the projects under an initiative.

Only primary keys, cursors, and the archivedAt tombstone are declared on the write schema; all remaining fields are populated by schema inference, so new Linear fields appear automatically without a connector change.

Archival and deletion​

warning

Archiving a record in Linear does not advance its updatedAt timestamp. This has a different consequence per stream, and it affects how you should interpret captured data.

  • issues capture archival. Linear's issue filter exposes an archivedAt comparator, so the connector runs a second pass over that field on every sync. An archived issue arrives with archivedAt set — treat that as the tombstone. Do not infer archival from updatedAt movement, which does not change when an issue is archived.

    A deleted issue is not removed from your destination. Linear moves it to the trash first, and it arrives with trashed: true only if trashing advances updatedAt, which has not been verified. Once Linear purges it, it never arrives again.

  • labels capture archival and deletion. Each snapshot includes archived labels with archivedAt set, and a label deleted in Linear is removed from your destination.

  • projects and initiatives do not capture archival. Linear's API exposes no archivedAt filter for these types, so there is no way to detect archival incrementally. A record archived or deleted in Linear remains in your destination indefinitely with a null archivedAt, indistinguishable from a live record. Re-running a backfill of the binding picks up archivedAt for records updated since the start date. It never removes records, though, so deleted projects and initiatives stay in your destination, and records archived before the start date keep a null archivedAt.

Limitations​

  • identifier is not captured for projects or initiatives. Linear gates it behind its paid "Project IDs" and "Initiative IDs" add-ons, and requesting it errors on every page for workspaces without them.
  • initiatives requires a paid Linear plan. How Linear responds to the stream on a workspace without the entitlement has not been verified. If it returns an error, the binding fails, so disable it on such workspaces.

Rate limits​

Linear meters two independent hourly budgets per user:

BudgetLimit
Requests2,500 per hour
Complexity3,000,000 points per hour
Single query10,000 points (hard cap)

Either can bind first, because complexity is charged per record returned rather than per request: workspaces whose records carry many populated relations spend complexity faster than requests. The connector reads both budgets from every response and pauses until the relevant window resets, so a healthy capture should not be rate-limited. If Linear still rejects a request as rate-limited, the connector waits for the budget to reset and retries. If a single page exceeds the 10,000-point cap, it retries with a smaller page. Reducing binding intervals across many bindings increases consumption of both budgets proportionally.

Prerequisites​

  • A Linear account with access to the teams whose data you want to capture. The connector sees exactly what the authenticating user sees.
  • A Linear personal API key. See Authentication below.
  • A paid Linear plan, if you intend to capture the initiatives stream.

Authentication​

The connector authenticates with a Linear personal API key.

To create one:

  1. Sign in to Linear as the user whose access the connector should use.
  2. Go to Settings > Security & access > Personal API keys.
  3. Click New API key, give it a name, and grant it read access.
  4. Copy the generated key immediately — Linear only displays it once.

You'll use this value as the access_token when configuring the connector.

Configuration​

You configure connectors either in the Estuary web app, or by directly editing the Data Flow specification file. See connectors to learn more about using connectors. The values and specification sample below provide configuration details specific to the Linear source connector.

Properties​

Endpoint​

PropertyTitleDescriptionTypeRequired/Default
/credentialsAuthenticationLinear API key credentials.objectRequired
/credentials/access_tokenAPI KeyLinear personal API key, created under Settings > Security & access > Personal API keys.stringRequired
/start_dateStart DateUTC date and time from which to start replicating data. Data generated before this date is not replicated, except labels, which are always captured in full. Defaults to 30 days before the present.string30 days ago

Bindings​

PropertyTitleDescriptionTypeRequired/Default
/nameNameName of the resource to capture (issues, projects, initiatives, or labels).stringRequired
/intervalIntervalInterval between data syncs for this resource.stringPT5M

Sample​

captures:
${PREFIX}/${CAPTURE_NAME}:
endpoint:
connector:
image: ghcr.io/estuary/source-linear:v1
config:
credentials:
credentials_title: API Key
access_token: <secret>
start_date: "2024-01-01T00:00:00Z"
bindings:
- resource:
name: issues
interval: PT5M
target: ${PREFIX}/issues
- resource:
name: projects
interval: PT5M
target: ${PREFIX}/projects
- resource:
name: initiatives
interval: PT5M
target: ${PREFIX}/initiatives
- resource:
name: labels
interval: PT5M
target: ${PREFIX}/labels