API

Your users, their login, their rows

Point a workspace at your Auth0, Clerk or Firebase and your end-users call the generated REST API with their own identities — row-level security narrows every query to their rows.

SchemaStack team20 Aug 2026Verified working · 20 Aug 2026Docs

Every workspace gets a generated REST API. The obvious way to use it is server-side, with a workspace API key. The less obvious, more interesting way: let your application's end-users call it directly, signed in as themselves — without a SchemaStack account existing for any of them.

The trick is that you almost certainly already run an identity provider. Point the workspace at it:

  1. Open Settings → Identity Provider in the workspace.
  2. Set the issuer URL — the iss claim your Auth0/Clerk/Firebase tokens carry. The signing keys are auto-discovered from the provider's OIDC metadata (or set the JWKS URI explicitly).
  3. Optionally pin an audience, choose read-only or read-write, enable.

From then on, a request like this works with the JWT your app already has in hand:

GET /api/v1/acme-corp/sales/Order
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...   ← your provider's token, not ours

SchemaStack reads the token's issuer, validates the signature against your provider's published keys, checks expiry and audience — and serves the request.

Row-level security is where it gets real

Authenticated is not the same as authorised to see everything. RLS rules map a column to a JWT claim — customer_id to sub, tenant to org_id — and from then on every query is narrowed automatically:

Your app's usersigns in as usualJWTYour IdPAuth0 · Clerk · FirebaseWorkspace APIvalidated via JWKSRLS filtercolumn = claimsomeone else’s row — invisible, 404 by idcustomer_id = auth0|… — visiblecustomer_id = auth0|… — visiblesomeone else’s row — invisible, 404 by idThe same table,as this user sees it →
Your user signs in with your identity provider; SchemaStack validates the token and row-level security narrows every query to their rows.

The enforcement is thorough on purpose, because half-enforced row security is a vulnerability with extra steps:

OperationBehaviour
List / queryWHERE clause added — only matching rows exist
Read by idsomeone else's row is a 404, not a 403 — its existence isn't confirmed
Createthe RLS column is set from the token's claim; sending a different value is rejected
Update / deleteonly your own rows, and the RLS column can't be rewritten to someone else's

That last table is the difference between "we filter the list view" and actual multi-tenant isolation on one table.

What this replaces

The backend-for-frontend you were going to write: the thin API whose only job is "take the user's token, look up their id, add WHERE customer_id = ? to everything." That service — its hosting, its deploys, its drift from the schema — stops needing to exist for the CRUD portion of your app.

What it doesn't do (yet)

  • RLS applies to external-IdP tokens only. API keys and SchemaStack's own OAuth tokens are workspace-owner credentials — they bypass RLS and see all data, by design. Don't hand those to end-users.
  • One identity provider per workspace, with one workspace-wide permission level (read-only or read-write) for all external users — no per-user roles yet.
  • Rules map one column per view to one claim — no compound expressions like org_id AND region.
  • Index the RLS column. The filter is added to every query; without an index that's a table scan every time. (This is in the docs, but it's the kind of advice people find out about later.)

Setup, claim requirements and per-provider notes are in the external identity providers guide.

Verified 20 Aug 2026: external-IdP token validation suite (13 cases — signature, issuer, audience, expiry) and the row-level-security filter suite (16 cases) run green against provider-style signed tokens.