Airtable Integration Map
Status: active working map Canonical scope: Airtable touchpoints across marketing, portals, APIs, automations, and webhook handoffs Last updated: 2026-03-09
1. Runtime contract in code
Environment variables the app currently expects
| Env var | Required now | Purpose | Notes |
|---|---|---|---|
AIRTABLE_API_KEY | yes | Airtable auth for all server-side CRUD | Valid locally as of 2026-03-08 |
AIRTABLE_PARENTS_BASE_ID | yes | Parent/client/contracts base | Required for clients + contracts |
AIRTABLE_DOULAS_BASE_ID | yes | Doula/provider base | Required for doula records |
AIRTABLE_PRODUCTS_BASE_ID | optional for lead flows | Family Favorites product base | Used for product/resources content |
AIRTABLE_MARKETING_BASE_ID | no for intake cutover, yes for marketing data | Marketing content base | Needed for blog/newsletter reads |
AIRTABLE_ADMIN_BASE_ID | no for intake cutover, yes for admin finance ops | Admin ops base | Needed for admin payment workflows |
Bases and tables currently wired in code
| Base | Live tables | Code status |
|---|---|---|
PARENTS | Parent Intake Forms, Parent-Doula Matches, Active Contracts, Parents Payments, Interview Status, Closed Contracts | wired for intake, matching, interviews, contracts, and parent payment receipts |
DOULAS | TBC Doula Database, Provider Directory | partially wired |
PRODUCTS | amazon products | wired for product content |
MARKETING | Family Favorites, Blog Posts, Newsletter Signups | base is now recognized in code, field mappings still thin |
ADMIN | Admin Payments, Invoices | wired for the canonical internal contract-level payment ledger and invoice persistence |
Tables explicitly missing in the current Airtable layer
| Domain | Current state in code | Impact |
|---|---|---|
| Payments | canonical split is live in app code | client receipts and admin payout ledger now persist through Airtable |
| Invoices | ADMIN.Invoices is wired | doula invoice creation and invoice detail now persist through Airtable |
| Interviews | Interview Status table is wired | booking, reschedule, and cancellation persist through Airtable |
| Match Responses | Parent-Doula Matches is wired | doula availability + client matches now use shared Airtable state |
| Doula Availability / Time Off | TBC Doula Database stores serialized availability and time-off payloads | booking availability now persists through Airtable-backed doula records |
2. Current Airtable touchpoint matrix
| Surface | User/system action | Project entry point | Airtable target | Direction | Current state | What must exist in Airtable |
|---|---|---|---|---|---|---|
| Marketing parent intake form | parent submits intake | /parent-intake-form -> /api/clients -> | PARENTS.Parent Intake Forms | write | code-complete; production validation still controlled because automations are active | correct field names, record create permissions, follow-up automation |
| Marketing doula application form | doula submits application | /doula-sign-up -> /api/doulas public application write | DOULAS.TBC Doula Database | write | live; production validation still controlled because webhook side effects are active | application fields, onboarding status fields, follow-up automation |
| Marketing doulas directory | visitor browses doulas | /doulas -> /api/doulas | DOULAS.TBC Doula Database | read | live with Airtable fallback/mock fallback | onboarded doula records, application status values |
| Marketing provider directory | visitor browses providers | /resources/providers -> /api/providers | DOULAS.Provider Directory | read | live with Airtable fallback/mock fallback | provider listing records and directory-safe fields |
| Client list / admin intake views | admin reads client/intake data | /api/clients, /admin/intake-forms, /admin/clients | PARENTS.Parent Intake Forms | read | live | stable field names for intake + client status |
| Client detail updates | admin edits client record | /api/clients/[id] | PARENTS.Parent Intake Forms | write | live | updateable client/intake fields |
| Client conversion | admin converts approved intake into active client record | /api/clients/[id]/convert, /admin/intake-forms/[id], /admin/clients/[id] | PARENTS.Parent Intake Forms | write | live | durable conversion metadata in Note, valid status transitions, same Airtable record remains canonical |
| Doula list / admin roster | admin/directory reads doulas | /api/doulas, /admin/doulas, /doula/profile | DOULAS.TBC Doula Database | read | live | onboarded doula records and approval metadata |
| Doula detail updates | admin edits doula | /api/doulas/[id] | DOULAS.TBC Doula Database | write | validated route, Airtable-dependent | writable doula profile/application fields |
| Doula approval workflow | admin approves a doula, assigns mentor, and controls provider visibility | /api/doulas/[id]/approval, /admin/doula-applications/[id], /admin/doulas, /admin/mentors, /doula/mentor | DOULAS.TBC Doula Database + DOULAS.Provider Directory | read + write | live | Application Status, Notes, Assigned Mentor/Mentees, provider directory rows |
| Contract list and detail | admin/client/doula reads contract data | /api/contracts, /api/contracts/[id] | PARENTS.Active Contracts | read | partially wired | contract rows with status, names, amounts |
| Contract creation | admin creates contract | /api/contracts | PARENTS.Active Contracts | write | validated route, Airtable-dependent | contract fields, linked workflow for signing/payment |
| Matching workflow | admin/doula/client matching actions | /admin/matching, /doula/leads, /client/matches | PARENTS.Parent-Doula Matches | read + write | live | parent link, doula id + name, response status, source, notes, interview link; no doula contact info is stored on the match row |
| Interview workflow | client books, doula/admin tracks interview | /client/search/[id], /client/appointments, /doula/calendar, /admin/matching | PARENTS.Interview Status | read + write | live | match link, interview datetime, status, outcome, notes |
| Parent-side payment tracking | client/admin payment visibility | /api/payments, /client/payments, /admin/payments | PARENTS.Parents Payments | read + write | live | canonical external money-in ledger, one record per client payment receipt collected by TBC |
| Admin finance ops | admin reconciliation and bookkeeping | /admin/payments, /doula/invoices | ADMIN.Admin Payments | read + write | live | internal contract-level finance ledger for referral fee capture, payout state, and bookkeeping |
| Invoice persistence | doula submits payout invoice and reviews invoice detail | /doula/invoices, /doula/invoices/new, /doula/invoices/[id], /api/invoices | ADMIN.Invoices + PARENTS.Active Contracts + PARENTS.Parents Payments | read + write | live | invoice table, linked payment ids, linked contract ids, PandaDoc references from signed contracts |
| Payment matching webhook | inbound payment notification | /api/webhooks/payment | PARENTS.Parents Payments + PARENTS.Active Contracts | read + write | live with signed webhook verification and duplicate-safe receipt reconciliation; invoice linkage now updates the shared payment ledgers | payment receipt table, contract economics, webhook secret |
| Zapier data feed | Zapier reads project data | /api/zapier/data | clients/doulas/contracts/appointments/invoices | read | partial, some TODOs remain | tables for each requested entity |
| Zapier inbound sync | Zapier pushes action payloads | /api/webhooks/zapier | various tables via handlers | write | security hardened, business handlers still partial | matching action/table contracts |
| Admin stats | admin dashboard summary | /api/admin/stats | clients + doulas + contracts | read | partially wired | enough real records to replace mock stats |
| Product/content resources | family favorites/resources | product fetchers | PRODUCTS.amazon products | read | wired | product rows and categories |
| Blog content | marketing blog and CMS | CMS/blog APIs | MARKETING.Blog Posts | read + write | base now recognized, field mapping still needs refinement | usable content model, publish fields |
| Newsletter signups | marketing signup capture | future newsletter write path | MARKETING.Newsletter Signups | write | base now recognized, no app write path yet | name/email fields and automation trigger |
3. Current project-side Airtable dependencies
Core Airtable module
Primary file:
airtable.ts
What it currently owns:
- base selection
- table selection
- field mappers for
Client,Doula,Contract,Product - generic CRUD wrappers
- filter builders
- duplicate detection for parent intake
What it does not fully own yet:
- explicit Airtable availability/time-off tables
- live PandaDoc credentials, template activation, and production webhook registration
Specialized Airtable mapping layer
Parent intake mapper:
parent-intake.ts
This is now the canonical public intake field contract. It must match the live Airtable field names exactly.
Routes that rely directly on Airtable availability
| Route | Read/write | Airtable fallback behavior |
|---|---|---|
| read + write | read falls back to mock; parent intake write requires Airtable |
| read + write | read fallback exists; write requires Airtable |
| read + write | read fallback exists; write requires Airtable |
| read + write | read fallback exists; write requires Airtable |
| read + write | read fallback exists; write requires Airtable |
| read + write | read fallback exists; write requires Airtable |
| read + write | live Airtable-backed receipt and admin-ledger views |
| read + write | live Airtable-backed receipt updates and admin payout-state updates |
| read + write | live Airtable-backed interview CRUD |
| read + write | live Airtable-backed interview CRUD |
| read + write | live Airtable-backed invoice create/list endpoint |
| read + write | live Airtable-backed invoice detail/update endpoint |
| read | uses Airtable when configured |
| read | partial Airtable coverage with TODOs |
| read + write side effects | signature-verified webhook path with idempotent receipt reconciliation against Parents Payments and Active Contracts |
4. What must exist inside Airtable for the next implementation wave
Launch-critical cutover set
| Needed for | Base | Table | Must exist before cutover? | Notes |
|---|---|---|---|---|
| Parent intake write | PARENTS | Parent Intake Forms | yes | field names must match mapper in parent-intake.ts |
| Parent follow-up automation | PARENTS | automation on Parent Intake Forms | yes | sends confirmation + account-create prompt |
| Doula application write | DOULAS | TBC Doula Database | yes | must support public application field set |
| Doula follow-up automation | DOULAS | automation on TBC Doula Database | yes | sends confirmation + account-create prompt |
| Contract workflow | PARENTS | Active Contracts | yes | already partially wired |
| Match responses | PARENTS | Parent-Doula Matches | yes for WORK-220 | live app path now reads/writes here via /api/matches; first-class response fields now exist, and app metadata is still stored in Notes as structured TBC_MATCH_META payload |
| Interviews | PARENTS | Interview Status | yes for WORK-286 / WORK-221 | table exists, field mapping + app contract still needed |
| Parent-side payments | PARENTS | Parents Payments | yes for real reconciliation | live app mapping now persists client payment receipts |
| Admin-side payments | ADMIN | Admin Payments | yes for finance ops | live app mapping now persists payout state and bookkeeping metadata |
| Invoices | ADMIN | Invoices | yes | live Airtable-backed payout invoice table with PandaDoc IDs sourced from Active Contracts |
| Doula availability | DOULAS | TBC Doula Database | yes | live app mapping persists Interview Availability JSON and Interview Time Off JSON directly on the doula record |
Airtable automations that the app expects or will expect
| Automation | Trigger | Current app dependency | Owner |
|---|---|---|---|
| Parent intake follow-up | new parent intake record | marketing intake success flow assumes Airtable sends confirmation + next-step email | Airtable |
| Doula application follow-up | new doula application record | marketing doula application success flow assumes Airtable sends confirmation + next-step email | Airtable |
| Requested doula unavailable | match response marks requested doula unavailable | /api/matches owns the single notification path and stamps the Airtable match record so duplicate sends are blocked | App + Airtable |
| Account invite / activation handoff | approved intake/application state change | future Clerk re-enable depends on this linkage | Airtable + Clerk |
| Interview sync | appointment created/rescheduled/cancelled | future Google Calendar / Meet path | Airtable + Google |
| Payment reconciliation follow-up | matched receipt or duplicate-safe retry result | admin/payment visibility and notifications | Airtable + Plaid/Zapier |
5. Current blockers and drift
| Area | Current blocker | Consequence |
|---|---|---|
| Parent intake | auth is fixed, real write path still needs live submit verification | WORK-218 is no longer blocked by credentials, only by end-to-end validation |
| Doula application | app path is wired; live create verification is still intentionally controlled | WORK-219 code path is complete, but production validation should respect active webhook side effects |
| Match responses | app mapping is now live in /api/matches | WORK-220 is implemented; client matches and doula availability now share Airtable-backed state |
| Interviews | Interview Status is the canonical shared interview table | WORK-286 is implemented; booking, reschedule, and cancellation now persist through /api/appointments |
| Payments/invoices | payment ledgers, receipt reconciliation, invoice persistence, and PandaDoc send/status/webhook scaffolding are in code; live PandaDoc activation is still pending | WORK-364, WORK-293, WORK-367, WORK-368, and WORK-374 are implemented; WORK-375 remains open |
| Docs | still describes an older model | easy to wire the wrong tables/fields if used blindly |
6. Active Airtable automations and live-side-effect risk
Parent Database
Confirmed active automations:
Parent Sign Up CreatedPostpartum Check-In!First Birthday EmailFinal Payment ReminderEmail response to referral formParent - Hired to ContractNew Contracts to Bookkeeping SpreadsheetPost to AvailabilityClosed Contracts
Key confirmed trigger:
Parent Sign Up Created- trigger: record created in
Parent Intake Forms - actions: sends email
- branch logic:
Kaiser Benefit?
- trigger: record created in
Risk implication:
- a real insert into
Parent Intake Formsis not a harmless test write - it can trigger Gmail, Slack, Google Sheets, and downstream contract/availability workflows
Doula Database
Confirmed active automations:
Directory Doula Confirmation Email With Payment Link[TBC Doula Database] Send Webhook when Record is Updated[Doula Directory] Send Webhook when Record is Created[TBC Doula Database] Send Webhook when Record is Created copy
Confirmed inactive automations:
New Doula Sign Up Email Confirmation With Doula Profile FormUpdate Record via Form V2[Join The Team Form Submission] Send Webhook when Record is Created ...Yurii
Risk implication:
- writes to
TBC Doula DatabaseandProvider Directorycan trigger webhook side effects - the public doula application destination table still needs to be chosen explicitly before any live submit test
Family Favorites
Confirmed active automations:
Send Webhook [Record Updated]Send Webhook [Record Created]
Risk implication:
- product/content table edits can fire webhooks immediately
Marketing
No automation screenshots were provided for Marketing.
Current assumption:
- treat
Marketingas potentially side-effectful until explicitly verified otherwise
Payments / TBC Admin Database
- user confirmed the old
Paymentsbase was deleted - any screenshots of that base should be treated as stale
TBC Admin Databasenow exists withAdmin Payments- no active automation screenshots were provided yet for
TBC Admin Database
7. Safe testing rules for Airtable cutover work
These are mandatory until the production automations are fully cataloged.
- Do not run live create/update tests against
Parent Intake Formswhile create-trigger automations are enabled unless the user explicitly approves the side effects. - Do not assume a "test record" is safe. A single insert can trigger Gmail, Slack, Google Sheets, and contract/availability workflows.
- Do not run any delete operations against Airtable production bases.
- Prefer one of these testing modes, in order:
- sandbox/test base copy
- temporary automation disablement during a controlled test
- production write with explicit operator approval and known side effects
- Any production write test must use:
- a clearly labeled test identity
- a unique email
- a single insert-only action
- no cleanup delete unless explicitly approved
8. Canonical table-role decisions
These need explicit decisions before more write paths are wired.
Doula application destination
Current ambiguity:
TBC Doula Databasehas a form calledDoula Profile FormProvider Directoryhas a form view calledDoula Intake Form
Decision required:
- which table is the canonical destination for public doula applications?
Recommended default:
TBC Doula Databasefor internal/application recordsProvider Directoryfor public/provider listing records only- this is now the live app behavior for approval, directory publication, and mentorship
Payments domain
Canonical model:
- old
Paymentsbase is deleted TBC Admin Databaseexists withAdmin PaymentsParent DatabasecontainsParents PaymentsActive Contractsis the canonical contract-economics record once PandaDoc metadata is ingested- PandaDoc send/status/webhook scaffolding now exists in the app code, but live activation still depends on production credentials and webhook registration
Parents Paymentsis the canonical external money-in ledgerAdmin Paymentsis the canonical internal contract-level finance and payout ledger
Relationship model:
- one
Active Contractsrecord exists per signed PandaDoc contract - one contract can have many
Parents Paymentsrows - one contract should have one
Admin Paymentsrow
Field ownership:
Active Contracts- total contract value
- deposit due
- balance due
- referral fee percent
- referral fee amount
- doula payout obligation
- Kaiser billing owner / handling
- PandaDoc reference
Parents Payments- parent/client
- contract
- payment stage (
deposit,final,other) - gross amount received
- payment method / external reference
- paid date
- receipt status
Admin Payments- contract
- total received to date
- remaining due
- referral fee captured
- doula payout due
- payout status / paid date / payout method
- bookkeeping notes
Operational rule:
- client-facing pages must not use
Admin Paymentsas the source of truth for money received - admin payout and referral-fee state must not derive only from
Parents Paymentswithout contract context
9. Connection map
flowchart LR
subgraph Marketing["Marketing Site"]
PI["/parent-intake-form"]
DS["/doula-sign-up"]
DL["/doulas"]
end
subgraph Portals["Client / Doula / Admin Portals"]
CI["Client portal"]
DP["Doula portal"]
AP["Admin portal"]
end
subgraph App["Next.js API + mapping layer"]
APIClients["/api/clients"]
APIDoulas["/api/doulas"]
APIContracts["/api/contracts"]
APIPayments["/api/payments"]
APIAppointments["/api/appointments"]
APIStats["/api/admin/stats"]
APIWebhookPayment["/api/webhooks/payment"]
APIWebhookZapier["/api/webhooks/zapier"]
AirtableLib["lib/airtable.ts"]
ParentMapper["lib/parent-intake.ts"]
end
subgraph Airtable["Airtable"]
ParentsBase["Parent Database"]
DoulasBase["Doula Database"]
ProductsBase["Family Favorites base"]
MarketingBase["Marketing base"]
AdminBase["TBC Admin Database"]
MissingOps["Missing ops tables\n(Invoices / Availability / Time Off)"]
end
subgraph Automation["Automations and external systems"]
AirtableAutos["Airtable automations"]
Zapier["Zapier"]
Plaid["Plaid"]
Clerk["Clerk"]
Google["Google Calendar / Meet"]
end
PI --> APIClients
DS --> APIDoulas
DL --> APIDoulas
CI --> APIClients
DP --> APIDoulas
AP --> APIStats
AP --> APIContracts
AP --> APIPayments
CI --> APIAppointments
DP --> APIAppointments
APIClients --> ParentMapper
ParentMapper --> AirtableLib
APIDoulas --> AirtableLib
APIContracts --> AirtableLib
APIPayments --> AirtableLib
APIAppointments --> AirtableLib
APIStats --> AirtableLib
AirtableLib --> ParentsBase
AirtableLib --> DoulasBase
AirtableLib --> ProductsBase
AirtableLib --> MarketingBase
AirtableLib --> AdminBase
AirtableLib -. required next .-> MissingOps
ParentsBase --> AirtableAutos
DoulasBase --> AirtableAutos
AirtableAutos --> Clerk
AirtableAutos --> Google
Plaid --> APIWebhookPayment
Zapier --> APIWebhookPayment
Zapier --> APIWebhookZapier
APIWebhookPayment --> APIPayments
APIWebhookPayment --> APIContracts
APIWebhookZapier --> AirtableLib
10. Immediate execution order for the Airtable call
| Order | Work item | Why first |
|---|---|---|
| 1 | add MARKETING and ADMIN base support to the Airtable layer | keeps code aligned with the real workspace |
| 2 | catalog active automations and live side effects by base | prevents accidental production-triggered writes |
| 3 | confirm the live field contract for TBC Doula Database so public submissions stay compatible with active automations | keeps WORK-219 durable |
| 4 | implement the canonical Parents Payments + Admin Payments contract-ledger model in app code | completed |
| 5 | validate Parent Intake Forms fields against | keeps WORK-218 implementation honest |
| 6 | review whether Parent-Doula Matches needs first-class fields for response timestamps and notification markers or whether Notes metadata is sufficient | determines whether WORK-220 needs a cleanup pass later |
| 7 | map Interview Status into the app’s interview model | unlocks WORK-286 and later WORK-221 |
| 8 | run one controlled live write only after automation risk is accepted or neutralized | closes WORK-218 safely |
11. Hard truths
- The current codebase is not built around one single Airtable base. It is already a multi-base model.
- Parent intake is the closest public lead flow to production. Doula application is next. Matching, interviews, and payment ledgers are now Airtable-backed.
- Payments are no longer structurally ambiguous. The remaining work is invoice approval workflow polish plus live PandaDoc activation, not ledger ownership, invoice persistence, or receipt dedupe.
- A live Airtable write is not equivalent to a harmless database insert. In this workspace, it can trigger real outbound automations immediately.
- If the call tries to redesign the entire Airtable architecture from scratch, you will lose time. The highest-return move is targeted cutover of the next four missing workflows.