Airtable (Personal Access Token)

This guide walks you through using an Airtable base as a scheduled, refreshable data source in DashboardFox via the Airtable Web API and a Personal Access Token (PAT).

Airtable connects through DashboardFox's generic REST API integration. A Personal Access Token is simple to set up, doesn't expire, and is created entirely inside Airtable. This is the recommended and supported path.


Prerequisites

Before starting, confirm you have:

  • An Airtable account with the base you want to import, and permission to create a Personal Access Token.

  • DashboardFox admin access for the integration setup.

  • The Airtable base prepared per Part 1 — field types matter more than you'd expect, and getting them right up front saves casting work later.

DashboardFox Cloud: each Airtable table you import is one API Endpoint and counts against your plan's endpoint limit. A base with three tables you want to report on = three endpoints. Self-hosted DashboardFox has no endpoint limit.


A Note on OAuth2

Airtable does support OAuth 2.0, but its implementation requires PKCE (Proof Key for Code Exchange) — a per-session generated secret that is hashed into the authorization request and presented again during token exchange. DashboardFox's OAuth2 forms store static parameter values and cannot generate or carry a per-session PKCE secret.

Use a Personal Access Token. Airtable PATs do not expire, are scoped to specific bases, and can be revoked at any time from the Airtable UI. For a server-to-server BI integration, a PAT is the correct choice regardless.

Legacy API keys no longer work. Airtable disabled account-level API keys on February 1, 2024. If you find an older guide referencing an API key beginning with key…, it's out of date. Personal Access Tokens (pat…) are the replacement.


Part 1. Prepare Airtable

1. Create a Personal Access Token

  • In Airtable, open the Builder hubPersonal access tokensCreate new token.

  • Give it a name (e.g., DashboardFox).

  • Add the scope data.records:read. That's the only scope this integration needs — DashboardFox reads records; it never writes.

  • Under Access, grant the token access to the specific base you want to import. Grant only what you need.

  • Click Create token and copy the full token immediately — Airtable shows it once.

Copy the whole thing. A PAT looks like patAbC123XyZ.0123456789abcdef0123456789abcdef… — an ID, a period, then a long secret. Both halves are required. Copying only the part before the period produces an authentication failure that looks like a wrong-token error.

2. Prepare Your Table for API Consumption

Airtable returns JSON typed according to each field's type, and DashboardFox stores every column as text. Setting field types correctly in Airtable is what makes the data cast cleanly downstream.

  • Set real field types. A column of true/false stored as Single line text is not the same as a Checkbox field — the API returns "true" (a quoted string) for the former and true (a real boolean) for the latter. The same applies to numbers: a Number field returns 147113.38, while the same value in a text field returns "147113.38" and may carry stray symbols. Convert your fields to their proper types before importing.

  • Prefer simple field types for a first integration: Single line text, Long text, Number, Currency, Percent, Date, Checkbox, Single select, Autonumber. These map to one clean column each.

  • Complex field types create extra tables. Multiple select, Linked records, and Attachments return JSON arrays, which DashboardFox flattens into additional child tables. See Limitations.

  • Field names become column names, lowercased with spaces converted to underscores (Close Dateclose_date). Avoid special characters. Renaming a field in Airtable renames the column and will break existing reports.

  • Empty values are omitted, not nulled. Airtable leaves a field out of a record entirely when it's empty — including unchecked checkboxes. This has a practical consequence: a column only exists in DashboardFox if at least one record in the fetch has a value for it. See Limitations.

  • Dates: Airtable date fields return ISO format (2026-01-12), which casts cleanly. Date fields with the time option enabled return full ISO 8601 UTC timestamps.

  • Percentages: Airtable stores and returns the underlying decimal (0.05 for 5%), which is what you want.

These rules match the prep philosophy of our Excel/CSV Import lesson — set types correctly at the source, save downstream pain.

3. Get the Base ID and Table ID

Open your table in a browser and look at the URL:

https://airtable.com/app5BOcO3r3DQAMNj/tbl6Oo79Cc75H850p/viwGAmzABiKtoS7GA
└── Base ID ──┘ └── Table ID ──┘ └── View ID ──┘
  • The segment beginning app… is your Base ID.

  • The segment beginning tbl… is your Table ID.

  • The viw… segment is a view ID — not needed.

Use the Table ID, not the table name. The API accepts either, but the ID never changes. If you use the table's name and someone renames the table in Airtable, the endpoint breaks. The ID also avoids URL-encoding problems with spaces.

You now have three values: PAT, Base ID, and Table ID.


Part 2. Configure the API in DashboardFox

1. Create the API Container

  • Log in to DashboardFox as an Admin.

  • Navigate to Settings → Integrations → Create App → APIs.

  • Fill in the form:

    Field

    Value

    API Name

    Airtable (or a name identifying this connection, e.g., Airtable — Sales Pipeline)

    API Description

    Optional. Useful for documenting which base this connects to.

    API Connection

    Select Manual from the dropdown.

  • Click Continue.

You'll land on the Register New API screen with sections for API Connection List, API Authorization List, Api Refresh Token, and Api Endpoints.

Skip the first three sections. Because Airtable uses a Personal Access Token rather than an OAuth2 flow, there is nothing to authorize and no token to refresh — the token goes directly on the endpoint as a header. The Manual connection type still displays these sections, but you don't need them. Go straight to Api Endpoints.

2. Add the Endpoint

Each Airtable table becomes one endpoint.

  • Under Api Endpoints, click Add Endpoint.

  • Fill in the form:

    Field

    Value

    Endpoint Name

    The table name, e.g., Sales_Pipeline

    Response By Name

    records (the Airtable API returns record data under a records array)

    Method

    GET

    Request URL — name

    request_url

    Request URL — value

    https://api.airtable.com/v0/{BASE_ID}/{TABLE_ID}

Substitute {BASE_ID} and {TABLE_ID} with the values from Part 1 Step 3. A finished URL looks like:

https://api.airtable.com/v0/app5BOcO3r3DQAMNj/tbl6Oo79Cc75H850p

3. Add the Parameters

Click Add New Parameter three times and configure each row as follows:

Name

Param Type

Value

Is Query Param

Authorization

Is Header

Bearer patAbC123XyZ.0123456…

unchecked

offset

Is Offset

offset

unchecked

pageSize

Records Per Page

100

unchecked

Three things here are easy to get wrong and each produces a different failure:

You must type Bearer yourself. The Value field is sent to Airtable verbatim as the header value, with no prefix added. It must read Bearer patAbC123XyZ.0123456… — the word Bearer, one space, then the full token. Pasting only the token produces an AUTHENTICATION_REQUIRED error that looks like the token is wrong when it isn't.

Use "Is Header", not "Is Auth Header". These are different. Is Auth Header is for OAuth2 connections, where DashboardFox looks up a stored access token — it will not work with a PAT. Is Header sends your literal value, which is what you want.

The offset parameter's two fields do different jobs. Name (offset) is the query parameter DashboardFox sends to request the next page. Value (offset) is the field in Airtable's response DashboardFox reads the next-page token from. They happen to be the same word for Airtable. If the Value is wrong, the fetch silently stops after the first 100 records.

About pageSize: 100 is Airtable's maximum and its default. Use the Records Per Page param type — not Is Page. Is Page is for APIs that paginate by page number; Airtable paginates by token.

  • Click Save.


Part 3. Fetch and Preview the Data

1. Fetch

  • On the endpoint row, open the Actions menu (the three-dot menu on the right) and click Connect.

  • A status indicator shows the fetch in progress.

  • DashboardFox pulls 100 records per request and follows Airtable's pagination automatically until every record is retrieved. Airtable limits each base to 5 requests per second; DashboardFox throttles itself to stay within that. A 1,000-record table takes a few seconds; 50,000 records takes a few minutes.

  • A green success bar confirms completion.

2. Preview

  • From the Actions menu, click Preview.

  • A dropdown appears with the tables DashboardFox created from the API response:

    Table

    Contents

    api_{apiId}_{endpointId}_records_fields

    Your data — one column per Airtable field. This is the table your reports will use.

    api_{apiId}_{endpointId}_records

    The Airtable record id (e.g., rec0DxiE74pxNxwCx) and createdTime.

    api_{apiId}_{endpointId}_records_parent

    Pagination bookkeeping. Ignore it.

The data is in _records_fields. If you open _records and see only record IDs and timestamps, that's expected — it isn't a failed import. Airtable nests the actual field values one level down, and DashboardFox mirrors that structure.

  • Select api_{apiId}_{endpointId}_records_fields and click Load.

  • Verify the data looks correct: row count matches your Airtable table, columns match your fields, values look right.

  • If something is wrong, edit the endpoint, then use Purge & Connect from the Actions menu to rebuild the tables from scratch.

3. Note the Table Names

Write down both:

api_{apiId}_{endpointId}_records_fields ← your data
api_{apiId}_{endpointId}_records ← record IDs

You'll join these two in App Builder.

4. Repeat for Each Table

For every Airtable table you want to import, repeat Part 2 Step 2 through Part 3 with a new endpoint, changing the Endpoint Name and the {TABLE_ID} segment of the URL. The Base ID and the Authorization, offset, and pageSize parameters are the same each time.


Part 4. Build a Database App on the Fetched Data

This is the second half of the setup, and it's the step most people miss.

DashboardFox stores fetched API data as tables inside its own internal PostgreSQL database. The Manage API section creates those tables — but it does not create an app. To report on the data, you create a normal Database app pointed at that internal Postgres, exactly as you would for any other database.

1. Get the Database Credentials

DashboardFox Cloud: Go to Settings → Integrations → Database Credentials tab. Host, database name, user, and password are shown there.

Self-hosted DashboardFox:

Field

Value

Host

localhost

Database

dashboardfox

User

postgres

Password (Windows)

dashboardfox

Password (Linux)

Run sudo cat /root/.passwords on the server

These credentials only work from inside DashboardFox. The internal database isn't exposed externally — pointing pgAdmin or another external tool at it won't work, and that boundary is intentional.

2. Create the Database App

  • Go to Settings → Integrations → Create App → Database.

  • Fill in:

    Field

    Value

    App Name

    A friendly name, e.g., Airtable Sales Pipeline

    Database Driver

    PostgreSQL

    Host / Database / User / Password

    From Step 1 above

  • Click Test Connection, then Save & Apply.

3. Grant Yourself the App Builder Role

  • Go to Settings → Security → Apps.

  • Find your new app, click Edit, and assign yourself the App Builder role.

  • Save.


Part 5. Build the App in App Builder

  • Open App Builder and find your app.

  • Drag both tables into the semantic layer:

    • api_{apiId}_{endpointId}_records_fields

    • api_{apiId}_{endpointId}_records

  • Create the join:

    api_..._records_fields.id_yurbi = api_..._records.id_yurbi

    id_yurbi is a row identifier DashboardFox assigns during the fetch. It links each record's field values to its Airtable record ID and creation timestamp.

  • Apply data type casts on date, numeric, and checkbox columns — see the table below.

  • Build reports following the lessons in our Academy.

Don't use id_yurbi as a business key. It's positional and gets reassigned on every fetch — the same Airtable record can have a different id_yurbi after the next refresh. If you need a stable identifier (for drill-through, deduplication, or joining to another system), use the Airtable record id from the _records table. It never changes.


Airtable Prep Best Practices — App Builder Cast Formulas

Every column imports as text. When your Airtable field types are set correctly per Part 1 Step 2, they cast cleanly:

Airtable Field Type

Imported Value

App Builder Cast Formula

Single line text / Long text

text

leave as-is

Number (integer)

51

[field_name]::INTEGER

Number (decimal) / Currency

147113.38

[field_name]::NUMERIC

Percent

0.05 (the decimal)

[field_name]::NUMERIC

Date

2026-01-12

[field_name]::DATE

Date with time

ISO 8601 UTC

[field_name]::TIMESTAMP

Checkbox

True when checked, empty when unchecked

CASE WHEN UPPER([field_name]) = 'TRUE' THEN true ELSE false END

Single select

text

leave as-is

Autonumber

1042

[field_name]::INTEGER

Formula / Rollup

depends on the result type

cast per the result type

The checkbox formula handles the empty case deliberately. Airtable omits unchecked checkboxes from the API response entirely, so unchecked records arrive with no value rather than False. The ELSE false branch converts those empties to false, which is almost always what you want. If you need to distinguish "unchecked" from "field didn't exist," you'll need a different approach — contact support.


Part 6. Schedule Automated Refreshes (Optional)

For ongoing automatic updates from Airtable:

  • From the endpoint's Actions menu, click Schedule.

  • Configure the cadence — hourly, daily, weekly, etc.

  • Save.

Each fetch replaces the previous data — the table is purged and repopulated, so no stale rows accumulate.

Airtable's rate limit is 5 requests per second per base, and DashboardFox throttles itself to stay under it. However, if you have several endpoints against the same base scheduled at the same time, they can collide and trigger rate limiting. Stagger their schedules by a few minutes.

Free and Team plan API caps. Airtable's Free plan allows 1,000 API calls per month and the Team plan 100,000. Each page of 100 records is one call. A 5,000-record table refreshed hourly is 50 calls per fetch × 24 × 30 = 36,000 calls/month — which would exhaust a Free plan in under a day. Match your schedule to your plan.


Limitations

  • Complex field types create additional tables. Multiple select, Linked records, and Attachments return JSON arrays. DashboardFox flattens these into extra child tables alongside _records_fields. This works, but the resulting structure varies by field type and hasn't been characterized for every case. Test with a small table first, and consider using Airtable formula fields to flatten arrays to text (e.g., ARRAYJOIN({Tags}, ", ")) before importing.

  • Empty values are omitted, not nulled. Airtable leaves empty fields out of the response entirely. If no record in the table has a value for a given field, that column won't exist in DashboardFox at all. Once at least one record has a value, the column appears on the next fetch and DashboardFox adds it to the existing table automatically.

  • Field and table renames break the integration. Renaming an Airtable field renames the DashboardFox column, breaking reports built on it. Renaming a table breaks the endpoint only if you used the table name instead of the Table ID in the URL — another reason to use the ID.

  • All views are ignored. The endpoint URL targets the table, so every record is returned regardless of any view filters. To limit which records are pulled, use Airtable's view or filterByFormula query parameters — add them as additional parameters on the endpoint (Name view, Value your viw… ID). Contact support if you need help with this.

  • Very large tables can hit a pagination timeout. Airtable's pagination token can expire mid-fetch on very large tables, producing a LIST_RECORDS_ITERATOR_NOT_AVAILABLE error. Airtable's own guidance is to restart the fetch. If this recurs, reduce the table size or filter it with a view.

  • Airtable plan record limits. The Free plan caps a base at 1,000 records; paid tiers allow substantially more. This is an Airtable limit, not a DashboardFox one.

  • id_yurbi is not stable across fetches. Use the Airtable record id for anything that needs a durable identifier.

  • Data is a snapshot, not live. DashboardFox reports against the fetched copy. Changes in Airtable appear only after the next Connect or scheduled fetch.


Troubleshooting

Symptom

Likely cause

Fix

AUTHENTICATION_REQUIRED — "Authentication required"

The Bearer prefix is missing from the Authorization parameter's Value, or the token was truncated at the period

Value must read Bearer patXXX.YYYY… — the word Bearer, a space, then the entire token including everything after the period

NOT_AUTHORIZED / 403

The PAT doesn't have access to this base, or is missing the data.records:read scope

Edit the token in Airtable's Builder hub — add the base under Access and confirm the scope

NOT_FOUND / 404

Wrong Base ID or Table ID

Re-copy both from the Airtable URL — app… is the base, tbl… is the table

INVALID_REQUEST_UNKNOWN — "parameter validation failed"

The offset parameter has Is Query Param checked

Uncheck Is Query Param on the offset parameter and re-Connect

Only 100 records imported

The offset parameter is missing, or its Value isn't offset

Add/edit the parameter: Name offset, Param Type Is Offset, Value offset

Far fewer records than expected, or odd page sizes

pageSize was saved with Param Type Is Page instead of Records Per Page

Edit the parameter and change Param Type to Records Per Page

Object reference not set to an instance of an object

This is a downstream symptom, not the real error — Airtable returned an error and DashboardFox tried to refresh a token that doesn't exist on a Manual connection

Look at the trace details above this message. The first entry is the actual Airtable error — start there

LIST_RECORDS_ITERATOR_NOT_AVAILABLE

Airtable's pagination token expired mid-fetch

Re-run Connect. If it recurs on a very large table, filter it down with a view

A checkbox column is missing entirely

No record in the table had the box checked — Airtable omits unchecked boxes

Check at least one record and re-Connect

Checkbox values import as lowercase true instead of True

The Airtable field is a text field containing the word "true", not a real Checkbox field

Change the field type in Airtable to Checkbox, then Purge & Connect

Numbers import with $ or , in them, and casts fail

The Airtable field is a text field, not Number or Currency

Change the field type in Airtable, then Purge & Connect

_records table looks almost empty — just IDs and timestamps

You're looking at the wrong table

Your data is in _records_fields

A column you expected is missing

Every record in the fetch had that field empty — Airtable omitted it

Populate at least one record and re-Connect

Can't connect the Database app

Wrong credentials, or values copied from the wrong row

Cloud: Settings → Integrations → Database Credentials. Self-hosted: see Part 4 Step 1

New app isn't visible in App Builder

The App Builder role wasn't granted

Settings → Security → Apps → Edit the app → assign App Builder → Save

Scheduled fetches fail intermittently, several endpoints on one base

Multiple endpoints hitting the same Airtable base simultaneously trip the 5 req/sec limit

Stagger the schedules a few minutes apart

For unresolved issues, contact team@dashboardfox.com.


Related Articles