Airtable Base Schema Auditor & Link Checker avatar

Airtable Base Schema Auditor & Link Checker

Pricing

from $0.50 / base audited

Go to Apify Store
Airtable Base Schema Auditor & Link Checker

Airtable Base Schema Auditor & Link Checker

Audit any Airtable base with a read-only token. Ranked findings for broken formulas, links into empty tables, duplicate field names, text columns holding dates, and invite links that give strangers edit access. Scorecard per base plus a shareable HTML report.

Pricing

from $0.50 / base audited

Rating

0.0

(0)

Developer

Mediocre_Interest

Mediocre_Interest

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Audit any Airtable base with a read-only token and get a ranked list of what is wrong with it — broken formulas, links into empty tables, near-duplicate field names, text columns holding dates, credentials typed into field descriptions, and reusable invite links that hand strangers edit access. Every base also gets a health score out of 100 and a shareable HTML report you can send to whoever owns it.

Press Start with nothing filled in and the Actor audits two bundled sample bases — one deliberately broken, one correctly built — so you can read real output before connecting an Airtable account. No LLM and no guesswork: the same schema always produces the same findings.

  • One read-only scope. The whole rule set runs on schema.bases:read. Record sampling is the only thing that asks for a second scope, and it is off by default.
  • 26 checks across five packs, each finding carrying the evidence it read, so you can verify any one of them in your base in seconds.
  • Nothing is written to your Airtable. Every request is a GET.

What does the Airtable Base Schema Auditor do?

Airtable makes it easy to add a field and hard to notice the cost later. Delete a column a formula reads and the formula keeps its place in every view, showing an error in every record. Rename a column with a trailing space and Airtable accepts it as a second, separate field, because it only blocks exact, case-insensitive duplicates. Share a base with a reusable invite link and there is no page that lists every link still outstanding across your workspace.

This Actor reads a base's schema — the same structure Airtable's metadata API returns — and runs 26 fixed rules over it. Optionally it also samples a few records per table, which is what lets it tell an always-empty column from a sparse one and a text field holding dates from a real text field. Every finding is one row naming the table, the field, the evidence and the fix. Every base also gets a scorecard: a score out of 100, a grade, and an honest account of which checks could and could not run against your token.

The exposure checks are the ones without an equivalent anywhere in Airtable's own interface. A base's invite links, its collaborator domains and its workspace sharing settings are each visible one dialog at a time; this reads all of them across every base a token can see, in one run.

Which Airtable base problems does it find?

Every finding carries its rule id, its pack and a confidence of high (read straight off the schema), medium (measured from a record sample) or low (an English-language name heuristic).

Exposure — who can reach this base, and what leaves it when they do

RuleSeverityWhat it catches
secret-in-descriptioncriticalA credential-shaped string in a field or table description — Stripe, Slack, GitHub, AWS, Google, Airtable keys and bearer tokens. The finding reports the pattern, the offset and the length, never the value.
open-invite-linkcriticalA reusable invite link granting edit or above to anyone holding the URL, with no email-domain restriction. high when the link is read-only.
collaborators-across-domainsmediumThe base is shared with people from two or more email domains. Carries domains and counts only — no address ever reaches the output.
workspace-shares-unrestrictedmediumAnyone with edit access in the workspace can create a public share link.
lookup-exposes-piimediumA lookup pulls a personal-data field across a link into another table, where different people can see it.
pii-fieldlowA field name implies personal data (email, phone, date of birth, iban, and similar).
workspace-invites-unrestrictedlowAnyone with edit access in the workspace can invite new collaborators.
domain-restricted-invite-linklowA reusable invite link exists but is restricted to named domains — worth confirming they are still the right ones.

Links — relationships and the computed fields riding on them

RuleSeverityWhat it catches
broken-computed-fieldcriticalA formula, rollup, lookup or count Airtable reports as invalid. Two causes: the field it read was deleted, or one side of a link it travelled along was. Every record shows an error until it is fixed.
orphan-tablemediumA table with no link fields out and nothing linking in.
link-target-unreadablemediumA link points at a table this token cannot see, so the relationship is invisible to the audit.
self-referential-linklowA table links to itself. Legitimate for hierarchies — reported once per relationship, not once per field.

Values — what the records say that the schema cannot (needs record sampling)

RuleSeverityWhat it catches
text-field-wrong-typehighA text column whose every sampled value is a date, an email address, a URL or a number. A text column holding dates sorts alphabetically.
duplicate-primary-valuehighTwo records sharing a primary-field value. Airtable does not enforce uniqueness there, and the primary field is how every link and lookup identifies a record.
link-to-empty-tablehighA link into a table that returned no records, so it can never resolve to anything.
empty-tablemediumA table with no records at all.
always-empty-fieldmediumA column nobody has ever filled in, across every sampled record.

Naming

RuleSeverityWhat it catches
duplicate-field-namehighFields in one table whose names differ only in spacing, separators or case — Client Name, Client Name, Client Name . Airtable allows all three.
duplicate-field-across-tablesmediumThe same field name in two or more tables, counted by table rather than by field.

Structure

RuleSeverityWhat it catches
select-should-be-tablemediumA single- or multi-select with 20 or more options. A list that long is a table wearing a disguise.
table-named-after-datemediumA table named after a year, month or quarter — a snapshot nobody will clean up.
inconsistent-precisionlowNumber, currency or percent fields in one table rounding to different decimal places, so totals stop matching their rows.
table-no-descriptionlowA table with nothing saying what one record represents.
no-field-descriptionslowA table of five or more fields where not one is described.
default-table-namelowTable 1, Untitled, Grid 2 — a table nobody has named.
default-field-namelowA table still carrying three or more of Airtable's starter field names, none described and none filled in; or a numbered name Airtable generated, like Field 7.

Why use the Airtable Base Schema Auditor?

  • The scope ask is one line. Everything above, including both critical exposure checks, runs on a token holding schema.bases:read and nothing else. Turn on record sampling and it asks for data.records:read as well. Nothing needs write access, and no request is anything but a GET.
  • Nothing to install, and no credentials needed to start. Press Start and read the two bundled sample bases. Connect a token when you want your own.
  • Every finding shows its work. The three colliding field names, the 28 select options, the four sampled values that were all dates — the evidence column carries what the rule actually read, so a false positive is obvious in seconds rather than trusted by default.
  • A credential it finds is never republished. A dataset is shareable by URL, so secret-in-description reports the pattern it matched, how long it was and where it sat — and never the string itself. Collaborator findings carry domains and counts, never email addresses.
  • Built for agencies and consultants. One run audits every base a token can see, in parallel, and writes one scorecard row per base you can sort by grade. Workspace-wide settings are reported once per run, not once per base, so auditing forty bases in one workspace does not produce the same two findings forty times. Schedule it on Apify for a monthly sweep, export to JSON, CSV or Excel, or call it from the API.

How to audit an Airtable base

The free path, with no Airtable account at all:

  1. Open the Actor and press Start without filling anything in.
  2. Read the Findings table in the Output tab — worst first, with the evidence beside each row.
  3. Open Scorecards for the two sample bases: a broken one at 0/F and a well-built one at 97/A.
  4. Open one of the audit reports for the same thing as a page you could hand to a client.

To audit your own bases:

  1. Go to airtable.com/create/tokens and create a personal access token.
  2. Give it the schema.bases:read scope. Add data.records:read as well if you want the value checks.
  3. Under Access, add every base you want audited — a personal access token lists its bases one by one, and a base you do not add is invisible to the token.
  4. Paste the token into Airtable personal access token and press Start. Leave Bases to audit empty to audit everything the token can see.
  5. Switch on Sample records if you granted the second scope.

Input

FieldWhat it does
Airtable personal access tokenYour read-only token. Leave it empty to audit the two bundled sample bases for free.
Bases to auditBase IDs, one per line. Paste a whole base URL if that is easier — the ID is taken out of it. Empty means every base the token can see.
Rule packsWhich of the five families to run: structure, naming, links, exposure, values.
Minimum severityDrop findings milder than this from the output. It does not change the score — see below.
Sample recordsRead a few records per table so the value checks can run. Needs data.records:read. Off by default.
Records sampled per tableHow many records to read from each table. Default 100. Below 3 the wrong-column-type check cannot fire.
Maximum tables sampledStop sampling after this many tables per base. Schema checks still cover every table. Default 200.
Write a shareable HTML reportProduce a self-contained page per base, linked from that base's scorecard row.

Audit one base, with the value checks on:

{
"airtableToken": "<your Airtable personal access token>",
"baseIds": ["appJlDPhIscwb0SAf"],
"sampleRecords": true
}

Sweep every base a token can see, for exposure problems only:

{
"airtableToken": "<your Airtable personal access token>",
"rulePacks": ["exposure"],
"minSeverity": "high"
}

Output

One row per finding in the default dataset, one row per base in the Scorecards dataset, and one HTML report per base plus the run totals in the key-value store. Download either dataset as JSON, CSV, Excel or HTML from the run's Output tab.

Pressing Start with nothing filled in produces 45 finding rows. This is one of them:

{
"source": "sample",
"collectedAt": "2026-09-29T06:18:30.683Z",
"baseId": "appJlDPhIscwb0SAf",
"baseName": "A1 Audit Fixture (messy)",
"tableId": "tblR61L0Lmcv5x2zP",
"tableName": "Clients",
"fieldId": "fldBzhbIDtVkKHsjv",
"fieldName": "Vendor Key",
"fieldType": "singleLineText",
"rulePack": "exposure",
"rule": "secret-in-description",
"severity": "critical",
"confidence": "medium",
"evidence": "Matches a Stripe live secret key, 34 characters long, at position 32 of the field description. The value is deliberately not reproduced here.",
"message": "The description of \"Clients.Vendor Key\" contains a credential-shaped string.",
"remediation": "Remove it and rotate the key. Descriptions are schema, so everyone with read access to the base can already see it, and every export and integration carries it."
}

And this one, where Airtable itself allows all three spellings:

{
"tableName": "Clients",
"rulePack": "naming",
"rule": "duplicate-field-name",
"severity": "high",
"confidence": "high",
"evidence": "\"Client Name\", \"Client Name\", \"Client Name \"",
"message": "Table \"Clients\" has 3 fields whose names differ only in spacing, separators or case.",
"remediation": "Airtable only blocks exact, case-insensitive duplicates, so a trailing space or an underscore slips past. Merge them into one field and delete the spares - anyone filling in this table is currently choosing between them at random."
}

What does each finding row contain?

ColumnMeaning
severity, confidencecritical, high, medium or low; and how far the finding can be trusted.
rule, rulePackWhich check fired, and which of the five families it belongs to.
baseName, tableName, fieldName, fieldTypeWhere the problem is. Empty baseName marks a workspace-wide finding.
message, remediationWhat was found, and what to change in Airtable.
evidenceWhat the rule actually read — the colliding names, the option count, the sampled values, the sample size.
sourceairtable for your bases, sample for the bundled demo.
baseId, tableId, fieldId, collectedAtIdentifiers and the run timestamp, for joining runs together.

What does each scorecard row contain?

{
"baseName": "A1 Audit Fixture (messy)",
"score": 0,
"grade": "F",
"tableCount": 6,
"fieldCount": 40,
"linkCount": 3,
"recordsSampled": 16,
"criticalCount": 3,
"highCount": 8,
"mediumCount": 17,
"lowCount": 13,
"findingCount": 41,
"findingsReported": 41,
"packsRun": ["structure", "naming", "links", "exposure", "values"],
"packsSkipped": []
}

linkCount counts relationships, not link fields: Airtable stores one relationship as a field in each of the two tables, and the pair counts once. findingCount is everything the checks found; findingsReported is how many rows reached the dataset after Minimum severity. reportUrl links that base's HTML page.

What do packsRun and packsSkipped tell me?

They account for all five packs in three states, and the third is the one that matters: unknown is not clean. If Airtable returns no invite-link data for a base, the scorecard says so rather than reporting no invite links — an absent answer and an empty one mean opposite things, and a base with an open edit link reported as clean would be the worst thing this Actor could do. A token that can read a base but not its workspace gets exposure marked as run with the two workspace-wide checks noted as skipped.

How is the score calculated?

Each distinct rule costs its severity weight — 25 for critical, 10 for high, 4 for medium, 1.5 for low — multiplied by 1 + ln(number of findings), and capped at 25 so no single rule can sink a base. The total is subtracted from 100. Grades are A at 85 or above, B at 70, C at 55, D at 40, F below that.

Two properties follow, and both are deliberate. A rule broken forty times is one problem that is worse than one broken once but not forty times worse, so the score does not simply track base size. And Minimum severity never changes the grade — it decides what is written to the dataset, not what the base is worth. Two people auditing the same base with different filters get the same score.

The score is modelled, not measured. Use it to rank bases against each other and to watch one base over time, not as an absolute measure of quality. Workspace-wide findings are excluded from it, because they describe the workspace rather than any base inside it.

How much does it cost to audit an Airtable base?

The Actor is pay per event, at the prices shown on this page, and there are two events:

EventChargedWhen
base-auditedOnce per baseAfter that base's findings and scorecard are written
records-sampledOnce per 1,000 records readAfter the rows those records produced are written

A base is priced whole: the full cost is worked out from its schema before a single record is read, and a base your remaining credit will not cover is skipped and named rather than half-audited. Nothing is charged per finding — a linter paid per finding becomes a noisy linter. Nothing is charged for a base that could not be read, and the two bundled sample bases are free.

A typical run auditing ten bases with sampling off costs ten base-audited events. Runs are fast — the bundled demo finishes in about a second, and a real base is one request for its schema plus one per sampled table — so platform usage on top is a fraction of a cent.

How to run the audit from the API or on a schedule

An audit takes seconds, so the Actor can run synchronously — one request in, findings out:

curl -X POST "https://api.apify.com/v2/acts/mediocre_interest~airtable-schema-auditor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"airtableToken": "<your Airtable personal access token>",
"baseIds": ["appXXXXXXXXXXXXXX"],
"sampleRecords": true
}'

The response is a JSON array of the finding rows shown above. Add &format=csv for a spreadsheet, or &fields=severity,rule,baseName,tableName,fieldName,message to trim the columns. Send an empty body, {}, to get the sample findings without a token.

Apify's scheduler runs the same input weekly or monthly without any code — point it at your token and read the Scorecards table each time. The Actor is also available through Apify's integrations for Make, n8n, Zapier and Slack, and through the Apify API clients for JavaScript and Python.

Tips for better results

  • Start with Minimum severity at low. The naming and documentation findings are most of what a consultant hands over, and the Output tab sorts by severity anyway.
  • Turn on Sample records for a base you actually own. Half the value checks — always-empty columns, text fields full of dates, duplicate primary values — cannot fire without them, and they are the findings that surprise people.
  • Grant the token every base at once. A personal access token lists its bases individually, so a sweep is only as complete as the Access list on the token.
  • Read packsSkipped before you trust a clean scorecard. A base with no findings and values: unknown has not been checked for empty tables; it has been checked for everything else.
  • Re-run after fixing. Rule ids are stable, so a diff of two runs is the list of what you fixed.

FAQ

Is it safe to give this Actor an Airtable token?

The token is stored encrypted, never written to the output, and never logged — the run log shows ***. The Actor only ever sends GET requests, and the scopes it asks for cannot write anything: schema.bases:read reads structure and data.records:read reads records.

Does it change anything in my Airtable base?

No. There is no write path in the Actor at all.

What scopes does my token actually need?

schema.bases:read for every check except the value pack, including both critical exposure checks. Add data.records:read only if you switch Sample records on. Both are read-only and available on every Airtable plan.

Does the exposure pack read my colleagues' email addresses?

It reads the base's collaborator list to count how many email domains it is shared across, and it writes only the domains and the counts. No address reaches a dataset row, a report, or a log line. If you would rather it did not read them at all, leave exposure out of Rule packs.

Why did the run finish with no findings?

Either the base is clean — the scorecard then says so with a high score — or Minimum severity filtered everything out. Check findingsReported against findingCount on the scorecard: when they differ, the gap is what the filter hid. A run whose rule packs cannot reach the chosen severity warns about it in the log before doing any work.

Does it use an AI model?

No. Every finding comes from a fixed rule over the schema, which is why the same base produces identical findings on every run and why a re-run after a fix is a reliable diff.

Why is a finding marked low confidence?

Because it came from an English-language word list. The personal-data names, the date-in-a-table-name check and the Airtable starter-name lists will miss a German or Japanese base entirely. They are graded low for exactly that reason rather than presented as certainties.

Can it audit a base I have only been shared, not created?

Yes, if you can add it to a personal access token under Access. The token's own permission level decides; Base read-only is enough.

What does it not check?

View filters, view sort configuration, share-link state and automations: Airtable's API does not expose any of them at any scope, so no Actor can read them. Interfaces are returned but nothing depends on them yet.

What other Actors work with this one?

Support

Found a false positive, a rule that should exist, or a base the Actor cannot read? Open an issue on the Issues tab. Include the rule id from the row and, if you can, the shape of the field or table that triggered it — never the base's contents. Custom rule sets and portfolio reports for agencies are available on request.