Перейти к основному содержимому

Airtable

REST API Airtable через curl. CRUD для записей, фильтры, апсерты.

Метаданные навыка​

ИсточникВстроенный (установлен по умолчанию)
Путьskills/productivity/airtable
Версия1.1.0
Авторcommunity
ЛицензияMIT
Платформыlinux, macos, windows
ТегиAirtable, Productivity, Database, API

Справочник: полный SKILL.md​

к сведению

Ниже приведено полное описание навыка, которое VibeOS загружает при его активации. Агент видит эти инструкции, когда навык активен.

Airtable — Базы, Таблицы и Записи

Работайте с REST API Airtable напрямую через curl с помощью инструмента terminal. Никакого MCP-сервера, OAuth-потока или Python SDK — только curl и персональный токен доступа.

Предварительные требования​

  1. Создайте персональный токен доступа (PAT) на https://airtable.com/create/tokens (токены начинаются с pat...).
  2. Предоставьте следующие разрешения (минимум):
    • data.records:read — чтение строк
    • data.records:write — создание / обновление / удаление строк
    • schema.bases:read — список баз и таблиц
  3. Важно: в том же интерфейсе токена добавьте каждую базу, к которой нужен доступ, в список Доступ токена. PAT ограничены по базам — валидный токен для неверной базы вернёт 403.
  4. Сохраните токен в ${VIBEOS_HOME:-~/.vibeos}/.env (или через vibeos setup):
    AIRTABLE_API_KEY=pat_your_token_here

Примечание: устаревшие ключи API вида key... были объявлены устаревшими в феврале 2024. Сейчас работают только PAT и OAuth-токены.

Основы API​

  • Эндпоинт: https://api.airtable.com/v0
  • Заголовок авторизации: Authorization: Bearer $AIRTABLE_API_KEY
  • Все запросы используют JSON (Content-Type: application/json для любого тела POST/PATCH/PUT).
  • ID объектов: базы app..., таблицы tbl..., записи rec..., поля fld.... ID никогда не меняются; имена могут. В автоматизации предпочитайте ID.
  • Лимит запросов: 5 запросов/сек/базу. 429 → пауза. Пакетная нагрузка на одну базу будет ограничена.

Базовый шаблон curl:

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

-s подавляет индикатор прогресса curl — всегда используйте его, чтобы вывод инструмента оставался чистым для VibeOS. Передавайте через python3 -m json.tool (всегда доступен) или jq (если установлен) для читаемого JSON.

Типы полей (форма тела запроса)​

Тип поляФормат записи
Однострочный текст"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 / Email / Телефон"Link": "https://…"
Вложение"Files": [{"url": "https://…"}] (Airtable загружает и размещает у себя)
Связанная запись"Owner": ["recXXXXXXXXXXXXXX"] (массив ID записей)
Пользователь"AssignedTo": {"id": "usrXXXXXXXXXXXXXX"}

Передайте "typecast": true на верхнем уровне тела создания/обновления, чтобы Airtable автоматически приводил типы (например, создавал новый вариант выбора на лету, преобразовывал "42" → 42).

Часто используемые запросы​

Список баз, доступных токену​

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

Список таблиц + схема для базы​

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 для полей выбора и имена первичных полей.

Список записей (первые 10)​

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

Получить одну запись​

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

Фильтрация записей (filterByFormula)​

Формулы Airtable должны быть URL-закодированы. Используйте стандартную библиотеку Python — никогда не кодируйте вручную:

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())

Сортировка + выбор конкретных полей​

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).

Использовать именованное представление​

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

Представления применяют свои сохранённые фильтры и сортировку на стороне сервера.

Часто используемые изменения​

Создать запись​

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

Создать до 10 записей за один вызов​

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 записей с короткой паузой, чтобы соблюдать 5 запросов/сек/базу.

Обновить запись (PATCH — объединяет, сохраняет неизменённые поля)​

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

Апсерт по полю слияния (ID не нужен)​

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 создаёт записи, значения поля слияния которых новые, и обновляет записи, значения поля слияния которых уже существуют. Отлично подходит для идемпотентной синхронизации.

Удалить запись​

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

Удалить до 10 записей за один вызов​

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

Пагинация​

Эндпоинты списков возвращают максимум 100 записей на страницу. Если ответ содержит "offset": "...", передайте его в следующем запросе. Повторяйте, пока поле не исчезнет:

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

Типичный рабочий процесс VibeOS​

  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. Найдите базу. Выведите список баз (шаг выше) ИЛИ спросите у пользователя ID вида app..., если у токена нет разрешения schema.bases:read.
  3. Изучите схему. GET /v0/meta/bases/$BASE_ID/tables — сохраните точные имена полей и имя первичного поля локально в сессии перед любыми изменениями.
  4. Читайте перед записью. Для «обновить X, где Y» сначала используйте filterByFormula, чтобы получить ID rec..., затем PATCH /v0/$BASE_ID/$TABLE/$RECORD_ID. Никогда не угадывайте ID записей.
  5. Пакетная запись. Объединяйте связанные создания в один POST на 10 записей, чтобы оставаться в рамках лимита 5 запросов/сек.
  6. Деструктивные операции. Удаления нельзя отменить через API. Если пользователь говорит «удалить все X», выведите фильтр + количество записей и подтвердите перед выполнением.

Подводные камни​

  • filterByFormula ОБЯЗАТЕЛЬНО должен быть URL-закодирован. Имена полей с пробелами или не-ASCII символами также требуют кодирования ({My Field} → %7BMy%20Field%7D). Используйте стандартную библиотеку Python (шаблон выше) — никогда не экранируйте вручную.
  • Пустые поля опускаются в ответах. Отсутствие ключа "Assignee" не означает, что поля не существует — это значит, что значение в этой записи пусто. Проверьте схему (шаг 3), прежде чем делать вывод, что поле отсутствует.
  • PATCH vs PUT. PATCH объединяет переданные поля с записью. PUT полностью заменяет запись и очищает любое поле, которое вы не включили. По умолчанию используйте PATCH.
  • Варианты одиночного выбора должны существовать. Запись "Status": "Shipping", когда Shipping нет в списке вариантов поля, вызовет ошибку INVALID_MULTIPLE_CHOICE_OPTIONS, если не передать "typecast": true (который автоматически создаёт вариант).
  • Область действия токена по базам. 403 на одной базе, когда другая работает, означает, что база не добавлена в список доступа токена — это не проблема области или авторизации. Отправьте пользователя на https://airtable.com/create/tokens, чтобы предоставить доступ.
  • Лимиты запросов действуют на базу, а не на токен. 5 запросов/сек на baseA и 5 запросов/сек на baseB — нормально; 6 запросов/сек только на baseA вызовет ограничение. Следите за заголовком Retry-After при 429.

Важные замечания для VibeOS​

  • Всегда используйте инструмент terminal с curl. НЕ используйте web_extract (он не может отправлять заголовки авторизации) или browser_navigate (требует авторизации в UI и медленный).
  • AIRTABLE_API_KEY автоматически передаётся из ${VIBEOS_HOME:-~/.vibeos}/.env в подпроцесс при загрузке этого навыка — не нужно повторно экспортировать его перед каждым вызовом curl.
  • Экранируйте фигурные скобки в формулах осторожно. В теле heredoc {Status} — литерал. В аргументе оболочки {Status} безопасен вне контекста подстановки {...} — но передавайте динамические строки через python3 urllib.parse.quote перед вставкой в URL.
  • Форматируйте вывод с помощью python3 -m json.tool (всегда доступен), а не jq (опционально). Используйте jq только когда нужна фильтрация/проекция.
  • Пагинация постраничная, а не глобальная. Лимит Airtable в 100 записей — жёсткое ограничение; увеличить его нельзя. Используйте цикл с offset, пока поле не исчезнет.
  • Читайте массив errors в ответах с кодом не 2xx — Airtable возвращает структурированные коды ошибок, такие как AUTHENTICATION_REQUIRED, INVALID_PERMISSIONS, MODEL_ID_NOT_FOUND, INVALID_MULTIPLE_CHOICE_OPTIONS, которые точно указывают на проблему.