# Airtable

Push submissions into an Airtable base with typed field mapping.

## Airtable

Send every submission to an Airtable table as a new record. Map fields to typed columns, compose a rich-text body, and backfill past responses.

<h2 id="what-you-get">What you get</h2>

<ul>
  <li>One record per submission</li>
  <li>Field-level mapping with type compatibility checks</li>
  <li>Metadata mapping, including a link to the generated submission PDF</li>
  <li>Optional rich-text body field with headings, bold, lists, and piped answers</li>
  <li>Backfill existing submissions on connect (batches of 10)</li>
  <li>Auto-recovery when columns are renamed</li>
  <li>Test record to verify the connection before real submissions arrive</li>
</ul>

<h2 id="connect">Connect Airtable</h2>

<h2 id="column-types">Column types</h2>

<p>formbase auto-creates select options when the submitted value doesn't match an existing option.</p>

<p>
  Formula, rollup, count, lookup, linked record, collaborator, created/modified time, created/modified by, auto-number, button, and
  synced-source columns are read-only and cannot be mapped.
</p>

<h2 id="repeating-groups">Repeating groups</h2>

<p>
  A <a href="/building-forms/repeating-groups">repeating group</a> lets respondents add as many entries as they need — like a list of
  guests, each with a name and age. In the field picker you choose how to map it:
</p>

<ul>
  <li>
    <strong>The whole group</strong> maps to one field. Every entry shows as numbered, labeled rows, like "1. Full name: Jane Appleseed,
    Age: 34, 2. Full name: Marcus Lee, Age: 29".
  </li>
  <li>
    <strong>Each member field</strong> maps to its own field. The values from every entry join with <code> · </code>, so the Full name field
    reads "Jane Appleseed · Marcus Lee".
  </li>
</ul>

<p>
  Pick one, the other, or both. If you remove a member field from your form later, it still appears in the picker so past records keep their
  field — your mapping never breaks.
</p>

<h2 id="rich-text-body">Rich-text body</h2>

<p>
  If your table has a Rich text, Long text, or Single line text column, you can compose its content with the template editor. Type{' '}
  <strong>@</strong> to insert any form field value or metadata such as PDF Link — the editor shows them as mention chips that resolve at
  sync time. Rich text columns preserve formatting; other column types receive plain Markdown.
</p>

<p>
  Supported formatting: headings (H1-H4), <strong>bold</strong>, <em>italic</em>, ~~strikethrough~~, <code>inline code</code>, links, and
  ordered/unordered lists. Images and embeds are not supported.
</p>

<h2 id="backfill">Backfill existing submissions</h2>

<p>
  After connecting, you can backfill past responses. Records are written in batches of 10 with a short delay between batches to stay within
  Airtable's rate limits. Progress is shown in the integration panel.
</p>

<h2 id="test-event">Test event</h2>

<p>
  The Finalize step and the integration detail panel both have a <strong>Send test</strong> button that writes a placeholder record. Text
  columns get <code>[Question Title]</code> strings, numbers get <code>0</code>, emails get <code>test@example.com</code>, dates get the
  current timestamp, and selects use the first option from the question's choices (to avoid creating stray options). Delete the test record
  after verifying.
</p>

<h2 id="abandoned-responses">Abandoned response events</h2>

<p>
  If a respondent starts your form but doesn't finish, formbase can still sync the partial data. On the{' '}
  <strong>Abandoned submissions</strong> step, set <strong>Send abandoned event after</strong> to 12 hours, 1 day, 3 days, or 1 week. An
  hourly sweep then writes a record using the same field mapping as a completed submission. Map the "Submission status" metadata field to a
  single-select or text column to tell "Partial" records from "Completed" and "Updated" ones.
</p>

<p>
  Only drafts from a share link are swept, and <strong>Required fields</strong> narrows it further: the record is written only when at least
  one of the fields you pick was filled in.
</p>

> ℹ️ **Pro feature**
> <p>
>     Abandoned response delivery requires a Pro or Business plan. The core Airtable integration is available on all plans. See{' '}
>     <a href="/subscription-billing/plans-pricing">plans & pricing</a>.
>   </p>

<h2 id="schema-drift">Schema changes and auto-recovery</h2>

<p>
  If you rename a column in Airtable, formbase detects the change on the next submission and updates its mapping automatically. Columns are
  matched by their stable internal ID, so renames are transparent.
</p>

<p>
  If you delete a column, formbase drops it from the mapping and keeps syncing the remaining fields. If a column's type changes to something
  incompatible, the value fails to sync — re-open the integration and re-map that field.
</p>

<h2 id="troubleshooting">Troubleshooting</h2>

<ul>
  <li>
    <strong>Authorization expired</strong> — Airtable access tokens last about an hour and are refreshed automatically, both by a daily job
    and before each delivery. If the refresh itself fails — the grant was revoked, or the refresh token expired — the connection is marked
    expired and every integration on it stops. Press Reconnect.
  </li>
  <li>
    <strong>Column not visible</strong> — Confirm the OAuth grant includes the base and the column type is writable (see table above).
  </li>
  <li>
    <strong>Rate limit</strong> — Airtable enforces 5 requests/second per base. Backfills throttle automatically; live syncs retry with
    backoff.
  </li>
</ul>

<h2 id="faq">FAQ</h2>

  <p>
    Four Airtable scopes: read/write record data, read base schemas, and read your email (to identify the account). Uses OAuth with PKCE —
    no API keys to manage.
  </p>

  <p>Yes. Airtable connections are workspace-scoped. Any member can use any connected account when setting up an integration.</p>

  <p>Yes. Authorize additional accounts during new integration setups. Each form picks which account to use.</p>

  <p>
    The next submission fails with a "not found" error and the integration stops. The base and table are fixed when the integration is
    created, so delete this integration and create a new one against the new table.
  </p>

  <p>
    No. These are read-only in Airtable's API. See the full list of excluded column types in the <a href="#column-types">column types</a>{' '}
    section.
  </p>

  <p>
    Go to Form settings → Integrations → Airtable and delete the integration. To also revoke formbase's access, go to your Airtable account
    settings and remove the formbase OAuth app.
  </p>

<h2 id="next-steps">Next steps</h2>
<div class="not-prose grid gap-3 sm:grid-cols-2">
  - [Linear](/integrations/linear) — Turn submissions into Linear issues
  - [GitHub Issues](/integrations/github) — Turn submissions into GitHub issues
  - [Repeating groups](/building-forms/repeating-groups) — Let respondents add multiple entries
</div>
