Summary
-
Tables and Records let you store structured data in Asana. A Table holds Records (rows), and its columns are custom fields
-
New resource types: Table and Record.
-
New OAuth scopes: tables:read, tables:write, tables:delete, records:read, records:write, records:delete.
-
Records support comments through the existing Stories API (GET/POST /records/{record_gid}/stories).
-
Webhooks (added, changed, deleted, and undeleted) are supported on Tables and Records. Subscribe to changes with POST /webhooks.
Who is affected
-
No breaking changes. These are new resources and new endpoints; no existing endpoint’s request or response shape changed.
-
Developers who want to create and manage Tables and Records via API, instead of only through the Asana web app.
Key behaviors
-
A record belongs to exactly one table. custom_fields values can only be written for fields already present in that table’s custom field settings
-
Only global (published) custom fields can be added to a table. Adding a non-global field, whether reusing an existing field or creating one inline, fails with 403 Forbidden.
Timeline
This is a non-breaking, additive change. The tables and Records endpoints will be available to all developers on October 27, 2026.
Creating a table
POST /tables
{
"data": {
"name": "Vendor contracts",
"workspace": "1331",
"custom_field_settings": ["14916"]
}
}
A custom_field_settings entry can be the GID of an existing global custom field, or an inline object creating a new one. This is equivalent to, but more efficient than, creating the table and then calling addCustomFieldSetting once per field.
Adding a custom field to an existing table
POST /tables/{table_gid}/addCustomFieldSetting
{
"data": {
"custom_field": "14916",
"is_important": true
}
}
Creating a record
POST /records
{
"data": {
"name": "Q3 renewal",
"table": "1337",
"custom_fields": {
"5678904321": "On Hold"
},
"unique_fingerprint": "sfdc-opportunity-0061"
}
}
Only custom fields already present in the record’s table can be set through custom_fields.
Listing records in a table
GET /tables/{table_gid}/records?limit=50&sort_by=created_at
{
"data": [
{
"gid": "1203",
"resource_type": "record",
"name": "Q3 renewal"
},
{
"gid": "1204",
"resource_type": "record",
"name": "Q4 renewal"
}
],
"next_page": {"offset": "...", "path": "...", "uri": "..."}
}
Searching records in a workspace
GET /workspaces/{workspace_gid}/records/search?text=Renewal&tables.any=12345,23456
{
"data": [
{
"gid": "1203",
"resource_type": "record",
"name": "Q3 renewal"
},
{
"gid": "1204",
"resource_type": "record",
"name": "Q4 renewal"
}
]
}
Supported endpoints
| Method | Route |
|---|---|
| GET | /workspaces/{workspace_gid}/tables |
| POST | /tables |
| GET | /tables/{table_gid} |
| PUT | /tables/{table_gid} |
| DELETE | /tables/{table_gid} |
| POST | /tables/{table_gid}/addCustomFieldSetting |
| POST | /tables/{table_gid}/removeCustomFieldSetting |
| GET | /tables/{table_gid}/custom_field_settings |
| GET | /tables/{table_gid}/records |
| POST | /records |
| GET | /records/{record_gid} |
| PUT | /records/{record_gid} |
| DELETE | /records/{record_gid} |
| GET | /workspaces/{workspace_gid}/records/search |
| GET | /records/{record_gid}/stories |
| POST | /records/{record_gid}/stories |
Error codes
| Status | Message |
|---|---|
| 400 Bad Request | Missing or malformed parameter. Check the documentation and the syntax of your request and try again. |
| 401 Unauthorized | A valid authentication token was not provided with the request. |
| 402 Payment Required | Advanced record search requires a premium Asana plan. |
| 403 Forbidden | Custom field already exists on the table. |
| 403 Forbidden | Cannot add a non-global (unpublished) custom field to a table. |
| 403 Forbidden | You cannot add any more custom fields to this table. The limit for custom fields on a table is 150. |
| 404 Not Found | The requested table or record does not exist, or you don’t have access to it. |
| 409 Conflict | A record with the given unique_fingerprint already exists in this table. A unique_fingerprint is a unique ID you choose for a record, such as its ID in another system. This conflict happens when you create a second record with the same value in the same table. This prevents retried or repeated imports from creating duplicate records in a table. |
| 429 Too Many Requests | You have exceeded one of the enforced rate limits in the API. |
| 500 Internal Server Error | There was a problem on Asana’s end. |
Resources
Questions and Feedback
If you have questions or feedback about the Tables and Records API, please reply to this post.