Connect Supabase to Fondoo

Live5 min readUpdated

If your app runs on Supabase, Fondoo can write each customer's paid plan into a table in your database, so your app knows who has access. It can also watch your Supabase Auth users and count new signups as conversions in Fondoo analytics.

What Fondoo can do with it

  • Paid-access sync (plan sync). When a customer's access changes in Fondoo (a purchase, a cancellation), Fondoo upserts one row in your table through the Supabase Data API: POST /rest/v1/<table>?on_conflict=<keyColumn>. The row holds the customer key, the active plan (or empty when nothing is active) and a status such as active or canceled. Fondoo recomputes the state at delivery time, so a late retry cannot overwrite a newer cancellation.
  • Signup sync (optional). With signupSyncEnabled: true, Fondoo reads your Auth users through the admin API (GET /auth/v1/admin/users, 100 per page, one page every 5 minutes). Each new user becomes a signup conversion. Fondoo stores only the Supabase user ID and a hashed email.
  • Health checks. get_connection_health lists the Auth users as a probe and reports ok or error for supabase:<mode>.

Related operations: connect_backend (owner only), set_plan_sync_mapping and test_plan_sync (scope payments:write; in live mode these are money-risk, so agents need owner approval), get_plan_sync_status (payments:read) and retry_payment_delivery (owner).

Before you start

  • A Supabase project on Supabase's hosted platform. Fondoo only accepts a project URL like https://abcdefghijklmnop.supabase.co. Custom domains and self-hosted Supabase are rejected.
  • Supabase's Free plan allows 2 active projects and pauses a project after one week without activity. Pro starts at $25 per month (pricing). A paused project will make syncs fail.
  • Fondoo payments set up for your site. Live mode needs a paid Fondoo workspace plan; otherwise you connect test mode.
  • A table for the plan data (below).

Step by step: get your credentials

  1. In the Supabase Dashboard open your project and click Connect. Copy the Project URL (https://<ref>.supabase.co). This is url.
  2. Go to Settings → API Keys (Supabase). This is serviceKey. Choose one:
    • Legacy service_role key (a long JWT) on the legacy keys tab. Fondoo sends the key in both the apikey header and Authorization: Bearer, which is how this key is designed to be used.
    • Secret key (sb_secret_...). Supabase recommends these, but its docs say to send them on the apikey header, not Authorization: Bearer. Fondoo sends both. Whether the Data API and Auth admin API accept that may differ for your account. If you use one, run test_plan_sync and get_connection_health right away, and fall back to the legacy key if they fail. Create a dedicated secret key named for Fondoo so you can revoke it alone.
  3. Create the table in the SQL Editor. The default mapping is table foundu_subscriptions, key column email, columns plan and status:
create table public.foundu_subscriptions (
  email text primary key,
  plan text,
  status text
);
alter table public.foundu_subscriptions enable row level security;
grant select, insert, update on table public.foundu_subscriptions to service_role;

The key column needs a unique or primary key constraint, because Fondoo upserts on it. The service role bypasses Row Level Security, but table grants still apply. Supabase is moving to a default where new tables are not exposed automatically, so keep the explicit grant (Supabase). The table must be in a schema exposed by the Data API (public by default).

Both values are full admin credentials for your project. Never put them in browser code or chat.

Connect it in Fondoo

a. In the dashboard. Under Connections → Available, Connect Supabase gives a Connect securely link with setup steps. The dashboard has no form for the key. Use REST below.

b. With REST (recommended). connect_backend requires the owner scope, and there is no secure paste page for it, so the safest path is to run it yourself with an owner-scoped Fondoo API key:

curl -X POST https://api.getfondoo.com/v1/ops/connect_backend \
  -H "Authorization: Bearer $FONDOO_OWNER_KEY" -H "Content-Type: application/json" \
  -d '{"siteId":"YOUR-SITE-ID","provider":"supabase","mode":"test","signupSyncEnabled":true,
       "credential":{"url":"https://abcdefghijklmnop.supabase.co","serviceKey":"YOUR-SERVICE-KEY"}}'

Leave out mode to use your workspace default (live on a paid plan, test otherwise). Repeat with "mode":"live" for live. One backend per site per mode; a new call replaces the old one.

c. By asking your agent. Agents without the owner scope get "Owner scope required". Ask for the preparation, not the secret: "Prepare a dry run of connect_backend for Supabase on my site and set the plan sync mapping to my table subscriptions keyed by user_id."

set_plan_sync_mapping({siteId, mapping: {table: "subscriptions", keyColumn: "user_id",
  planColumn: "plan", statusColumn: "status", identity: "externalUserId", target: "table"}})

Use identity: "externalUserId" only if your checkouts pass the Supabase user ID as externalUserId; otherwise keep email. For Supabase, target must be table.

Optional: set_provider({siteId, capability: "backend", provider: "supabase"}) (owner). If you set a backend provider, it must match the connected one, or syncs stop with "Selected backend connection is missing".

Test that it works

  1. get_plan_sync_status({siteId, mode: "test"}) shows connected: true, provider: "supabase" and your mapping.
  2. Make a test purchase, or run test_plan_sync({siteId, mode: "test", email: "buyer@your-domain"}) for an existing customer. It never invents access.
  3. Check the table in Supabase. get_plan_sync_status lists recent deliveries and their status.
  4. With signup sync on, get_connection_health({siteId}) should show supabase:test as ok.

Troubleshooting

  • "Use a hosted Supabase project origin": send only https://<ref>.supabase.co, no path or trailing text.
  • "Supabase requires a URL and service key": both url and serviceKey are required.
  • Deliveries stay pending or become dead_letter: the table, columns, grant or unique key is missing, the key is wrong, or the project is paused. After 5 failed attempts Fondoo raises an alert. Fix it, then retry_payment_delivery.
  • "Live payments require a paid workspace plan": connect with "mode":"test", or upgrade.
  • Health shows error / "Signup sync failed": the key cannot read Auth users. Use the service role or secret key, not the publishable or anon key.
  • "Mapping columns must differ": key, plan and status columns need different names.

Limits, data and security

  • Signup sync reads 100 users per run, every 5 minutes, on servers with CONNECT_JOBS_ENABLED=true. A project with 10,000 users needs about 100 runs for the first pass. The first pass counts existing users as signups at sync time, without backdating.
  • Changing the project URL or provider clears the list of users already seen.
  • Fondoo encrypts the URL and key with AES-256-GCM, bound to the site, mode and provider. No operation returns them.
  • To rotate, create a new key in Supabase, run connect_backend again, then revoke the old one. Note that this resets the signup cursor.
  • There is no disconnect operation for backends. To stop access, revoke or deactivate the key in Settings → API Keys. To stop only signup sync, call connect_backend again with signupSyncEnabled: false.
  • No webhooks are used. Fondoo writes to Supabase; Supabase does not call Fondoo.