---
title: 'How to Use the Airtable API: A Beginner''s Guide'
description: 'Learn the Airtable REST API from scratch — personal access tokens, first request, CRUD operations, pagination, rate limits, and the patterns that work in production.'
canonical_url: 'https://www.business-automated.com/tutorials/airtable-api-beginners-guide'
md_url: 'https://www.business-automated.com/tutorials/airtable-api-beginners-guide.md'
last_updated: 2026-08-31
---

The Airtable REST API turns a base into a programmable database. Anything the UI can do — read, search, filter, create, update, delete, manage attachments — the API does too. Learning the API is the bridge from "Airtable is a tool I click in" to "Airtable is a backend my code can use."

This guide walks through the API from zero. By the end you'll have authenticated, made requests, handled pagination and rate limits, and written code that's safe to run in production. All examples use plain `curl` for clarity; production code will use a client library (covered at the end).

## Step 1: Get a Personal Access Token

Airtable replaced legacy API keys with Personal Access Tokens (PATs) in 2024. PATs are scoped — they specify which bases they can access and what they can do.

1. Go to [airtable.com/create/tokens](https://airtable.com/create/tokens).
2. Click **Create new token**.
3. Name it (e.g. "My first API token").
4. Add scopes:
   - `data.records:read` — read records.
   - `data.records:write` — create, update, delete records.
   - `schema.bases:read` — read base/table/field metadata.
5. Add base access — pick the specific bases the token can access. Avoid all-workspace access unless you really need it.
6. Click **Create token**.
7. **Copy the token immediately.** Airtable shows it once and never again.

For a deeper walkthrough including OAuth alternatives, see our [PAT guide](/tutorials/airtable-personal-access-token-guide).

## Step 2: Find Your Base ID

Every Airtable base has a unique ID starting with `app`. Two ways to find it:

1. Open the base in Airtable. The URL looks like `https://airtable.com/appXXXXXXXXXXXXXX/tblYYYYYYYYYYYYYY/...`. The `app...` portion is your Base ID.
2. Go to [airtable.com/api](https://airtable.com/developers/web/api/introduction), pick the base, and the docs page shows the Base ID prominently.

The same docs page shows every table's ID and field IDs — useful reference material.

## Step 3: Make Your First Request

The base URL for the Airtable API is:

```text
https://api.airtable.com/v0/{baseId}/{tableIdOrName}
```

Substitute your Base ID and table name (URL-encoded if it contains spaces):

```bash
curl https://api.airtable.com/v0/appXXXXXXXXXXXXXX/Tasks \
  -H "Authorization: Bearer pat_xxxxxxxxxxxxx"
```

You'll get back JSON like:

```json
{
  "records": [
    {
      "id": "recAAAAAAAAAAAAAA",
      "createdTime": "2026-04-15T10:30:00.000Z",
      "fields": {
        "Name": "Set up onboarding",
        "Status": "Done",
        "Due Date": "2026-04-20"
      }
    }
  ]
}
```

Each record has an `id` (the unique record ID, used for updates and links), a `createdTime`, and `fields` containing the actual field values.

## Step 4: Filtering and Sorting

The API supports several query parameters:

| Parameter | Purpose |
| --- | --- |
| `view` | Scope results to a specific view |
| `filterByFormula` | Filter with an Airtable formula |
| `sort[0][field]` and `sort[0][direction]` | Order results |
| `fields[]` | Return only specific fields |
| `maxRecords` | Cap total records returned |
| `pageSize` | Records per page (default 100, max 100) |

Example: get only open high-priority tasks, sorted by due date:

```bash
curl -G "https://api.airtable.com/v0/appXXXX/Tasks" \
  -H "Authorization: Bearer pat_xxxx" \
  --data-urlencode "filterByFormula=AND({Status}='Open', {Priority}='High')" \
  --data-urlencode "sort[0][field]=Due Date" \
  --data-urlencode "sort[0][direction]=asc"
```

`filterByFormula` accepts any [Airtable formula](/tutorials/airtable-formulas-cheat-sheet) that returns true/false per record.

## Step 5: Pagination

The API returns up to 100 records per request. When more exist, the response includes an `offset` cursor:

```json
{
  "records": [...],
  "offset": "itrXXXX/recXXXX"
}
```

To get the next page, repeat the request with `offset=...`:

```bash
curl -G "https://api.airtable.com/v0/appXXXX/Tasks" \
  -H "Authorization: Bearer pat_xxxx" \
  --data-urlencode "offset=itrXXXX/recXXXX"
```

Loop until the response no longer includes `offset`. **Always paginate** — never assume one request returns the whole table.

## Step 6: Creating Records

POST to `/v0/{baseId}/{tableId}` with a JSON body:

```bash
curl -X POST https://api.airtable.com/v0/appXXXX/Tasks \
  -H "Authorization: Bearer pat_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "records": [
      {"fields": {"Name": "New task", "Status": "Open", "Priority": "High"}}
    ]
  }'
```

Up to 10 records per request — batch when creating many.

Common field type formats:

| Field Type | JSON Format |
| --- | --- |
| Single line / Long text | `"text value"` |
| Number / Currency / Percent | `123.45` |
| Date | `"2026-06-15"` |
| Date and time | `"2026-06-15T14:00:00.000Z"` |
| Single select | `"Option Name"` |
| Multi-select | `["Option 1", "Option 2"]` |
| Linked record | `["recXXXX", "recYYYY"]` (array of IDs) |
| Checkbox | `true` or `false` |
| Attachments | `[{"url": "https://..."}]` |

## Step 7: Updating Records

Two methods:

- **PATCH** — update specified fields only (partial update).
- **PUT** — replace all fields (anything not specified is cleared).

PATCH is what you want 99% of the time:

```bash
curl -X PATCH https://api.airtable.com/v0/appXXXX/Tasks \
  -H "Authorization: Bearer pat_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "records": [
      {"id": "recAAAA", "fields": {"Status": "Done"}}
    ]
  }'
```

Up to 10 records per request, same as create.

## Step 8: Deleting Records

DELETE with record IDs as query parameters:

```bash
curl -X DELETE "https://api.airtable.com/v0/appXXXX/Tasks?records[]=recAAAA&records[]=recBBBB" \
  -H "Authorization: Bearer pat_xxxx"
```

Up to 10 deletions per request.

## Step 9: Upsert (Create or Update)

The API supports upserts via a single POST request:

```bash
curl -X POST https://api.airtable.com/v0/appXXXX/Tasks \
  -H "Authorization: Bearer pat_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "performUpsert": {
      "fieldsToMergeOn": ["External ID"]
    },
    "records": [
      {"fields": {"External ID": "ABC123", "Name": "Hello"}}
    ]
  }'
```

If a record exists with `External ID = "ABC123"`, it's updated. If not, it's created. Use this pattern for sync scripts where you don't want to write your own "search then create or update" logic.

## Step 10: Rate Limits and Production Patterns

The hard limits:

- **5 requests per second per base.** Exceed and get a 429 with a 30-second cooldown.
- **10 records per request** for create/update/delete.
- **100 records per request** for list/search.

For batch operations:

```python
import time

for batch in chunks(records, 10):
    response = create_records(batch)
    time.sleep(0.25)  # 4 req/sec safe margin
```

For high-volume sync, consider:

- **Webhooks API** for change-data-capture instead of polling.
- **Caching** — keep a local copy of slowly-changing reference data.
- **Enterprise tier** — higher rate limits available on request.

## Step 11: Use a Client Library

Curl works for learning. For production, use an official or community client library:

| Language | Library |
| --- | --- |
| **JavaScript / TypeScript** | `airtable` (official) |
| **Python** | `pyairtable` (community, well-maintained) |
| **Go** | `mehanizm/airtable` |
| **Ruby** | `airrecord` |

Example with pyairtable:

```python
from pyairtable import Api

api = Api('pat_xxxx')
table = api.table('appXXXX', 'Tasks')

# List, with auto-pagination
records = table.all(formula="{Status}='Open'")

# Create
table.create({'Name': 'New task', 'Status': 'Open'})

# Update
table.update('recAAAA', {'Status': 'Done'})

# Upsert
table.batch_upsert(records, key_fields=['External ID'])
```

For Python specifically, see our [Airtable with Python guide](/tutorials/airtable-python-guide).

## Common Mistakes

**Mistake 1: Hardcoding PATs in code.** Use environment variables. Commit a token to GitHub and it ends up in attack scripts within hours.

**Mistake 2: Single requests for batch operations.** 100 individual creates take 100 requests + 25 seconds of rate-limit delay. One batched call per 10 records is 90% faster.

**Mistake 3: Not handling 429 errors.** Production code must catch 429 and back off. Sleep 30 seconds, retry, escalate if it persists.

**Mistake 4: Filtering client-side.** Pulling 50,000 records to filter them in code wastes bandwidth and burns rate limit. Use `filterByFormula` server-side.

**Mistake 5: Using table names instead of IDs.** Names break if anyone renames the table. Use the `tbl...` ID for stable references.

## Troubleshooting

**401 Unauthorized.** PAT is wrong, expired, or doesn't have access to the base. Confirm via the Airtable API docs page for the base.

**403 Forbidden.** PAT is valid but lacks the required scope. Add `data.records:write` if you're getting this on a POST/PATCH.

**404 Not Found.** Base ID or table ID/name is wrong. Double-check both.

**422 Unprocessable Entity.** Field values don't match the schema. Most often: passing a string where a number is expected, or an unknown single-select option.

**429 Too Many Requests.** Rate limited. Back off 30 seconds, then retry. Reduce request frequency or batch more aggressively.

## Next Steps

The API is the foundation for any serious Airtable integration. Once you're comfortable with CRUD operations and pagination, the natural next steps are: building a sync script between Airtable and another system, integrating Airtable into your product backend, and writing scripts that automate data cleanup and reporting tasks.

For deeper dives, see our [finding Airtable IDs guide](/tutorials/find-airtable-api-key-base-id), [Python guide](/tutorials/airtable-python-guide), [scripting guide](/tutorials/airtable-scripting-guide), and [webhooks guide](/tutorials/airtable-webhooks-guide). For production integrations that need to be reliable at scale, [get in touch](/contact).


## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
