Skip to content

Client libraries

Tested with: supabase-js 2 · supabase-py 2 · Databasezy API v1

The project endpoint speaks the same HTTP APIs as Supabase for Auth (/auth/v1) and the Data API (/rest/v1, /graphql/v1), and accepts the key the same way (apikey header plus Authorization: Bearer). So the Supabase client libraries work as they are: give them your project’s endpoint and a publishable key.

shell
npm install @supabase/supabase-js
src/lib/db.ts
import { createClient } from "@supabase/supabase-js";
import type { Database } from "./database.types"; // zb gen types > src/lib/database.types.ts
export const supabase = createClient<Database>(
"https://<ref>.us-east.databasezy.com:8443",
import.meta.env.PUBLIC_DATABASEZY_PUBLISHABLE_KEY, // zbp_...
);

The constructor argument some libraries call anonKey or supabaseKey is your publishable key. Never ship a secret key (zbs_...) in a client: it acts as service_role and bypasses row-level security.

@supabase/ssr keeps the user’s session in cookies for Next.js, SvelteKit, Remix and Astro. Pass the same endpoint and publishable key to createServerClient and createBrowserClient; nothing else changes. The PKCE code exchange, token-hash email links and CORS for the browser client are served by the project endpoint; see Server-side auth for each framework.

lib/server.ts
import { createServerClient } from "@supabase/ssr";
import { cookies } from "next/headers";
export async function serverClient() {
const store = await cookies();
return createServerClient(process.env.DATABASEZY_URL!, process.env.DATABASEZY_PUBLISHABLE_KEY!, {
cookies: {
getAll: () => store.getAll(),
setAll: (list) => list.forEach(({ name, value, options }) => store.set(name, value, options)),
},
});
}
Supabase client calls against the project endpoint, with status
Client call Path Status
auth.signUp , signInWithPassword , signInWithOtp , verifyOtp , resetPasswordForEmail , updateUser /auth/v1 Live
refreshSession , getUser , signOut /auth/v1 Live
auth.signInWithOAuth /auth/v1 Coming soon
auth.mfa.* /auth/v1 Coming soon
auth.signInWithSSO /auth/v1 Coming soon
auth.signInAnonymously /auth/v1 Coming soon
from(table).select / insert / update / upsert / delete , rpc /rest/v1 Live
GraphQL clients /graphql/v1 Live
storage.from(bucket).* /storage/v1 Coming soon
functions.invoke /functions/v1 Coming soon
channel(...) broadcast /realtime/v1 Coming soon
channel(...) presence /realtime/v1 Coming soon
channel(...) postgres_changes /realtime/v1 Coming soon

scripts/sdk-compat/run.py runs each library’s basic calls against a live project: sign in, refresh and read the user, insert and select a row under row-level security (another user can neither see it nor insert as its owner), upload, download and sign a file in a private bucket (another user cannot download it), broadcast and receive Postgres changes (another user does not get them), invoke a function, and sign out (the refresh token stops working). It runs weekly in CI on a disposable project; run it yourself against an existing project with your keys in the environment:

shell
export DATABASEZY_URL=https://<ref>.us-east.databasezy.com:8443
export DATABASEZY_PUBLISHABLE_KEY=zbp_... DATABASEZY_SECRET_KEY=zbs_... DATABASEZY_INSTANCE=<primary instance id>
python3 scripts/sdk-compat/run.py --install # --only js,ssr,python --skip realtime --json report.json

The secret key only prepares the fixture (a table with a policy, a private bucket, two throwaway users); the libraries get the publishable key, and every line they print is redacted.

LibraryAuthData API + RLSStorageRealtimeFunctionsHow it is checked
supabase-js 2yesyesyesyesyesrun.py --only js (Node), CI weekly
@supabase/ssryes (cookies, PKCE)yes---run.py --only ssr (Node), CI weekly
supabase-py 2yesyesyesyesyesrun.py --only python, CI weekly
supabase-flutteryesyesyesyesyesrun.py --only flutter: the Dart client inside supabase_flutter, needs the Dart SDK
supabase-swiftyesyesyesnot in the smokenot in the smokesmoke app in scripts/sdk-compat/swift, run by hand on a Mac
supabase-ktyesyesyesnot in the smokenot in the smokesmoke app in scripts/sdk-compat/kotlin, run by hand with Gradle

Known gaps: passkeys and WebAuthn factors (auth.mfa with webauthn, auth.passkey.*), reauthenticate(), and SSO providers managed through auth.admin (use the management API). The full auth-js list is in the Supabase compatibility notes.

@databasezy/js is a thin wrapper around supabase-js that takes your project ref and region instead of a URL, refuses a secret key in a browser (and an endpoint that is not https), and tags requests with its version:

src/lib/db.ts
import { createClient } from "@databasezy/js";
export const db = createClient({ ref: "abcdefghijklmnopqrst", region: "us-east" }, import.meta.env.PUBLIC_DATABASEZY_PUBLISHABLE_KEY);

Without a region the endpoint is the production one, https://<ref>.databasezy.app; a full URL works too. @databasezy/js/ssr wraps createServerClient and createBrowserClient the same way (cookie methods getAll / setAll).

The Supabase compatibility notes list the differences that remain.

zb gen types writes the Database type supabase-js uses, from the schemas your Data API exposes:

shell
zb gen types --output src/lib/database.types.ts

See zb gen types for the options (--schema, --secret-key, --db-url).