1. Opening Problem Statement
Meet Sarah, a project manager at a fast-growing software development company. Every morning, she spends 2-3 hours manually compiling tickets from her team’s Linear project management tool to update a Google Sheet report used by stakeholders. This tedious task often leads to errors: missing tickets, inconsistent data due to human mistakes, and delays in sharing updates. Sarah knows that this manual process wastes precious time and increases the risk of outdated information influencing critical decisions.
This workflow is made specifically for people like Sarah — who want a reliable, automated way to export and keep their Linear team’s tickets updated in Google Sheets daily without any manual intervention.
2. What This Automation Does
This n8n workflow automatically fetches all tickets from a specified Linear team using the Linear GraphQL API each day at 9:00 AM and writes them into a Google Sheets spreadsheet. Here’s what it accomplishes:
- Daily Scheduled Sync: Runs every day at 9 AM exactly, ensuring your ticket data is fresh every morning.
- Full Pagination Handling: Automatically fetches all tickets beyond the first 100 by handling Linear’s pagination—no tickets are missed.
- Custom Field Setup: Sets default values like ticket estimates and extracts labels for each ticket, enriching the data for reporting.
- Smart Google Sheets Update: Appends new tickets or updates existing rows based on ticket IDs, keeping the sheet tidy and accurate.
- Flattened Data Structure: Uses a Code node to flatten the nested GraphQL response for easier filtering and mapping in Sheets.
- Team-Specific Filter: You control exactly which team’s tickets to export by setting the team name in the GraphQL query variables.
By automating this, Sarah and teams save several hours weekly, eliminate manual copying errors, and always start their day with up-to-date ticket data.
3. Prerequisites ⚙️
- n8n account (cloud or self-hosted) ⏱️🔌
- Linear API access with a personal API key (used via Header Auth in GraphQL nodes) 🔑
- Google account with access to Google Sheets and OAuth credentials configured in n8n 📊🔐
- Linear team name you want to export tickets from (e.g., “Adore”)
For those preferring self-hosting their n8n, platforms like Hostinger can be a great option.
4. Step-by-Step Guide
Step 1: Create a Scheduled Trigger to Run Daily at 9 AM
Navigate to Nodes → Schedule Trigger in n8n. Configure the trigger with a fixed hour of 9. This sets the workflow to start every day at 9 AM local time.
You should see a trigger ready to fire daily. Common mistake: Forgetting to set the correct time zone or hour, leading to execution at unexpected times.
Step 2: Add a GraphQL Node to Query Linear Tickets
Add a GraphQL node named “Get all your team’s tickets”. Set the API endpoint to https://api.linear.app/graphql. Input the query to fetch issues with filters, including the team name set to your team (e.g., “Adore”). The variables field must include the team filtering JSON exactly like this:
{
"filter": {
"team": {
"name": {
"eq": "YourTeamName"
}
}
}
}Set the authentication to use your Linear API key via Header Auth credentials.
When run, this node fetches up to 100 tickets. Common mistake: Misconfiguring the filter variable JSON or using the wrong API key.
Step 3: Setup an If Node to Check for Pagination
Add an If node right after the GraphQL query. Configure it to check if {{$json.data.issues.pageInfo.hasNextPage}} is true. This lets the workflow know if there are more tickets beyond the first 100.
If the condition is true, the workflow proceeds to fetch the next page; otherwise, it moves on to processing tickets.
Common mistake: Using incorrect syntax or path to access the GraphQL result.
Step 4: Use a Set Node to Pass the End Cursor for Pagination
Add a Set node called “Get end cursor” to capture the endCursor from the previous query results. This cursor tells the API where to start the next page.
Set a new field after with the value {{$json.data.issues.pageInfo.endCursor}}. This prepares the pagination variable for the next query.
Common mistake: Not matching the correct JSON path to set the cursor.
Step 5: Call GraphQL Node Again to Fetch the Next Page
Add another GraphQL node “Get next page” similar to Step 2, but this time pass the after variable to fetch the next 100 tickets starting after the cursor.
The query needs the same team filter and pagination parameter after. This node loops until all pages are fetched.
Common mistake: Forgetting to interpolate the after variable correctly in the query.
Step 6: Split Out Tickets Into Individual Items
Add a Split Out node “Split out the tickets” after the initial and pagination GraphQL nodes. Set it to split the array field data.issues.nodes so each ticket becomes an individual item for easier processing.
Common mistake: Using the wrong field path or forgetting to split, which makes mapping later difficult.
Step 7: Set Custom Fields for Each Ticket
Add a Set node “Set custom fields” to add or override ticket fields. For example, pull labels names into a comma-separated string and set a default estimate of 1 if none exists.
Use expressions like:
estimate: {{$json.estimate ?? 1}}
labels: {{$json.labels.nodes.map(label => label.name).toString()}}This enriches data for better reporting and filtering.
Common mistake: Incorrect JavaScript syntax in the expression.
Step 8: Flatten Nested Ticket Objects for Simple Fields
Add a Code node “Flatten object to have simple fields to filter by” with this JavaScript to flatten nested data structures:
function flattenObject(ob) {
var toReturn = {};
for (var i in ob) {
if (!ob.hasOwnProperty(i)) continue;
if ((typeof ob[i]) == 'object' && ob[i] !== null) {
var flatObject = flattenObject(ob[i]);
for (var x in flatObject) {
if (!flatObject.hasOwnProperty(x)) continue;
toReturn[i + '.' + x] = flatObject[x];
}
} else {
toReturn[i] = ob[i];
}
}
return toReturn;
}
return flattenObject($input.item.json);This makes downstream Google Sheets mapping easier.
Common mistake: Not using the exact flattening code can break field mapping.
Step 9: Write Tickets to Google Sheets
Add a Google Sheets node “Write tickets to Sheets” with the following settings:
- Operation: Append or Update
- Sheet name: Your target sheet name or ID
- Document ID: Your Google Sheet file ID
- Columns: Set an “id” column for matching, and enable autoMapInputData for other fields
- Authentication: Use your Google Sheets OAuth2 credentials
This ensures tickets are saved and updated without duplicates.
Common mistake: Not matching columns correctly or missing Google credentials.
5. Customizations ✏️
- Change Team Name Filter: In the “Get all your team’s tickets” and “Get next page” GraphQL nodes, change the
team.name.eqvalue to your own team (e.g., “Adore”) to export tickets for a different project. - Modify Default Estimate: In the “Set custom fields” node, change
estimatefrom1to any default value that fits your workflow requirements. - Customize Google Sheets Target: In the “Write tickets to Sheets” node, update the
sheetNameordocumentIdparameters to point to a different Google Sheet or tab. - Add Extra Fields: Modify the GraphQL query to include more ticket details such as assignee name or comments, then map those new fields in the “Set custom fields” or flatten node.
- Adjust Schedule Timing: Modify the schedule trigger node to run at any other hour or frequency that suits your team’s reporting needs.
6. Troubleshooting 🔧
Problem: “Authentication failed on GraphQL requests”
Cause: Incorrect or expired Linear API key.
Solution: Go to the credentials section in n8n, update or regenerate your Linear API key, and reconnect the GraphQL nodes.
Problem: “Google Sheets node fails to write data”
Cause: Invalid or revoked Google OAuth credentials or lacking sheet access.
Solution: Reauthorize Google Sheets credentials in n8n, verify sheet permissions, and ensure the correct sheet ID and name are used.
Problem: “Pagination does not fetch all tickets”
Cause: Incorrect handling of endCursor or hasNextPage in the workflow.
Solution: Check the If node condition’s JSON path and the Set node extracting endCursor for correctness; ensure the “Get next page” node uses the cursor variable properly.
7. Pre-Production Checklist ✅
- Verify your Linear API key is active and has access to the desired team’s tickets.
- Test the GraphQL query independently with your variables before adding to the workflow.
- Validate Google Sheets credentials and that the sheet exists with the required columns (at least “id”).
- Run workflow manually a few times to watch for errors or missing data.
- Back up your Google Sheet data before first automated update.
8. Deployment Guide
Once fully tested, activate the workflow in n8n. Monitor the daily runs via the execution log to confirm tickets export correctly each day at 9 AM.
Set up email or Slack alerts for failures if needed, to keep your ticket reports reliable.
9. FAQs
Can I export tickets from multiple teams? Yes, but you would need to duplicate or modify this workflow for each team or enhance the GraphQL filter logic.
Does this consume Linear API rate limits? Yes, but fetching 100 tickets per page with pagination is efficient. Run frequency and volume should be balanced accordingly.
Is my ticket data secure? All credentials are stored securely in n8n. Ensure your API keys are kept private.
10. Conclusion
By following this detailed guide, you automated the daily export of all your Linear team’s tickets to Google Sheets with n8n, saving hours every week from tedious manual reporting. Your ticket data stays accurate and up-to-date, improving your team’s visibility and decision-making.
Next, consider automating ticket status changes notifications or integrating ticket comments into Slack for real-time updates. Keep enhancing your developer productivity with smart, tailored workflows!