# Load job postings data into Airtable

> Upsert job posts into an Airtable base in batches of ten, matched on the job ID so re-runs never duplicate records.

Page: https://jobdataapi.com/integrations/airtable/
Category: Spreadsheets and no-code
You need: Python 3.9+, pip install requests, an Airtable personal access token with write access to the base and a jobdata API key (https://jobdataapi.com/accounts/pricing/).

## Steps

1. Create a Jobs table with the fields Job ID (number), Title, Company, Location, Published and Apply link.
2. Set your jobdata API key, Airtable token and base ID.
3. The script upserts in batches of ten (Airtable's limit) and waits between requests to stay under five requests per second.

## Code

```python
import requests

API_KEY = "YOUR_API_KEY"


def fetch_jobs(**params):
    """Yield every job for the given filters, following pagination."""
    url = "https://jobdataapi.com/api/jobs/"
    params = {"page_size": 1000, **params}
    headers = {"Authorization": f"Api-Key {API_KEY}"}
    while url:
        resp = requests.get(url, headers=headers, params=params, timeout=60)
        resp.raise_for_status()
        data = resp.json()
        yield from data["results"]
        url, params = data["next"], None  # "next" already carries the filters


import time

AIRTABLE_TOKEN = "YOUR_AIRTABLE_TOKEN"
AIRTABLE_URL = "https://api.airtable.com/v0/YOUR_BASE_ID/Jobs"


def upsert(records):
    resp = requests.patch(AIRTABLE_URL, timeout=60, headers={
        "Authorization": f"Bearer {AIRTABLE_TOKEN}",
    }, json={
        "performUpsert": {"fieldsToMergeOn": ["Job ID"]},
        "records": [{"fields": fields} for fields in records],
        "typecast": True,
    })
    resp.raise_for_status()
    time.sleep(0.25)


batch = []
for job in fetch_jobs(max_age=1, title="data engineer"):
    batch.append({
        "Job ID": job["id"],
        "Title": job["title"],
        "Company": job["company"]["name"],
        "Location": job["location"],
        "Published": job["published"],
        "Apply link": job["application_url"],
    })
    if len(batch) == 10:
        upsert(batch)
        batch = []
if batch:
    upsert(batch)
```

## Notes

- Airtable bases have record limits per plan - filter to the roles or regions you actually need.
- Run it daily with max_age=1 to pick up new job posts; on access lite, drop max_age - the feed covers the past 90 days and upserting by id keeps it free of duplicates.

## Related docs

- [Jobs API Ingestion Guide: Reliable Historical Backfills and Incremental Syncs](https://jobdataapi.com/c/jobs-api-ingestion-guide-reliable-historical-backfills-and-incremental-syncs/)
- [Integrating the jobdata API with Make](https://jobdataapi.com/c/integrating-the-jobdata-api-with-make/)
- [Integrating the jobdata API with Zapier](https://jobdataapi.com/c/integrating-the-jobdata-api-with-zapier/)

