Airtable-backed approval form gated behind Airtable OAuth sign-in.
/auth/login, which first shows an interstitial
"Login with Airtable" page; clicking the button (?proceed=1) then redirects to
https://airtable.com/oauth2/v1/authorize.user.email:read). It is used
only to verify who signed in and to resolve their email via /v0/meta/whoami.AIRTABLE_API_KEY env var (a personal access
token), NOT the user's OAuth token. This is intentional — sign-in is a gate,
and doesn't require approvers to be base collaborators. Don't "fix" this by
switching base calls to the OAuth token.oauth_sessions table; the session id is an
httpOnly airtable_session cookie. Access tokens are refreshed on demand
(refresh_token grant) so sessions last up to ~30 days.GET /auth/login — starts OAuth, sets CSRF oauth_state cookieGET /auth/callback — exchanges code, verifies state + whoami, creates sessionPOST /auth/logout — deletes session, clears cookieAIRTABLE_CLIENT_ID — required; from the Airtable OAuth integrationAIRTABLE_CLIENT_SECRET — optional; only if one was generatedAIRTABLE_API_KEY — required; personal access token for the baseRegister the OAuth callback URL in the integration (in Airtable → Builder Hub →
OAuth integrations):
https://airtable-approval.val.run/auth/callback
A full sign-in round trip (Airtable login → callback → session redirect) must be
tested in a real browser; fetch_val_endpoint cannot complete it.