Important Changes to API and SeaTable Cloud with Version 5.0

On July 15th 2024, SeaTable version 5.0 will introduce significant changes to the API. This summary outlines the upcoming changes, with some relevant to the general API and others specific to SeaTable Cloud.

If this text is too long for you, you will find a short summary after each paragraph:

:+1: Example for the summary of this paragraph


1. API Gateway is Recommended, Not Mandatory

The new API gateway endpoints are recommended for all future applications. You can find them at SeaTable API Reference - Base Operations or just by looking for the URL containing /api-gateway/.

image

However, it is not required to update or change existing apps. The old endpoints are not deprecated and remain valid. Existing automations and integrations using platforms like n8n, Make.com, or Zapier will continue to work without updates.

:+1: No changes required — this is just for your information.


2. SeaTable Cloud Redirects Some Calls to the API Gateway

Approximately 70% of all requests to SeaTable Cloud are external API requests, mainly for Get Row, List Rows, and List Rows with SQL.

The new API gateway offers faster responses by checking if the base has remained unchanged since the last request. Consequently, we decided to redirect these three endpoints to the API gateway to reduce the overall load of SeaTable Cloud.

The requests are not proxied, but instead return a 302 header redirect with the new URL. Most integrations and software tools, such as n8n, Zapier, Make.com, and libraries like requests (Python), Guzzle (PHP), and Axios (Node), will follow these redirects automatically.

However, with cURL, you need to use the -L parameter to follow redirects. Otherwise, no output will be received.

Example for adding the -L parameter to a curl request:

curl --request GET -L \
     --url 'https://cloud.seatable.io/dtable-server/api/v1/dtables/...' \
     --header 'accept: application/json' \
     --header 'authorization: Bearer ...

:+1: Verify that your custom solutions follow redirects automatically.
(most do this automatically!)


3. Harmonization of Data Outputs

The output format for the Get Row and List Rows endpoints will change with the redirect to the API gateway. To avoid breaking changes, SeaTable ensures that the output format remains consistent even with these redirects.

However, there are two exceptions:

  • Link columns now return an array containing display_value and row_id instead of a string with only the display_value.
  • Link-Formula columns now return the appropriate output type depending on the result. Single numbers are returned as integers, while multiple values are returned as arrays.
# output before 5.0 of a link column
{
   "link": ["value 1", "value2"]
}

# output with 5.0 of a link column
{
   "link": [
     {
       "display_value": "value1",
       "row_id": "A1R_7bMzQxexjVHa0_vgZw"
     },
     {
       "display_value": "value2",
       "row_id": "MwznxkdhS7y15HdlAE1uDg"
     }
}
# output before 5.0 of a link-formula column
"link-formula-countlinks": "6"
"link-formula-lookup": "value 1, value 2",

# output with 5.0 of a link-formula column
"link-formula-countlinks": 6,
"link-formula-lookup": [
  "value 1",
  "value 2"
]

These adjustments harmonize the output of Get Row and List Rows to be consistent with the List Rows with SQL endpoint!

Self-hosted and dedicated SeaTable server systems are not affected by this, as there the three endpoints are not redirected to the API gateway and the output remains the same.

:+1: Please check your custom API workflows and custom apps to see if these changes of the output type of Link and Link Formula columns affect you.

This is only relevant for these two endpoints: Get Row and List Rows.
If you are using the List Rows with SQL endpoint already, you are not affected by this change.


4. Retrieve Current Rate Limits

API Gateway endpoints return the current rate limit usage through x-ratelimit headers. These headers provide the daily limit, current usage, and the next reset time as a Unix timestamp in seconds. Below is an example of the returned headers:

x-ratelimit-limit: 5000
x-ratelimit-remaining: 4996
x-ratelimit-reset: 1720710405

:+1: No changes required — this is just for your information.

More information about the new release will be available soon.

3 Likes

Just wanted to share with you that we experienced a breaking change yesterday with the Go-Live of 5.0, which I don’t see mentioned:

We were using convert_link_id: true with the List Rows API and this parameter apparently has now changed to convert_keys: true

Hm, I don’t think I fully understand. This is how convert_link_id could be used in the past for list rows api:

With the new output format of links, there is no more need for this parameter because ID and value of every link is returned - and this is explained in 3, right?

I am also a bit confused. Thanks for the swift reply. Has the convert_keys default value maybe changed from true to false? What I can say for sure that previously we were not using the convert_keys parameter in one place and still got the datasets with the column headers as keys. After 5.0 I had a broken page and after adding convert_keys: true it was back to normal

Did you also update the Python pipeline?

Thanks both for checking! :slight_smile: I wouldn’t think python pipeline can be involved in our scenario

The mentioned case is Datatables with an JS Ajax call to get the Data From SeaTable Cloud via "cloud.seatable.io/api-gateway/api/v2/dtables/dtable_uuid/rows/

Previously not using convert_keys param and working fine, and after 5.0 I had to add it. So definitely nothing major and it’s already fixed on our end, but maybe someone is experiencing the same.

Hi @cdb , it seems that with the last API changes, the result of link columns for a List rows returns only the ten first display_value / row_id pairs, which is quite problematic…

Can you confirm this ? Is it possible to change that behavior ?

Bests,
Benjamin

As far as I know, this behaviour has not changed and was always like this. If you want to get more links, you have to use a separate API request.
Let me check with @daniel.pan.

I’m pretty sure something changed because I have routines not working anymore since the 5.0 update…
Just to compare, here are the results of a List Rows API call, limited to 1 record:

4.3 Self-Hosted enterprise version

{
  "rows": [
    {
      "_id": "AocFPY7FQFS7H5XdE7SRCQ",
      "_mtime": "2024-01-30T09:45:28.197+00:00",
      "_ctime": "2024-01-08T14:21:56.991+00:00",
      "Nom": "Semi-complet 500g",
      "Producteur": [
        "PW880DBNRZC7qK9a52a_CA"
      ],
      "Prix": 2.4,
      "Qte": 0.5,
      "Unite": "kg",
      "Commandes": [
        "PMHMESW6R9mtakfBEhsaHQ",
        "c5sgxi8iTEmKJ_c9RCFQlw",
        "cz0yXQODQdCE4NXsQZMhdA",
        "Pot2x283Sj6trK2wiWd0xw"
      ],
      "Dates_dispo": [
        "R7peHCWbRmq5LaqTNHqUIA",
        "WW5P1vxuSyqFippAhPxemw",
        "SEKBOIXSS_y3vt1O4s21aQ",
        "CP9KXG0QQGmgA9O02XhO3Q",
        "Dzjny0EmSwCED1tHbbBcqQ",
        "J1be2ef6TI-3EoBT_K3zPw",
        "MVQd4K1WTVm94j-eMJwCdA",
        "LJyZA2OgRfaBMV3hsYw0RQ",
        "UZ1QgXHOQ1mwuF1fKG6jAA",
        "A8kdHTEHQWSZ5xJg-cmyyw",
        "dOE1zYFgTQSXFIo7NalAVQ",
        "fL3tecu3TfW7-31Y9Zg09A",
        "NlUPHn-IQc2kj4wXCeIVDQ",
        "Pk23lx5GSbWJ5Mez0NXU5g",
        "dUA9tcNIQlGAii7eVmo35w",
        "JH0GJyV9TvabxrKA0p6JXQ",
        "HHxwdMn4QqSk5xnvq113aQ",
        "X0SZTvfBRWyGqsYXyZSWiA",
        "dvrPqDrvQBGkX0wvu5qCDQ",
        "IZkfIdetT-OmmoU90bYBRg",
        "KDduG7IuRfWHhJLklgTOzQ",
        "UHPm0NsKTb-nyZOxtwoV5g",
        "evdp6ADKQCeS-lYBB-yXKQ",
        "e0RBg72wSj-npCTI-cM5Xw",
        "FrKZi0twSl-4CkKAz5uY8A",
        "e5Mvk1tTTECUzSt9NCSqdw",
        "NrwKnG8SSU-7aQ7XRQi1ag",
        "dpY3S_twSWSRlP7GTLc-mw",
        "Bs8OKH_8TG2ejFt3yrUb1A",
        "ApDfi79uTbG5L04uPSR2QA",
        "XKMY644kQaOfa__WZq4ubg"
      ]
    }
  ]
}

As you can see, the Dates_dispo link column contains (and returns) around 30 links

5.0 Cloud-version

{
  "rows": [
    {
      "0000": "Semi-complet 500g",
      "bl9l": [
        {
          "row_id": "PW880DBNRZC7qK9a52a_CA",
          "display_value": "le GAEC Dou Chonlai"
        }
      ],
      "2O36": 2.4,
      "LcMK": 0.5,
      "3tU5": "671076",
      "wUsJ": [
        {
          "row_id": "PMHMESW6R9mtakfBEhsaHQ",
          "display_value": "20240302-0001"
        },
        {
          "row_id": "c5sgxi8iTEmKJ_c9RCFQlw",
          "display_value": "20240302-0002"
        },
        {
          "row_id": "cz0yXQODQdCE4NXsQZMhdA",
          "display_value": "20240526-0005"
        },
        {
          "row_id": "Pot2x283Sj6trK2wiWd0xw",
          "display_value": "20240615-0001"
        }
      ],
      "d3r3": [
        {
          "row_id": "R7peHCWbRmq5LaqTNHqUIA",
          "display_value": "2024-02-05T00:00:00+01:00"
        },
        {
          "row_id": "WW5P1vxuSyqFippAhPxemw",
          "display_value": "2024-02-12T00:00:00+01:00"
        },
        {
          "row_id": "SEKBOIXSS_y3vt1O4s21aQ",
          "display_value": "2024-02-19T00:00:00+01:00"
        },
        {
          "row_id": "CP9KXG0QQGmgA9O02XhO3Q",
          "display_value": "2024-02-26T00:00:00+01:00"
        },
        {
          "row_id": "Dzjny0EmSwCED1tHbbBcqQ",
          "display_value": "2024-03-04T00:00:00+01:00"
        },
        {
          "row_id": "J1be2ef6TI-3EoBT_K3zPw",
          "display_value": "2024-03-11T00:00:00+01:00"
        },
        {
          "row_id": "MVQd4K1WTVm94j-eMJwCdA",
          "display_value": "2024-03-18T00:00:00+01:00"
        },
        {
          "row_id": "LJyZA2OgRfaBMV3hsYw0RQ",
          "display_value": "2024-03-25T00:00:00+01:00"
        },
        {
          "row_id": "UZ1QgXHOQ1mwuF1fKG6jAA",
          "display_value": "2024-04-08T00:00:00+02:00"
        },
        {
          "row_id": "A8kdHTEHQWSZ5xJg-cmyyw",
          "display_value": "2024-04-15T00:00:00+02:00"
        }
      ],
      "_locked": null,
      "_locked_by": null,
      "_archived": false,
      "_creator": "edfefe21cd2641d68b592b5e18a12db4@auth.local",
      "_ctime": "2024-01-08T15:21:56.991+01:00",
      "_last_modifier": "edfefe21cd2641d68b592b5e18a12db4@auth.local",
      "_mtime": "2024-01-30T10:45:28.197+01:00",
      "_id": "AocFPY7FQFS7H5XdE7SRCQ"
    }
  ]
}

As you can see, only the ten first links are displayed for the Dates_dispo link column (it’s the same record).

By the way: Since 5.0, the columns’ names are replaced by their keys, which is no the easiest way to work neither (if it stays like that, it will be necessary to systematically run a List columns request to populate a list of columns containing both names and keys, and then refer to this list instead of just accessing row[COLUMN_NAME]).

Thanks for your help,

Bests,
Benjamin

For the issue “the columns’ names are replaced by their keys”, in version 5.0, you can add parameter “convert_keys” to true to return column names.

https://api.seatable.io/reference/listrows

For the issue “only the first 10 records in linked columns returned”, this is the designed behaviour of the new list-rows API via API-gateway. We may consider to increase the number limit to 50 records later.

To get a full list of linked records in linked columns, the API https://api.seatable.io/reference/listrowlinks need to be used.

Hi @daniel.pan , sorry I had missed this information, my bad!

Ok, I won’t tell you that I’m particularly happy with this change, as I have to modify a significant number of scripts and workflows, but I understand. However, this change does not appear in @cdb’s message above, nor in the API documentation. Perhaps it would be interesting to add it somewhere?

This leads me to another question about how to keep SeaTable always on with such API changes, but I created a specific topic as here doesn’t look like the good place to discuss it to me…

Bests,
Benjamin

One question regarding column_keys instead of column_names: do you use python pipeline or an ordinary api request? If you are running python scripts with python pipeline, please update the python runner to the latest version, then you will have the default behaviour that column_names are returned by default.

Hi @cdb, no actually I use the seatable_api python library in an ordinary python environment, which is quite problematic for now: I updated the library, but it still calls the api v1 URLS, whereas the result seems to be the result of v2…

I’m probably not clear, but here is the problem. I’m using seatable-api v 2.8.1 to work on cloud-hosted v5 bases, and in this 2.8.1 version of the library, here is the definition of the list_rows function:

def list_rows(self, table_name, view_name=None, order_by=None, desc=False, start=None, limit=None):
        """
        :param table_name: str
        :param view_name: str
        :param order_by: str
        :param desc: boolean
        :param start: int
        :param limit: int
        :return: list
        """
        url = self._row_server_url()
        params = {
            'table_name': table_name
        }

        if like_table_id(table_name):
            params['table_id'] = table_name
        if view_name:
            params['view_name'] = view_name
        if order_by:
            params['order_by'] = order_by
            params['direction'] = 'desc' if desc else 'asc'
        if start:
            params['start'] = start
        if limit:
            params['limit'] = limit
        response = requests.get(url, params=params, headers=self.headers, timeout=self.timeout)
        data = parse_response(response)
        return data.get('rows')

and the _row_server_url() function:

def _row_server_url(self):
        return self.dtable_server_url + '/api/v1/dtables/' + self.dtable_uuid + '/rows/'

As you can see, the convert_keys parameter can’t be passed to the function, however the function returns the rows with the columns’ keys instead of the columns’ names…

To keep using my scripts, I had to manually modify the _row_server_url() function as followed:

def _row_server_url(self):
        return self.dtable_server_url + '/api/v1/dtables/' + self.dtable_uuid + '/rows/?convert_keys=true'

It’s working, but manually modifying a lib looks somewhat unconventional to me, do you agree ?

Bests,
Benjamin