Connect Clerk

Use Clerk user and organization metadata as your access source instead of Postgres.

Use Clerk as your access source instead of connecting a database when your app stores plan, premium, and trial in Clerk user or organization metadata rather than a Postgres table.

You still connect Stripe for billing — Clerk only replaces the database step. Checks, access incidents, and the Access Ledger all work exactly the same.

Before you start

  • Your app stores plan, premium, or trial in Clerk user (or organization) metadata — not a Postgres table. If it’s in Postgres instead, connect a database rather than Clerk.
  • A Clerk Backend API secret key from Clerk Dashboard → API keys → Secret keyssk_test_ for your development instance, sk_live_ for production.
  • Stripe still connected on step 2 of onboarding. Clerk only replaces the database step, not billing.
  • Admin role on the ParityRail project — connecting Clerk requires admin.
  • The Stripe customer id stored somewhere in Clerk user metadata — that’s what ParityRail matches on.
Connect a Postgres database or Clerk, not both. Pick whichever one actually holds the plan, premium flag, and trial your app reads.

Connect Clerk to ParityRail

  1. In the Clerk Dashboard, open API keys → Secret keys and copy your secret key (starts with sk_).
  2. In ParityRail onboarding, go to step 3 (Database) and click the Clerktab in the source toggle — the tablist labeled “Access-state source,” with options “Postgres / Supabase” and “Clerk.”
  3. Paste the key into the Clerk Backend API secret key field (placeholder sk_test_…).
  4. Click Test & connect. The button reads “Testing & connecting…” while ParityRail verifies the key by calling Clerk’s GET /users?limit=1 before saving it.
  5. Step 4 (Identity mapping)then shows “Customer matching is automatic” — just click Continue. Clerk matches each user to a Stripe customer by the metadata field you set next.
  6. Step 6 (Access mapping)asks “Which Clerk fields say who has paid access?” ParityRail samples your recent users and offers the metadata keys it finds as options. Map at minimum the Stripe customer id field and either a plan or premium field, then click Save and continue.
ParityRail only lists and retrieves users and organizations — it never writes to Clerk. It can’t create a narrower-scope key, so treat this one like any other credential and rotate it in Clerk if it ever leaks.

Field paths, ready to paste

The secret key you paste in step 2 above looks like this — copy the shape, not the placeholder:

sk_test_<...>   secret key for your development instance
sk_live_<...>   secret key for production

Each mapped field on step 6 is a path shaped <container>.<key> — for example, the required Stripe customer id field:

public_metadata.stripe_customer_id

Other fields you can map follow the same shape:

public_metadata.plan
public_metadata.is_premium
public_metadata.trial_ends_at
public_metadata.entitlements

The container is one of:

  • public_metadata
  • private_metadata
  • unsafe_metadata
FieldExample pathRequiredWhy
Stripe customer idpublic_metadata.stripe_customer_idYesMatches a Clerk user or organization to its Stripe customer — required to reconcile.
Planpublic_metadata.planOptionalThe plan value your app stores, compared against the Stripe subscription's plan.
Premium flagpublic_metadata.is_premiumOptionalA truthy flag marking paid access (true/1/yes/on/premium/active all read as true).
Trial endpublic_metadata.trial_ends_atOptionalWhen the trial ends, as an ISO string or epoch, compared against the Stripe trial.
Entitlementspublic_metadata.entitlementsOptionalAn object of { featureKey: boolean }; its keys become the subject's entitlements.

On step 6, ParityRail samples your users (and organizations, if enabled) and suggests the metadata keys it finds — you usually pick from a dropdown instead of typing paths by hand. Organization billing works too: enable the organizations section and map the org metadata field that holds the Stripe customer id and, optionally, the plan.

Verify it worked

  • Connecting succeeds with a toast reading Clerk connected — <masked label>, plus a green Clerk connected card on step 3 showing the masked key label (for example sk_test_…abcd).
  • Step 4 renders the Customer matching is automaticpanel — a wand icon plus “Matched automatically for Clerk” — instead of the SQL table/column pickers. The left-rail hint for step 4 also changes to “Matched automatically.”
  • On step 6, the field dropdowns are populated with your sampled metadata keys, shown as public_metadata.<key>. Seeing real keys there confirms ParityRail could read your Clerk metadata.

Troubleshooting

You seeWhat it meansFix
Clerk rejected the secret key (HTTP 401)…Wrong or revoked key, or you pasted a publishable key (pk_) instead of a secret key.Recopy the Secret key from Clerk Dashboard → API keys → Secret keys.
Enter a Clerk Backend API secret key (sk_test_… or sk_live_…)The value you pasted doesn't match the sk_ pattern.Paste the full secret key exactly as Clerk shows it — no extra spaces or truncation.
No metadata keys were found on your Clerk users.None of the sampled users have any metadata set yet (shown on step 6).Store the Stripe customer id (and plan/premium) in a user’s publicMetadata or privateMetadata in Clerk, then click Retry — ParityRail re-samples your recent users.
Clerk rate limit hit (HTTP 429)…Too many requests hit Clerk's Backend API in a short window.Wait a moment, then retry — ParityRail already backs off automatically before surfacing this.
Expecting ParityRail to fix Clerk metadata automaticallyClerk repairs are guided, not automated — ParityRail reads Clerk read-only and never writes metadata back.Apply the exact user/field/value change the access incident shows, in Clerk, then re-run the check to verify it took effect.

Repairs are guided, not automated

For a Postgres source, an approved repair writes a column directly using a narrow repair role. Clerk is different: ParityRail reads it read-only and does not write metadata back.

When it finds an access incident on a Clerk-sourced project, it files the incident with full evidence and the exact metadata change to make — which user or organization, which field, and the expected value.

You apply that change in Clerk (or your own admin tooling), then re-run the check to verify it took effect.

Automated Clerk metadata writes are on the roadmap. Until then, Clerk projects run detect-and-guide: every incident carries a before/after so the fix is a copy-and-paste away, and re-verification confirms the promise once you’ve applied it.