# \[New\] Tables and Records API

**URL:** <https://forum.asana.com/t/new-tables-and-records-api/1159790>\
**Category:** Changelog\
**Tags:** api, new-api\
**Created:** [26 October 2026 17:22 UTC](https://forum.asana.com/t/new-tables-and-records-api/1159790 "2026-10-26T17:22:26Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Darya\_Selivanava](https://sea2.discourse-cdn.com/asana/user_avatar/forum.asana.com/darya_selivanava/32/285705_2.png) [@Darya\_Selivanava](https://forum.asana.com/u/Darya_Selivanava)\
**Post date:** [26 October 2026 17:22 UTC](https://forum.asana.com/t/new-tables-and-records-api/1159790/1 "2026-10-26T17:22:27Z")

</div>

## **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**

```auto
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**

```auto
POST /tables/{table_gid}/addCustomFieldSetting
{
  "data": {
    "custom_field": "14916",
    "is_important": true
  }
}

```

#### **Creating a record**

```auto
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**

```auto
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**

```auto
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**

- [Custom fields guide](https://developers.asana.com/docs/custom-fields-guide)

- [Stories](https://developers.asana.com/reference/stories)

- [Rate limiting](https://developers.asana.com/docs/rate-limits)

## **Questions and Feedback**

If you have questions or feedback about the Tables and Records API, please reply to this post.

---

<div class="post-metadata">

**Author:** ![Phil\_Seeman](https://sea2.discourse-cdn.com/asana/user_avatar/forum.asana.com/phil_seeman/32/81525_2.png) [@Phil\_Seeman](https://forum.asana.com/u/Phil_Seeman)\
**Post date:** [26 October 2026 17:42 UTC](https://forum.asana.com/t/new-tables-and-records-api/1159790/2 "2026-10-26T17:42:25Z")

</div>

Excellent - thanks, @Darya_Selivanava!

---

<div class="post-metadata">

**Author:** ![Andrea\_Carlaw](https://sea2.discourse-cdn.com/asana/user_avatar/forum.asana.com/andrea_carlaw/32/292742_2.png) [@Andrea\_Carlaw](https://forum.asana.com/u/Andrea_Carlaw)\
**Post date:** [27 October 2026 00:33 UTC](https://forum.asana.com/t/new-tables-and-records-api/1159790/3 "2026-10-27T00:33:45Z")

</div>

Thanks Darya, great to see this live.

One gap we ran into last week: there’s no endpoint for reading or changing record permissions (privacy or record members). The help article confirms access can be set per record, but there’s no way to change it in bulk, either in the UI or through the API.

A customer in pilot had 500+ records where users who could see the table (set to public to org) couldn’t find records they hadn’t created when searching in a reference custom field.  
Making each record visible to the organisation fixed it, but it had to be done manually (ended up using Claude to interact with the browser and go through record by record - not ideal).

There wasn’t an option we could find in the API and therefore scripting to be able to achieve it, nor a bulk update option in the UI.

Are record permission endpoints, or a table-level default for new records, on the roadmap?
