For organizations using Asana’s Timesheets and Budgets, periodic reporting is essential for accurate accounting and payroll. While Asana provides robust in-app views, you may occasionally need a comprehensive CSV export of all time entries across your entire domain for external auditing or custom processing at the end of a month or quarter.
This article explains how to use the Asana API to aggregate time entries from across your workspace and format them into a clean, accounting-ready CSV that matches your internal requirements.
Note
While this guide is tailored for users of the Timesheets and Budgets add-on, this API-based export method is also available for non-addon users who log time via standard Asana task fields.
While the Asana UI offers powerful dashboards, exporting via API allows you to:
To ensure compatibility with standard accounting practices, your export script should produce a CSV containing the following fields as seen in your reviewer view exports:
|
Column |
Description |
|
Task name |
The title of the task where time was logged. |
|
Time (hours) |
Total duration converted from minutes to decimal hours. |
|
Date |
The specific day the work was performed. |
|
Submitter |
The name of the team member who logged the time. |
|
Task GID |
The unique identifier for the Asana task. |
|
Project GID |
The unique identifier for the parent project. |
|
Task Status |
Whether the task is currently "Open" or "Completed". |
|
Entry GID |
The unique identifier for the specific time log. |
To export "all" time, your script must iterate through your projects to find tasks, then fetch time entries for those tasks using the Get time tracking entries for a task endpoint.
Pythonimport asanaimport pandas as pd# Initialize Clientclient = asana.Client.access_token('YOUR_PERSONAL_ACCESS_TOKEN')workspace_gid = 'YOUR_WORKSPACE_GID'def export_domain_time():all_time_data = []# 1. Iterate through all projects in the workspaceprojects = client.projects.get_projects({'workspace': workspace_gid})for project in projects:# 2. Get all tasks for the projecttasks = client.tasks.get_tasks_for_project(project['gid'], opt_fields=['name', 'gid', 'completed', 'completed_at', 'priority'])for task in tasks:# 3. Fetch time entries for each tasktime_entries = client.time_tracking_entries.get_time_tracking_entries_for_task(task['gid'],opt_fields=['created_by.name', 'duration_minutes', 'entered_on', 'gid'])for entry in time_entries:# Calculate hours in decimal formathours = round(entry['duration_minutes'] / 60, 2)# Build the row to match the CSV templateall_time_data.append({"Task name": task['name'],"Time (hours)": hours,"Date": entry['entered_on'],"Submitter": entry['created_by']['name'],"Task GID": task['gid'],"Project GID": project['gid'],"Task Status": "Completed" if task['completed'] else "Open","Task Completion Date": task.get('completed_at', ''),"Task Priority": task.get('priority', ''),"Entry GID": entry['gid']})# 4. Save to CSVdf = pd.DataFrame(all_time_data)df.to_csv('asana_time_export_accounting.csv', index=False)print("Export complete: asana_time_export_accounting.csv")export_domain_time()
When running this export for an entire organization, keep the following best practices in mind: