Summary
We’re introducing a new set of endpoints that let you programmatically manage weekly timesheet approval workflows in Asana.
With this release, you can:
- Read and manage timesheet approval statuses for any user on a per-week basis (Monday-Sunday UTC)
- Transition timesheets through approval states:
DRAFT→SUBMITTED→APPROVED(orREJECTED) - Filter time tracking entries by their associated timesheet approval status
- Set
descriptionandbillable_statuson time tracking entries
Note: description and billable_status on time tracking entries requires the Timesheets & Budgeting add-on (TBAO).
This enables teams to build automated timesheet submission, validation, approval, and reporting workflows via the API.
Timeline
These endpoints are now available!
Usage
New resource: Timesheet Approval Status
Each timesheet_approval_status represents one user’s weekly timesheet (Monday–Sunday UTC). The resource has the following shape:
| Field | Type | Description |
|---|---|---|
gid |
string | Globally unique identifier |
user |
UserCompact | The user who submitted the timesheet |
workspace |
WorkspaceCompact | The workspace the timesheet belongs to |
start_date |
date | Start of the timesheet week (Monday, UTC) |
end_date |
date | End of the timesheet week (Sunday, UTC) |
approval_status |
enum | One of: DRAFT, SUBMITTED, APPROVED, REJECTED |
created_at |
datetime | When the timesheet record was created |
New endpoints
Get a single timesheet approval status
GET /timesheet_approval_statuses/{timesheet_approval_status_gid}
List timesheet approval statuses (with filters)
GET /timesheet_approval_statuses
Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
workspace |
string | Yes | Workspace GID |
user |
string | Conditional | User GID. Required when filtering by dates or statuses. |
from_date |
date | Yes | Filters to timesheets with start_date ≥ this value |
to_date |
date | No | Filters to timesheets with start_date ≤ this value |
approval_statuses |
string | No | Comma-separated list (e.g., submitted,approved) |
Example: retrieve a user’s submitted and approved timesheets for a date range:
// GET /timesheet_approval_statuses?user=123&workspace=456&from_date=2025-03-10&to_date=2025-03-16&approval_statuses=submitted,approved
{
"data": [
{
"gid": "890",
"resource_type": "timesheet_approval_status",
"user": {
"gid": "123",
"resource_type": "user"
},
"workspace": {
"gid": "456",
"resource_type": "workspace"
},
"start_date": "2025-03-10",
"end_date": "2025-03-16",
"approval_status": "SUBMITTED",
"created_at": "2025-03-16T01:00:00Z"
}
]
}
Create or retrieve a timesheet approval status
Use this endpoint to get-or-create a weekly timesheet. If a record already exists for the given user, workspace, and week, it is returned.
// POST /timesheet_approval_statuses
{
"data": {
"user": "123",
"workspace": "456",
"start_date": "2025-03-10",
"end_date": "2025-03-16"
}
}
Update a timesheet approval status
Transition a timesheet to a new approval state. The server enforces valid state transitions and domain mode (e.g., submit-only vs. submit-and-approve). You can optionally include a message that will be recorded as a story on the transition.
// PUT /timesheet_approval_statuses/{timesheet_approval_status_gid}
{
"data": {
"approval_status": "APPROVED",
"message": "Looks good — approved for the week."
}
}
Updated endpoints
Filter time tracking entries by timesheet
The existing GET /time_tracking_entries endpoint now accepts a timesheet_approval_status_gid parameter. This returns all time tracking entries matching the user and date range of the specified timesheet.
GET /time_tracking_entries?timesheet_approval_status_gid=890
New optional fields on time tracking entries (TBAO only)
POST /tasks/{task_gid}/time_tracking_entries and PUT /time_tracking_entries/{time_tracking_entry_gid} now support two additional optional fields:
| Field | Type | Description |
|---|---|---|
description |
string | A text description for the time entry |
billable_status |
enum | Whether the entry is billable or non-billable |
Example: create a time tracking entry with description and billable status:
POST /tasks/{task_gid}/time_tracking_entries
{
"data": {
"entered_on": "2025-03-12",
"duration_minutes": 120,
"description": "Client review meeting and follow-up notes",
"billable_status": "billable"
}
}
Resources
Thanks, and feel free to reply to this post with questions!