airtable

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Airtable — Bases, Tables & Records

Airtable — Bases、Tables与Records

Work with Airtable's REST API directly via
curl
using the
terminal
tool. No MCP server, no OAuth flow, no Python SDK — just
curl
and a personal access token.
使用
terminal
工具,通过
curl
直接调用Airtable的REST API。无需MCP服务器、OAuth流程或Python SDK —— 只需
curl
和个人访问令牌。

Prerequisites

前置条件

  1. Create a Personal Access Token (PAT) at https://airtable.com/create/tokens (tokens start with
    pat...
    ).
  2. Grant these scopes (minimum):
    • data.records:read
      — read rows
    • data.records:write
      — create / update / delete rows
    • schema.bases:read
      — list bases and tables
  3. Important: in the same token UI, add each base you want to access to the token's Access list. PATs are scoped per-base — a valid token on the wrong base returns
    403
    .
  4. Store the token in
    ~/.hermes/.env
    (or via
    hermes setup
    ):
    AIRTABLE_API_KEY=pat_your_token_here
Note: legacy
key...
API keys were deprecated Feb 2024. Only PATs and OAuth tokens work now.
  1. https://airtable.com/create/tokens创建**个人访问令牌(Personal Access Token, PAT)**(令牌以
    pat...
    开头)。
  2. 授予以下最低权限范围:
    • data.records:read
      — 读取行数据
    • data.records:write
      — 创建/更新/删除行数据
    • schema.bases:read
      — 列出Bases和Tables
  3. 重要提示:在同一个令牌界面中,将你想要访问的每个Base添加到令牌的**访问(Access)**列表中。PAT是按Base划分权限范围的——如果令牌在错误的Base上使用,会返回
    403
    错误。
  4. 将令牌存储在
    ~/.hermes/.env
    中(或通过
    hermes setup
    设置):
    AIRTABLE_API_KEY=pat_your_token_here
注意:旧版
key...
格式的API密钥已于2024年2月弃用。现在仅支持PAT和OAuth令牌。

API Basics

API基础

  • Endpoint:
    https://api.airtable.com/v0
  • Auth header:
    Authorization: Bearer $AIRTABLE_API_KEY
  • All requests use JSON (
    Content-Type: application/json
    for any POST/PATCH/PUT body).
  • Object IDs: bases
    app...
    , tables
    tbl...
    , records
    rec...
    , fields
    fld...
    . IDs never change; names can. Prefer IDs in automations.
  • Rate limit: 5 requests/sec/base.
    429
    → back off. Burst on a single base will be throttled.
Base curl pattern:
bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=5" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
-s
suppresses curl's progress bar — keep it set for every call so the tool output stays clean for Hermes. Pipe through
python3 -m json.tool
(always present) or
jq
(if installed) for readable JSON.
  • 端点
    https://api.airtable.com/v0
  • 认证头
    Authorization: Bearer $AIRTABLE_API_KEY
  • 所有请求均使用JSON格式(POST/PATCH/PUT请求体需设置
    Content-Type: application/json
    )。
  • 对象ID:Bases为
    app...
    、Tables为
    tbl...
    、Records为
    rec...
    、Fields为
    fld...
    。ID永不改变;名称可能变更。在自动化操作中优先使用ID。
  • 速率限制:每个Base每秒最多5次请求。收到
    429
    响应时请暂停请求。针对单个Base的突发请求会被限流。
基础curl调用模板:
bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=5" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
-s
参数会隐藏curl的进度条——每次调用都请保留该参数,以确保工具输出在Hermes中保持整洁。可通过管道输出到
python3 -m json.tool
(系统默认自带)或
jq
(若已安装)来格式化JSON,提升可读性。

Field Types (request body shapes)

字段类型(请求体格式)

Field typeWrite shape
Single line text
"Name": "hello"
Long text
"Notes": "multi\nline"
Number
"Score": 42
Checkbox
"Done": true
Single select
"Status": "Todo"
(name must already exist unless
typecast: true
)
Multi-select
"Tags": ["urgent", "bug"]
Date
"Due": "2026-04-01"
DateTime (UTC)
"At": "2026-04-01T14:30:00.000Z"
URL / Email / Phone
"Link": "https://…"
Attachment
"Files": [{"url": "https://…"}]
(Airtable fetches + rehosts)
Linked record
"Owner": ["recXXXXXXXXXXXXXX"]
(array of record IDs)
User
"AssignedTo": {"id": "usrXXXXXXXXXXXXXX"}
Pass
"typecast": true
at the top level of a create/update body to let Airtable auto-coerce values (e.g. create a new select option on the fly, convert
"42"
42
).
字段类型写入格式
单行文本
"Name": "hello"
多行文本
"Notes": "multi\nline"
数字
"Score": 42
复选框
"Done": true
单选
"Status": "Todo"
(选项名称必须已存在,除非设置
typecast: true
多选
"Tags": ["urgent", "bug"]
日期
"Due": "2026-04-01"
日期时间(UTC)
"At": "2026-04-01T14:30:00.000Z"
URL / 邮箱 / 电话
"Link": "https://…"
附件
"Files": [{"url": "https://…"}]
(Airtable会获取并重新托管文件)
关联记录
"Owner": ["recXXXXXXXXXXXXXX"]
(记录ID数组)
用户
"AssignedTo": {"id": "usrXXXXXXXXXXXXXX"}
在创建/更新请求体的顶层设置
"typecast": true
,可让Airtable自动转换值(例如动态创建新的单选选项、将
"42"
转换为
42
)。

Common Queries

常见查询

List bases the token can see

列出令牌可访问的Bases

bash
curl -s "https://api.airtable.com/v0/meta/bases" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
bash
curl -s "https://api.airtable.com/v0/meta/bases" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool

List tables + schema for a base

列出某个Base的Tables及 schema

bash
curl -s "https://api.airtable.com/v0/meta/bases/$BASE_ID/tables" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
Use this BEFORE mutating — confirms exact field names and IDs, surfaces
options.choices
for select fields, and shows primary-field names.
bash
curl -s "https://api.airtable.com/v0/meta/bases/$BASE_ID/tables" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
在执行修改操作前请先调用此接口——确认字段的准确名称和ID,查看单选字段的
options.choices
选项,以及主键字段名称。

List records (first 10)

列出记录(前10条)

bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=10" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=10" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool

Get a single record

获取单条记录

bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool

Filter records (filterByFormula)

筛选记录(filterByFormula)

Airtable formulas must be URL-encoded. Let Python stdlib do it — never hand-encode:
bash
FORMULA="{Status}='Todo'"
ENC=$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$FORMULA")
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?filterByFormula=$ENC&maxRecords=20" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
Useful formula patterns:
  • Exact match:
    {Email}='user@example.com'
  • Contains:
    FIND('bug', LOWER({Title}))
  • Multiple conditions:
    AND({Status}='Todo', {Priority}='High')
  • Or:
    OR({Owner}='alice', {Owner}='bob')
  • Not empty:
    NOT({Assignee}='')
  • Date comparison:
    IS_AFTER({Due}, TODAY())
Airtable公式必须进行URL编码。请使用Python标准库完成编码——切勿手动编码:
bash
FORMULA="{Status}='Todo'"
ENC=$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$FORMULA")
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?filterByFormula=$ENC&maxRecords=20" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
实用公式模板:
  • 精确匹配:
    {Email}='user@example.com'
  • 包含匹配:
    FIND('bug', LOWER({Title}))
  • 多条件:
    AND({Status}='Todo', {Priority}='High')
  • 或条件:
    OR({Owner}='alice', {Owner}='bob')
  • 非空:
    NOT({Assignee}='')
  • 日期比较:
    IS_AFTER({Due}, TODAY())

Sort + select specific fields

排序并选择特定字段

bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?sort%5B0%5D%5Bfield%5D=Priority&sort%5B0%5D%5Bdirection%5D=asc&fields%5B%5D=Name&fields%5B%5D=Status" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
Square brackets in query params MUST be URL-encoded (
%5B
/
%5D
).
bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?sort%5B0%5D%5Bfield%5D=Priority&sort%5B0%5D%5Bdirection%5D=asc&fields%5B%5D=Name&fields%5B%5D=Status" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
查询参数中的方括号必须进行URL编码(
%5B
/
%5D
)。

Use a named view

使用命名视图

bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?view=Grid%20view&maxRecords=50" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
Views apply their saved filter + sort server-side.
bash
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?view=Grid%20view&maxRecords=50" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
视图会在服务器端应用已保存的筛选和排序规则。

Common Mutations

常见修改操作

Create a record

创建记录

bash
curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fields":{"Name":"New task","Status":"Todo","Priority":"High"}}' | python3 -m json.tool
bash
curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fields":{"Name":"New task","Status":"Todo","Priority":"High"}}' | python3 -m json.tool

Create up to 10 records in one call

单次调用创建最多10条记录

bash
curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "typecast": true,
    "records": [
      {"fields": {"Name": "Task A", "Status": "Todo"}},
      {"fields": {"Name": "Task B", "Status": "In progress"}}
    ]
  }' | python3 -m json.tool
Batch endpoints are capped at 10 records per request. For larger inserts, loop in batches of 10 with a short sleep to respect 5 req/sec/base.
bash
curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "typecast": true,
    "records": [
      {"fields": {"Name": "Task A", "Status": "Todo"}},
      {"fields": {"Name": "Task B", "Status": "In progress"}}
    ]
  }' | python3 -m json.tool
批量接口的上限为每次请求10条记录。如需插入更多记录,请按10条为一批进行循环,并在每批之间短暂休眠,以遵守每个Base每秒5次请求的限制。

Update a record (PATCH — merges, preserves unchanged fields)

更新记录(PATCH —— 合并更新,保留未修改字段)

bash
curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fields":{"Status":"Done"}}' | python3 -m json.tool
bash
curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fields":{"Status":"Done"}}' | python3 -m json.tool

Upsert by a merge field (no ID needed)

通过合并字段进行Upsert(无需记录ID)

bash
curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "performUpsert": {"fieldsToMergeOn": ["Email"]},
    "records": [
      {"fields": {"Email": "user@example.com", "Status": "Active"}}
    ]
  }' | python3 -m json.tool
performUpsert
creates records whose merge-field values are new, patches records whose merge-field values already exist. Great for idempotent syncs.
bash
curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "performUpsert": {"fieldsToMergeOn": ["Email"]},
    "records": [
      {"fields": {"Email": "user@example.com", "Status": "Active"}}
    ]
  }' | python3 -m json.tool
performUpsert
会为合并字段值不存在的记录创建新条目,为合并字段值已存在的记录更新内容。非常适合实现幂等同步。

Delete a record

删除记录

bash
curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
bash
curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool

Delete up to 10 records in one call

单次调用删除最多10条记录

bash
curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE?records%5B%5D=rec1&records%5B%5D=rec2" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool
bash
curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE?records%5B%5D=rec1&records%5B%5D=rec2" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool

Pagination

分页

List endpoints return at most 100 records per page. If the response includes
"offset": "..."
, pass it back on the next call. Loop until the field is absent:
bash
OFFSET=""
while :; do
  URL="https://api.airtable.com/v0/$BASE_ID/$TABLE?pageSize=100"
  [ -n "$OFFSET" ] && URL="$URL&offset=$OFFSET"
  RESP=$(curl -s "$URL" -H "Authorization: Bearer $AIRTABLE_API_KEY")
  echo "$RESP" | python3 -c 'import json,sys; d=json.load(sys.stdin); [print(r["id"], r["fields"].get("Name","")) for r in d["records"]]'
  OFFSET=$(echo "$RESP" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("offset",""))')
  [ -z "$OFFSET" ] && break
done
列表接口每页最多返回100条记录。如果响应中包含
"offset": "..."
,请在下一次调用时传入该参数。循环调用直到该字段不存在:
bash
OFFSET=""
while :; do
  URL="https://api.airtable.com/v0/$BASE_ID/$TABLE?pageSize=100"
  [ -n "$OFFSET" ] && URL="$URL&offset=$OFFSET"
  RESP=$(curl -s "$URL" -H "Authorization: Bearer $AIRTABLE_API_KEY")
  echo "$RESP" | python3 -c 'import json,sys; d=json.load(sys.stdin); [print(r["id"], r["fields"].get("Name","")) for r in d["records"]]'
  OFFSET=$(echo "$RESP" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("offset",""))')
  [ -z "$OFFSET" ] && break
done

Typical Hermes Workflow

典型Hermes工作流

  1. Confirm auth.
    curl -s -o /dev/null -w "%{http_code}\n" https://api.airtable.com/v0/meta/bases -H "Authorization: Bearer $AIRTABLE_API_KEY"
    — expect
    200
    .
  2. Find the base. List bases (step above) OR ask the user for the
    app...
    ID directly if the token lacks
    schema.bases:read
    .
  3. Inspect the schema.
    GET /v0/meta/bases/$BASE_ID/tables
    — cache the exact field names and primary-field name locally in the session before mutating anything.
  4. Read before you write. For "update X where Y",
    filterByFormula
    first to resolve the
    rec...
    ID, then
    PATCH /v0/$BASE_ID/$TABLE/$RECORD_ID
    . Never guess record IDs.
  5. Batch writes. Combine related creates into one 10-record POST to stay under the 5 req/sec budget.
  6. Destructive ops. Deletions can't be undone via API. If the user says "delete all Xs", echo back the filter + record count and confirm before firing.
  1. 确认认证有效性。执行
    curl -s -o /dev/null -w "%{http_code}\n" https://api.airtable.com/v0/meta/bases -H "Authorization: Bearer $AIRTABLE_API_KEY"
    —— 预期返回
    200
  2. 找到目标Base。列出Bases(如上一步),或者如果令牌缺少
    schema.bases:read
    权限,直接向用户询问
    app...
    格式的Base ID。
  3. 检查Schema。调用
    GET /v0/meta/bases/$BASE_ID/tables
    —— 在执行任何修改操作前,在会话本地缓存字段的准确名称和主键字段名称。
  4. 先读取再写入。对于“更新满足Y条件的X记录”操作,先通过
    filterByFormula
    解析出
    rec...
    格式的记录ID,再调用
    PATCH /v0/$BASE_ID/$TABLE/$RECORD_ID
    。切勿猜测记录ID。
  5. 批量写入。将相关的创建操作合并为单次10条记录的POST请求,以控制在每秒5次请求的限制内。
  6. 破坏性操作。通过API删除的记录无法恢复。如果用户要求“删除所有X记录”,请先返回筛选条件和记录数量,确认后再执行操作。

Pitfalls

常见陷阱

  • filterByFormula
    MUST be URL-encoded.
    Field names with spaces or non-ASCII also need encoding (
    {My Field}
    %7BMy%20Field%7D
    ). Use Python stdlib (pattern above) — never hand-escape.
  • Empty fields are omitted from responses. A missing
    "Assignee"
    key doesn't mean the field doesn't exist — it means this record's value is empty. Check the schema (step 3) before concluding a field is missing.
  • PATCH vs PUT.
    PATCH
    merges supplied fields into the record.
    PUT
    replaces the record entirely and clears any field you didn't include. Default to
    PATCH
    .
  • Single-select options must exist. Writing
    "Status": "Shipping"
    when
    Shipping
    isn't in the field's option list errors with
    INVALID_MULTIPLE_CHOICE_OPTIONS
    unless you pass
    "typecast": true
    (which auto-creates the option).
  • Per-base token scoping. A
    403
    on one base while another works means the token's Access list doesn't include that base — not a scope or auth issue. Send the user to https://airtable.com/create/tokens to grant it.
  • Rate limits are per base, not per token. 5 req/sec on
    baseA
    and 5 req/sec on
    baseB
    is fine; 6 req/sec on
    baseA
    alone will throttle. Monitor the
    Retry-After
    header on
    429
    .
  • filterByFormula
    必须进行URL编码
    。包含空格或非ASCII字符的字段名称也需要编码(例如
    {My Field}
    %7BMy%20Field%7D
    )。请使用Python标准库(如上模板)——切勿手动转义。
  • 空字段会从响应中省略。响应中缺少
    "Assignee"
    键并不意味着该字段不存在——而是表示该记录的此字段值为空。在判断字段是否存在前,请先检查Schema(步骤3)。
  • PATCH与PUT的区别
    PATCH
    会将提供的字段合并到记录中。
    PUT
    会完全替换记录,并清空所有未包含的字段。默认优先使用
    PATCH
  • 单选选项必须已存在。如果字段选项列表中没有
    Shipping
    ,写入
    "Status": "Shipping"
    会返回
    INVALID_MULTIPLE_CHOICE_OPTIONS
    错误,除非设置
    "typecast": true
    (会自动创建该选项)。
  • 令牌按Base划分权限。在一个Base上返回
    403
    错误但在另一个Base上正常,说明令牌的访问列表未包含该Base——并非权限范围或认证问题。请引导用户前往https://airtable.com/create/tokens授予访问权限。
  • 速率限制是按Base而非令牌计算。在
    baseA
    每秒5次请求、
    baseB
    每秒5次请求是允许的;但仅在
    baseA
    上每秒6次请求会被限流。收到
    429
    响应时,请查看
    Retry-After
    头信息。

Important Notes for Hermes

Hermes相关重要提示

  • Always use the
    terminal
    tool with
    curl
    .
    Do NOT use
    web_extract
    (it can't send auth headers) or
    browser_navigate
    (needs UI auth and is slow).
  • AIRTABLE_API_KEY
    flows from
    ~/.hermes/.env
    into the subprocess automatically
    when this skill is loaded — no need to re-export it before each
    curl
    call.
  • Escape curly braces in formulas carefully. In a heredoc body,
    {Status}
    is literal. In a shell argument,
    {Status}
    is safe outside
    {...}
    brace-expansion context — but pass dynamic strings through
    python3 urllib.parse.quote
    before splicing into a URL.
  • Pretty-print with
    python3 -m json.tool
    (always present) rather than
    jq
    (optional). Only reach for
    jq
    when you need filtering/projection.
  • Pagination is per-page, not global. Airtable's 100-record cap is a hard limit; there is no way to bump it. Loop with
    offset
    until the field is absent.
  • Read the
    errors
    array
    on non-2xx responses — Airtable returns structured error codes like
    AUTHENTICATION_REQUIRED
    ,
    INVALID_PERMISSIONS
    ,
    MODEL_ID_NOT_FOUND
    ,
    INVALID_MULTIPLE_CHOICE_OPTIONS
    that tell you exactly what's wrong.
  • 始终使用
    terminal
    工具配合
    curl
    。请勿使用
    web_extract
    (无法发送认证头)或
    browser_navigate
    (需要UI认证且速度慢)。
  • 加载此技能时,
    AIRTABLE_API_KEY
    会自动从
    ~/.hermes/.env
    传入子进程
    ——无需在每次
    curl
    调用前重新导出该变量。
  • 注意公式中花括号的转义。在 heredoc 体中,
    {Status}
    是字面量。在Shell参数中,
    {Status}
    {...}
    括号扩展上下文之外是安全的——但在将动态字符串拼接到URL前,请通过
    python3 urllib.parse.quote
    处理。
  • 使用
    python3 -m json.tool
    格式化输出
    (系统默认自带),而非
    jq
    (可选安装)。仅在需要筛选/投影时使用
    jq
  • 分页是按页而非全局限制。Airtable的100条记录上限是硬性限制;无法调整。请循环传入
    offset
    直到该字段不存在。
  • 查看非2xx响应中的
    errors
    数组
    。Airtable会返回结构化错误码,例如
    AUTHENTICATION_REQUIRED
    INVALID_PERMISSIONS
    MODEL_ID_NOT_FOUND
    INVALID_MULTIPLE_CHOICE_OPTIONS
    ,可明确告知问题所在。