The official C# client for Supabase. This is a monorepo: the top-level
Supabase client and every service package it builds on live here, under packages/.
Use the Supabase meta-package for the full client, or reference an individual service package
(Auth, Postgrest, Storage, Realtime, Functions) on its own.
| Package | NuGet | Source | Purpose |
|---|---|---|---|
| Supabase | packages/Supabase | The unified client that wires the services below together. Start here. | |
| Supabase.Gotrue | packages/Gotrue | Authentication — email/password, OAuth, SSO, magic links. | |
| Supabase.Postgrest | packages/Postgrest | Query your database through the auto-generated REST API, with LINQ. | |
| Supabase.Storage | packages/Storage | File storage — upload, download, signed URLs, buckets. | |
| Supabase.Realtime | packages/Realtime | Realtime — Postgres changes, Broadcast, and Presence over websockets. | |
| Supabase.Functions | packages/Functions | Invoke Edge Functions. | |
| Supabase.Core | packages/Core | Shared primitives used by the packages above. Rarely referenced directly. |
Every package targets .NET Standard 2.1, so it runs on .NET Core 3.0+ / .NET 5+, recent MAUI, Xamarin, and Unity. See the wiki for platform-specific guides (Unity, desktop/mobile, server-side).
dotnet add package SupabaseusingSupabase;varurl=Environment.GetEnvironmentVariable("SUPABASE_URL");varkey=Environment.GetEnvironmentVariable("SUPABASE_KEY");varoptions=newSupabaseOptions{AutoRefreshToken=true,AutoConnectRealtime=true};varsupabase=newClient(url,key,options);awaitsupabase.InitializeAsync();// Authawaitsupabase.Auth.SignIn("user@example.com","password");// Databasevarmovies=awaitsupabase.From<Movie>().Get();// Storageawaitsupabase.Storage.From("avatars").Download("me.png",null);Each service is reached from the initialized client: supabase.Auth, supabase.From<T>() /
supabase.Rpc(...), supabase.Storage, supabase.Realtime, and supabase.Functions. For using a
single service on its own, see that package's README.
A note on keys: some APIs (user administration, bypassing RLS, etc.) require the
service_keyrather than the public/anon key. Never expose aservice_keyin client-side code, and use a separate client instance for service and user contexts.
The clients emit traces and metrics through System.Diagnostics, so you can wire them into
OpenTelemetry (or any ActivityListener / MeterListener) without taking a dependency on the
OpenTelemetry packages. Emission is zero-cost while nothing is listening, so it is always on and
stays silent until you subscribe.
Register every instrumented source at once with SupabaseDiagnostics.SourceNames — each client
shares one name between its ActivitySource and its Meter, so the same list works for tracing and
metrics:
usingOpenTelemetry.Metrics;usingOpenTelemetry.Trace;usingSupabase;builder.Services.AddOpenTelemetry().WithTracing(tracing =>tracing.AddSource(SupabaseDiagnostics.SourceNames.ToArray()).AddOtlpExporter()).WithMetrics(metrics =>metrics.AddMeter(SupabaseDiagnostics.SourceNames.ToArray()).AddOtlpExporter());This covers the Auth, Postgrest, Functions, and Storage clients (Realtime is not yet instrumented). URLs are recorded without their query string, and no token, credential, or payload is placed in a tag. Each package's README documents the specific spans and metrics it produces.
packages/
Supabase/ The unified client (NuGet: Supabase)
Gotrue/ Auth (NuGet: Supabase.Gotrue)
Postgrest/ Database (NuGet: Supabase.Postgrest)
Storage/ Storage (NuGet: Supabase.Storage)
Realtime/ Realtime (NuGet: Supabase.Realtime)
Functions/ Functions (NuGet: Supabase.Functions)
Core/ Shared (NuGet: Supabase.Core)
Each packages/<Name>/ holds the library project and its test project. Package metadata common to
every project (license, authors, repository) lives in Directory.Build.props;
dependency versions are managed centrally in Directory.Packages.props.
The SDK builds with the .NET SDK version pinned in global.json.
dotnet restore
dotnet build Supabase.sln --configuration Release
dotnet test Supabase.sln --configuration ReleaseSome test suites are end-to-end and need a local Supabase stack via the
Supabase CLI (supabase start, which requires Docker). The
Realtime suite additionally expects realtime-dev.localhost to resolve locally — add a hosts entry:
127.0.0.1 realtime-dev.localhost
Releases are automated with release-please. Commits
follow Conventional Commits; the changelog is generated in
CHANGELOG.md. For breaking changes and how to adapt to them across major
versions, see the migration guides.
Contributions are welcome — please open an issue to discuss substantial changes, then submit a PR.