Pricing

How to Connect Asana to Google Sheets

AsanaSaved SearchDateDocumentAmount07/01INV-40214,280.0007/02INV-40221,860.5007/05INV-40239,140.0007/08INV-40242,375.2507/09INV-40256,902.7507/12INV-40263,118.40BrookedABCDateDocumentAmount123456707/01INV-40214,280.0007/02INV-40221,860.5007/05INV-40239,140.0007/08INV-40242,375.2507/09INV-40256,902.7507/12INV-40263,118.40Google SheetsAsana report
JW
James Whitfield

Export Asana tasks to Google Sheets with the API, including the opt_fields parameter without which you get only names, and custom fields that arrive typed.

Asana exports any project to CSV in two clicks, which handles one-off requests. For reporting that refreshes, the API is the route, and the first thing that surprises people is that it returns almost nothing by default: without an opt_fields parameter you get task names and IDs and nothing else. This guide covers that, plus pagination, custom fields and the two different due-date fields.

The two-minute option: CSV export

Open a project, use the dropdown next to its name, and choose Export/Print → CSV. Import into Sheets via File → Import. The export is per project, so a portfolio view means repeating it for each one, which is the usual reason people move to the API.

Asana to Google Sheets for free (Apps Script + API)

Create a personal access token from your Asana profile settings → Apps → Developer apps, or at the Asana developer console. Get the project GID from the project URL: it is the long numeric ID in the path.

The critical parameter is opt_fields. Asana defaults to a compact representation of every object, returning only gid, name and resource_type. Any field you want, including nested ones like an assignee's name, has to be named explicitly, using dot notation for nesting.

Code.gs
function importAsanaTasks() {  const TOKEN = "YOUR_PERSONAL_ACCESS_TOKEN";  const PROJECT_GID = "1201234567890123";   const headers = { Authorization: "Bearer " + TOKEN };   // Without opt_fields you get gid + name only. Nested values use dot paths.  const FIELDS = [    "name", "completed", "completed_at", "due_on", "due_at",    "assignee.name", "custom_fields.name", "custom_fields.display_value",  ].join(",");   const rows = [];  let offset = null;   do {    let url = "https://app.asana.com/api/1.0/tasks"      + "?project=" + PROJECT_GID      + "&limit=100"                 // 100 is the maximum      + "&opt_fields=" + FIELDS;    if (offset) url += "&opt_pretty=false&offset=" + offset;     const res = JSON.parse(      UrlFetchApp.fetch(url, { headers, muteHttpExceptions: true })        .getContentText()    );    if (res.errors) throw new Error(JSON.stringify(res.errors));     res.data.forEach((t) => {      // A task has due_at (timestamp) OR due_on (date), never both.      const due = t.due_at || t.due_on || "";       // Custom fields are an array, not named columns. display_value gives a      // string for any type, which avoids branching on text/number/enum.      const custom = (t.custom_fields || [])        .filter((f) => f.display_value)        .map((f) => f.name + ": " + f.display_value)        .join("; ");       rows.push([        t.name,        t.completed ? "Complete" : "Open",        t.completed_at || "",        due,        t.assignee ? t.assignee.name : "Unassigned",        custom,      ]);    });     // The offset token is opaque; it must come from next_page.    offset = res.next_page ? res.next_page.offset : null;  } while (offset);   const header = ["Task","Status","Completed","Due","Assignee","Custom fields"];  const ss = SpreadsheetApp.getActiveSpreadsheet();  const sheet = ss.getSheetByName("Asana") || ss.insertSheet("Asana");  sheet.clearContents();  sheet.getRange(1, 1, 1, header.length).setValues([header]);  if (rows.length) {    sheet.getRange(2, 1, rows.length, header.length).setValues(rows);  }}

Run once to authorise, then add a time-driven trigger. Note that requesting more opt_fields makes responses larger and slower, so name what you need rather than everything available.

Limits: Apps Script's six-minute cap applies, and Asana rate-limits per token, so a portfolio-wide pull across many projects is better split across scheduled runs than attempted in one.

The Brooked method

Brooked requests the right fields for you, pages through the offset tokens, and flattens custom fields into real named columns rather than a single joined string, so you can filter and pivot on them. Several projects can import into one spreadsheet on a single schedule.

Step 1: Install Brooked

Install Brooked from the Google Workspace Marketplace. Free tier includes 100 imports per month, no credit card required.

Step 2: Connect Asana

Choose Asana in Brooked and authorise your workspace, or paste a personal access token. Pick the projects you want, choose whether to include completed tasks, and import.

Step 3: Schedule the refresh

Set the import to re-run daily or weekly so status reports rebuild themselves before the meeting rather than during it.

BrookedBrooked AI, Asana
Live
Ask anything about your Asana data…

Method comparison

MethodCostSetupRefreshTwo-wayBest for
Asana CSV exportFree (per project)2 minManualNoA one-off export of a single project
Apps Script + Asana APIFree25 to 35 minTime-driven triggerDIYSeveral projects, custom fields
Zapier / MakeFree tier limited · paid for volume10 to 15 minOn task created or completedDIY (second workflow)Logging individual task events
BrookedFree tier · Pro $29/user/mo~3 minScheduled (hourly, daily, weekly)YesScheduled portfolio reporting

Common use cases

  • Portfolio reporting: roll several projects into one status table for leadership
  • Workload balancing: count open tasks per assignee to spot who is over capacity
  • Cycle time: compare created against completed_at to measure how long work takes
  • Client reporting: filter a project to client-visible tasks and share just that sheet
  • Historical snapshots: schedule daily imports to keep trend history Asana does not retain

Troubleshooting common issues

Frequently asked questions

Why does the Asana API only return gid and name?

By design. Asana returns a compact record containing gid, name and resource_type unless you ask for more, so a request without opt_fields looks like it lost every field you cared about. Pass opt_fields with an explicit comma-separated list, for example opt_fields=name,completed,due_on,assignee.name,custom_fields.name,custom_fields.display_value.

Can I export Asana to Google Sheets for free?

Yes. Any project exports to CSV from its project menu under Export/Print, free on all plans, which covers a one-off. The Apps Script method here uses a free personal access token and a free time-driven trigger for data that refreshes. Brooked's free tier covers 100 imports a month.

What is the difference between due_on and due_at?

due_on is a plain date with no time, and due_at is a full timestamp used when a task has a specific due time. A task has one or the other, never both, so code reading only due_at silently shows blanks for every task with a date-only deadline. Read due_at and fall back to due_on.

How do I get more than 100 tasks?

limit maxes out at 100. Asana paginates with an offset token: the response's next_page object contains an offset value you pass as the offset parameter on the next request, repeating until next_page is null. The token is opaque and cannot be constructed yourself.

How do custom fields come back?

As an array of objects on each task rather than as named columns, with each entry carrying the field name plus a typed value: text_value, number_value, enum_value with a name, or date_value. The simplest approach is to request custom_fields.display_value, which gives a string rendering of any type, and only reach for the typed fields when you need to do arithmetic.

Can I write changes from Sheets back into Asana?

Yes for editable fields, and Brooked supports write-back, so bulk updates to assignees, due dates or custom fields are possible from a sheet. Computed and system fields reject writes: created_at, modified_at, and the gid itself.

Connect Asana to Google Sheets today.

Free tier: 100 imports per month, no credit card required. Or see the full Asana integration details.

Install Brooked free →

Also in Project Management

More Project Management guides

Project Management

How to Connect Monday.com to Google Sheets

Export Monday.com boards to Google Sheets with the GraphQL API, including the items query that was removed and the complexity budget that throttles large boards.

JW
James Whitfield
Read
Project Management

How to Connect Clockify to Google Sheets

Export Clockify time entries to Google Sheets, including the per-user endpoint that hides your team's hours and the ISO durations that will not sum.

JW
James Whitfield
Read
Project Management

How to Connect ClickUp to Google Sheets

Export ClickUp tasks to Google Sheets, including the closed tasks and subtasks left out by default and the timestamps that arrive as millisecond strings.

JW
James Whitfield
Read

Get your spreadsheet hours back

Brooked sets up in seconds. Your team is querying live data before lunch.

Get started free